Abstract / Overview

Outcomes

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

System design

Data model (Airtable "Mentions")

Idempotency

Step-by-Step Walkthrough

1) Prepare Airtable

2) Turn on X email notifications

3) Create Gmail routing

4) Make.com scenario (free)

Modules

Mapping

5) Enrichment (optional)

6) Test the path

7) Harden the scenario

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

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

Limitations / Considerations

Fixes (common pitfalls and troubleshooting)

Budget Calculation

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

Variables

Example

Cost controls

No-Code Alternative (Free)

If you prefer a visual, no-code approach, this same Twitter → Airtable flow can also be built using Make. It offers a free tier and lets you design the automation with simple drag-and-drop modules—useful if you want filters, branching, or additional app integrations later.

You can explore it here (free account): https://www.make.com/en/register?pc=rohit9910

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.