AI Automation & Agents  

Track Twitter Mentions and Save to Airtable (Free Integration)

Abstract / Overview

  • Goal: Capture mentions of your handle on Twitter (X) and store clean records in Airtable without paying for the X API.

  • Approach: Use X email notifications for mentions, a Gmail label filter, and a Make.com scenario that parses each email and writes to Airtable. No scraping. No paid API.

  • Assumption: You will use Gmail, Make.com Free, and Airtable Free. You will not call the X API.

  • Fit. Personal brands and small projects that need light “Twitter monitor automation” with an “Airtable save”.

Outcomes

  • Structured table of mentions with Tweet ID, author, text, URL, and timestamp.

  • Deduplication and basic enrichment.

  • Optional Slack alert.

Conceptual Background

Mentions are tweets containing @yourhandle in the text or in a reply. X can email you when a new mention occurs. These emails contain the tweet URL and a text preview. Parsing that email yields the data you need.

Why email

  • Free and allowed by platform settings.

  • Works without X API access.

  • Reliable enough for personal volume.

System design

  • Trigger: Gmail watches incoming mention emails.

  • Parse: Extract tweet URL, Tweet ID, author handle, message snippet, and time.

  • Idempotency: Use the Tweet ID as a unique key to block duplicates.

  • Storage: Airtable table “Mentions” with typed fields.

  • Enrichment: Optional sentiment scoring and link unshortening.

  • Alert: Optional Slack notification.

Data model (Airtable “Mentions”)

  • TweetID (single line text, primary key candidate)

  • AuthorHandle (single line text)

  • AuthorName (single line text, optional)

  • Text (long text)

  • TweetURL (URL)

  • MentionedAt (date-time, created from email date)

  • Project (single select, optional)

  • Sentiment (single select: Positive | Neutral | Negative, optional)

  • SourceEmailID (single line text)

  • RawEmail (long text, optional for audit)

Idempotency

  • Create a formula field UniqueKey with CONCATENATE("tw_", TweetID).

  • Use it to prevent duplicates.

Step-by-Step Walkthrough

1) Prepare Airtable

  • Create base: Social Listening.

  • Create table: Mentions.

  • Add fields as listed above.

  • Add formula field UniqueKey = CONCATENATE("tw_", {TweetID}).

2) Turn on X email notifications

  • In X settings, enable email notifications for mentions.

  • Test by mentioning your handle from another account.

3) Create Gmail routing

  • Create label twitter-mentions.

  • Create a filter that matches the X-mentioned emails and applies the label. Use the sample query below.

  • Optional: forward to a parsing inbox. Not required for Make.

4) Make.com scenario (free)

Modules

  • Gmail > Watch emails. Trigger on label twitter-mentions.

  • Tools > Text parser or Code (JavaScript). Extract fields.

  • Airtable > Search records  UniqueKey to check duplicates.

  • Airtable > Create record only if not found.

  • Optional: Slack > Send message.

Mapping

  • Use the email’s HTML or plain text. Prefer HTML for stable links.

  • Extract the first URL matching https://twitter.com/.../status/ID or https://x.com/.../status/ID.

  • Parse TweetID and AuthorHandle via regex.

  • Set MentionedAt from email Date.

5) Enrichment (optional)

  • Sentiment: lightweight rule-based scoring.

  • Unshorten links: HTTP module with follow-redirects enabled.

6) Test the path

  • Send a real mention. Confirm one new Airtable row.

  • Confirm no duplicates on reprocessing.

7) Harden the scenario

  • Add retry logic in Airtable modules.

  • Guard against template changes. Keep regex flexible.

  • Log raw email on parser failures.

Code / JSON Snippets

Below are copy-paste blocks for each piece.

Gmail filter query (mentions)

Use one of these search queries for labeling. Include both “Twitter” and “X” cases.

from:([email protected] OR [email protected] OR [email protected]) subject:(mentioned you OR mention) OR "mentioned you on X"

Gmail filter import (XML)

Import under Gmail Settings > Filters > Import. Replace YOUR_LABEL.

<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns='http://schemas.google.com/apps/2006'>
  <entry>
    <category term='filter'/>
    <title>Twitter/X Mention</title>
    <apps:property xmlns:apps='http://schemas.google.com/apps/2006' name='from' value='[email protected] OR [email protected] OR [email protected]'/>
    <apps:property xmlns:apps='http://schemas.google.com/apps/2006' name='subject' value='mentioned you'/>
    <apps:property xmlns:apps='http://schemas.google.com/apps/2006' name='label' value='twitter-mentions'/>
    <apps:property xmlns:apps='http://schemas.google.com/apps/2006' name='shouldNeverSpam' value='true'/>
  </entry>
</feed>

Make.com Code module: robust parser

Parses HTML or text. Extracts URL, TweetID, AuthorHandle, and a safe text preview.

// Input: bundle.inputData.htmlBody, bundle.inputData.textBody, bundle.inputData.emailId, bundle.inputData.date
function getFirst(arr){ return Array.isArray(arr) && arr.length ? arr[0] : null; }

const html = (input.htmlBody || "").toString();
const text = (input.textBody || "").toString();

const urlRegex = /(https?:\/\/(?:twitter|x)\.com\/[A-Za-z0-9_]{1,15}\/status\/(\d+)[^"' \n]*)/i;
const handleRegex = /@([A-Za-z0-9_]{1,15})/g;

// Prefer HTML match
let urlMatch = html.match(urlRegex) || text.match(urlRegex);
let tweetUrl = urlMatch ? urlMatch[1] : "";
let tweetId = urlMatch ? urlMatch[2] : "";

let handles = [];
let m;
while ((m = handleRegex.exec(html || text)) !== null) {
  handles.push(m[1]);
}
// Heuristic: the first handle that is not your own is the author
const YOUR_HANDLE = (input.yourHandle || "yourhandle").replace(/^@/, "").toLowerCase();
let authorHandle = handles.map(h => h.toLowerCase()).find(h => h !== YOUR_HANDLE) || getFirst(handles) || "";

// Clean preview
const preview = (text || html.replace(/<[^>]*>/g, " "))
  .replace(/\s+/g, " ")
  .trim()
  .slice(0, 260);

// Basic rule-based sentiment
function scoreSentiment(s){
  const pos = ["great","love","thanks","good","awesome","cool","nice","helpful","🔥","💯","+1"];
  const neg = ["bad","hate","terrible","annoying","bug","issue","broken","wtf","ugh","👎"];
  let p = pos.some(k => s.toLowerCase().includes(k));
  let n = neg.some(k => s.toLowerCase().includes(k));
  if (p && !n) return "Positive";
  if (n && !p) return "Negative";
  return "Neutral";
}

return [{
  TweetURL: tweetUrl,
  TweetID: tweetId,
  AuthorHandle: authorHandle ? "@" + authorHandle : "",
  Text: preview,
  MentionedAt: input.date || new Date().toISOString(),
  SourceEmailID: input.emailId || ""
}];

Airtable “Search or Create” logic in Make

  • Airtable > Search records. Table: Mentions. Formula:
    "{UniqueKey} = 'tw_" + {{Code[1].TweetID}} + "'".

  • If empty result, Airtable > Create a record mapping:

    • TweetID: {{Code[1].TweetID}}

    • AuthorHandle: {{Code[1].AuthorHandle}}

    • Text: {{Code[1].Text}}

    • TweetURL: {{Code[1].TweetURL}}

    • MentionedAt: {{Code[1].MentionedAt}}

    • SourceEmailID: {{Code[1].SourceEmailID}}

    • Sentiment: {{Code[1].Sentiment}} (optional)

Fallback: direct Airtable API (cURL)

Use if you prefer HTTP modules. Replace placeholders.

curl -X POST "https://api.airtable.com/v0/YOUR_BASE_ID/Mentions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "TweetID": "1831100012345678901",
      "AuthorHandle": "@sampleuser",
      "Text": "Thanks @yourhandle for the new release",
      "TweetURL": "https://x.com/sampleuser/status/1831100012345678901",
      "MentionedAt": "2025-08-18T12:34:56Z",
      "SourceEmailID": "msg-f:12345"
    }
  }'

Sample workflow JSON code

Portable and platform-agnostic. Represents the scenario graph. You can adapt fields to Make or n8n.

{
  "workflow": {
    "name": "twitter-mentions-to-airtable-free",
    "assumptions": {
      "noTwitterApi": true,
      "emailNotifications": true
    },
    "nodes": [
      {
        "id": "gmail_watch",
        "type": "trigger.gmail.watch",
        "config": {
          "label": "twitter-mentions",
          "includeHtml": true,
          "includeText": true
        },
        "outputs": ["email"]
      },
      {
        "id": "parse_email",
        "type": "function.javascript",
        "inputs": ["email"],
        "config": {
          "source": "/* JS from snippet above */"
        },
        "outputs": ["parsed"]
      },
      {
        "id": "airtable_search",
        "type": "db.airtable.search",
        "inputs": ["parsed"],
        "config": {
          "baseId": "YOUR_BASE_ID",
          "table": "Mentions",
          "formula": "({UniqueKey} = 'tw_' & {{parsed.TweetID}})"
        },
        "outputs": ["hits"]
      },
      {
        "id": "router_create_if_missing",
        "type": "router",
        "branches": [
          {
            "when": "hits.count == 0",
            "to": "airtable_create"
          }
        ]
      },
      {
        "id": "airtable_create",
        "type": "db.airtable.create",
        "inputs": ["parsed"],
        "config": {
          "baseId": "YOUR_BASE_ID",
          "table": "Mentions",
          "fields": {
            "TweetID": "{{parsed.TweetID}}",
            "AuthorHandle": "{{parsed.AuthorHandle}}",
            "Text": "{{parsed.Text}}",
            "TweetURL": "{{parsed.TweetURL}}",
            "MentionedAt": "{{parsed.MentionedAt}}",
            "SourceEmailID": "{{parsed.SourceEmailID}}"
          }
        }
      },
      {
        "id": "slack_notify",
        "type": "notify.slack.send",
        "optional": true,
        "inputs": ["parsed"],
        "config": {
          "channel": "#mentions",
          "text": "New mention by {{parsed.AuthorHandle}} → {{parsed.TweetURL}}"
        }
      }
    ]
  }
}

Diagram

diagram

Use Cases / Scenarios

  • Personal brand monitoring: Capture praise, questions, and issues. Route negatives to a support queue.

  • Product feedback: Tag Project by keyword or campaign and aggregate sentiment.

  • Community support: Track replies mentioning moderators.

  • Client reporting: Share a live Airtable view filtered by Project.

Limitations / Considerations

  • Email dependency: If X email notifications pause or templates change, parsing breaks.

  • Latency: Emails may arrive minutes after the tweet. Real-time is not guaranteed.

  • Coverage: Only mentions that trigger emails are captured. Direct replies without @yourhandle may not.

  • Parsing fragility: HTML templates can change. Keep regex generic.

  • Volume caps: Free tiers limit throughput and storage.

  • Privacy: Do not store sensitive data in Airtable if not required.

  • Legal: Respect X Terms and sender email policies. No scraping.

Fixes (common pitfalls and troubleshooting)

  • No emails in Gmail: Recheck X notification settings. Send a manual test mention. Check spam.

  • Filter not catching messages: Broaden the query. Include both Twitter and X sender domains. Use the XML import.

  • Parser fails to find URL: Switch to HTML body. Update the regex to support x.com and twitter.com. Log raw email on failure.

  • Duplicates in Airtable: Confirm UniqueKey formula. Ensure the search module uses it. Guard against empty TweetID.

  • Garbled text: Strip HTML tags and decode entities. Ensure UTF-8 in Make.

  • Airtable rate limits: Add a short delay in Make on bursts. Batch with “Create records” if available.

  • Slack not posting: Validate OAuth scopes and channel ID.

  • Operations over free quota: Add filters for low-value mentions. Throttle alerts and keep only Airtable writes.

Budget Calculation

Assumptions. Free plan values vary by provider. Replace with your actual quotas.

Variables

  • M = monthly mentions captured.

  • O = Make operations per mention (trigger + parse + search + conditional + create + optional notify). Typical O = 4 without Slack, O = 5 with Slack.

  • OpsTotal = M × O.

Example

  • M = 200, O = 5OpsTotal = 1,000. Fits a 1,000-ops free tier.

  • Airtable storage: if Free plan allows R records per base, ensure M × monthsKept ≤ R.

  • If you keep 12 months and expect M = 150, then TotalRecords = 1,800. Use a paid plan or archive old rows monthly.

Cost controls

  • Add a Make filter to ignore self-mentions or known bots.

  • Drop Slack step or batch alerts.

  • Archive old rows to CSV monthly.

Conclusion

You can build a robust “Twitter monitor automation” with an “Airtable save” using only email notifications, Gmail filters, and a Make.com scenario. The flow is API-free and stable at a personal scale. It records the essentials, blocks duplicates, and supports light enrichment. You can move to the X API later if your volume or latency demands change.