This workflow corresponds to n8n.io template #13653 — we link there as the canonical source.
This workflow follows the Emailsend → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "am1RwBADxjmSSZRZ",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "AI Social Listening Agent",
"tags": [],
"nodes": [
{
"id": "7c80824c-f381-4551-a857-74c7cd35337d",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2752,
-464
],
"parameters": {
"width": 820,
"height": 720,
"content": "## AI Social Listening Agent\n\nMonitors brand mentions across Twitter/X, Reddit, and news sources in real-time. Uses AI to analyze sentiment (positive/negative/neutral), detects trending topics, classifies urgency, and delivers actionable insights via Slack and Email with daily digest reports.\n\n## How it works\n\n1. **Trigger** \u2014 Runs every hour to check for new brand mentions\n2. **Fetch & collect** \u2014 Pulls mentions from Twitter/X, Reddit, and News APIs in parallel\n3. **Analyze** \u2014 AI sentiment analysis, urgency classification, and trend detection\n4. **Deduplicate** \u2014 Filters already-processed mentions to avoid noise\n5. **Alert** \u2014 Sends real-time Slack alerts for negative/urgent mentions; logs all to Airtable\n6. **Report** \u2014 Generates daily HTML digest and emails summary to marketing team\n\n## Setup steps\n\n1. **Social APIs** \u2014 Add your Twitter/X Bearer Token, Reddit Client ID/Secret, and News API Key\n2. **OpenAI** \u2014 Add your OpenAI API key for sentiment analysis\n3. **Airtable** \u2014 Create a `brand_mentions` base and add your API key\n4. **Slack** \u2014 Add your incoming webhook URL to the Slack node\n5. **Email** \u2014 Configure SMTP credentials and set `from` / `to` addresses\n6. **Brand Config** \u2014 Update the brand name and keywords in the Config node\n7. **Test** \u2014 Run manually to verify all connections, then activate"
},
"typeVersion": 1
},
{
"id": "43b61124-1746-4b60-9632-91ef576a8de4",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1840,
-368
],
"parameters": {
"color": 5,
"width": 468,
"height": 465,
"content": "## 1. Trigger & configure\n\nRuns every hour to initiate brand monitoring. Config node sets brand name, keywords, and monitoring parameters"
},
"typeVersion": 1
},
{
"id": "875435b7-441a-46b2-a86f-1ccfced6b2a3",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1328,
-496
],
"parameters": {
"color": 5,
"width": 668,
"height": 820,
"content": "## 2. Fetch & collect mentions\n\nFetches brand mentions from Twitter/X, Reddit, and News APIs in parallel, then merges all results into a unified stream"
},
"typeVersion": 1
},
{
"id": "67f60b4a-55fc-4e5e-9200-2553a772f960",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-624,
-544
],
"parameters": {
"color": 5,
"width": 588,
"height": 905,
"content": "## 3. AI analyze & deduplicate\n\nUses OpenAI to classify sentiment, detect urgency, extract topics, and deduplicates mentions already seen this session"
},
"typeVersion": 1
},
{
"id": "62d00e40-ad6e-458e-8ef6-13793c17d173",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
32,
-528
],
"parameters": {
"color": 5,
"width": 1328,
"height": 713,
"content": "## 4. Store, alert & report\n\nLogs all mentions to Airtable, sends real-time Slack alerts for negative/urgent mentions, and emails a daily HTML digest to the marketing team"
},
"typeVersion": 1
},
{
"id": "28fbfdd8-4086-47b1-a30d-eaf8b80d5d54",
"name": "Monitor brand mentions every hour",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-1712,
-64
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "39123f7b-7809-4887-bdf8-9105af94f0f7",
"name": "Set brand monitoring config",
"type": "n8n-nodes-base.set",
"position": [
-1488,
-64
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "brand-name",
"name": "brandName",
"type": "string",
"value": "YourBrand"
},
{
"id": "keywords",
"name": "keywords",
"type": "string",
"value": "YourBrand,@YourBrand,#YourBrand"
},
{
"id": "lookback-hours",
"name": "lookbackHours",
"type": "number",
"value": 1
},
{
"id": "alert-threshold",
"name": "negativeAlertThreshold",
"type": "number",
"value": 3
}
]
}
},
"typeVersion": 3.4
},
{
"id": "dbac966d-a71b-4dc9-84b3-621beca97b98",
"name": "Fetch Twitter/X mentions",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1264,
-352
],
"parameters": {
"url": "https://api.twitter.com/2/tweets/search/recent",
"options": {},
"sendQuery": true,
"sendHeaders": true,
"queryParameters": {
"parameters": [
{
"name": "query",
"value": "={{ $json.brandName + ' -is:retweet lang:en' }}"
},
{
"name": "tweet.fields",
"value": "created_at,author_id,text,public_metrics,geo"
},
{
"name": "max_results",
"value": "50"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "f3a1d9e5-14e8-4b1c-a04c-57a23f5cd2a4",
"name": "Fetch Reddit mentions",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1264,
-160
],
"parameters": {
"url": "https://www.reddit.com/search.json",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.brandName }}"
},
{
"name": "sort",
"value": "new"
},
{
"name": "t",
"value": "day"
},
{
"name": "limit",
"value": "25"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "d6f98d40-927b-41b0-bd18-5246780b10b8",
"name": "Fetch news article mentions",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1264,
32
],
"parameters": {
"url": "https://newsapi.org/v2/everything",
"options": {},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "q",
"value": "={{ $json.brandName }}"
},
{
"name": "sortBy",
"value": "publishedAt"
},
{
"name": "language",
"value": "en"
},
{
"name": "pageSize",
"value": "20"
},
{
"name": "apiKey",
"value": "YOUR_NEWS_API_KEY"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "0a3f264c-b449-41de-822f-888ac8b0e899",
"name": "Merge all platform mentions",
"type": "n8n-nodes-base.merge",
"position": [
-1040,
-160
],
"parameters": {
"mode": "combine",
"options": {}
},
"typeVersion": 3
},
{
"id": "81837c5d-634f-4019-8195-46fc6268d41c",
"name": "Normalize mentions into unified schema",
"type": "n8n-nodes-base.code",
"position": [
-816,
-160
],
"parameters": {
"jsCode": "// Normalize all platform data into a unified mention schema\nconst items = $input.all();\nconst normalizedMentions = [];\nconst now = new Date();\nconst brandName = 'YourBrand'; // Update to match config\n\nitems.forEach(item => {\n const data = item.json;\n\n // Twitter/X mentions\n if (data.data && Array.isArray(data.data)) {\n data.data.forEach(tweet => {\n normalizedMentions.push({\n platform: 'Twitter/X',\n mentionId: `tw_${tweet.id}`,\n text: tweet.text || '',\n author: tweet.author_id || 'unknown',\n url: `https://twitter.com/i/web/status/${tweet.id}`,\n publishedAt: tweet.created_at || now.toISOString(),\n likes: tweet.public_metrics?.like_count || 0,\n shares: tweet.public_metrics?.retweet_count || 0,\n reach: (tweet.public_metrics?.like_count || 0) + (tweet.public_metrics?.retweet_count || 0),\n rawData: tweet\n });\n });\n }\n\n // Reddit mentions\n if (data.data?.children && Array.isArray(data.data.children)) {\n data.data.children.forEach(post => {\n const p = post.data;\n normalizedMentions.push({\n platform: 'Reddit',\n mentionId: `rd_${p.id}`,\n text: `${p.title} ${p.selftext || ''}`.trim(),\n author: p.author || 'unknown',\n url: `https://reddit.com${p.permalink}`,\n publishedAt: new Date(p.created_utc * 1000).toISOString(),\n likes: p.score || 0,\n shares: p.num_comments || 0,\n reach: p.score || 0,\n rawData: p\n });\n });\n }\n\n // News mentions\n if (data.articles && Array.isArray(data.articles)) {\n data.articles.forEach((article, idx) => {\n normalizedMentions.push({\n platform: 'News',\n mentionId: `nw_${Buffer.from(article.url || idx.toString()).toString('base64').slice(0,12)}`,\n text: `${article.title} ${article.description || ''}`.trim(),\n author: article.source?.name || 'Unknown Source',\n url: article.url || '',\n publishedAt: article.publishedAt || now.toISOString(),\n likes: 0,\n shares: 0,\n reach: 0,\n rawData: article\n });\n });\n }\n});\n\nconst reportTimestamp = now.toISOString();\nconst reportDate = now.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n\nreturn normalizedMentions.map(mention => ({\n json: {\n ...mention,\n brandName,\n reportTimestamp,\n reportDate,\n totalMentionsCollected: normalizedMentions.length\n }\n}));"
},
"typeVersion": 2
},
{
"id": "c5e986df-9285-4d2b-b43f-4ea0f4569d8d",
"name": "AI sentiment and urgency analysis",
"type": "n8n-nodes-base.httpRequest",
"position": [
-592,
-160
],
"parameters": {
"url": "https://api.openai.com/v1/chat/completions",
"method": "POST",
"options": {},
"jsonBody": "={\n \"model\": \"gpt-4o-mini\",\n \"max_tokens\": 300,\n \"response_format\": { \"type\": \"json_object\" },\n \"messages\": [\n {\n \"role\": \"system\",\n \"content\": \"You are a brand monitoring AI. Analyze the given text and return ONLY valid JSON with these fields: sentiment (positive/negative/neutral), sentimentScore (-1.0 to 1.0), urgency (low/medium/high/critical), topics (array of up to 3 key topics), summary (one sentence), requiresResponse (boolean), language (ISO 639-1 code).\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Analyze this brand mention from {{ $json.platform }}: {{ $json.text }}\"\n }\n ]\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "11463390-874b-43e1-ab29-1b5dc31f4b76",
"name": "Process AI analysis results",
"type": "n8n-nodes-base.code",
"position": [
-160,
-160
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Parse AI response and enrich mention with sentiment data\nconst item = $input.item.json;\n\nlet aiAnalysis = {};\ntry {\n const content = item.choices?.[0]?.message?.content || '{}';\n aiAnalysis = JSON.parse(content);\n} catch (e) {\n aiAnalysis = {\n sentiment: 'neutral',\n sentimentScore: 0,\n urgency: 'low',\n topics: [],\n summary: 'Analysis unavailable',\n requiresResponse: false,\n language: 'en'\n };\n}\n\nconst sentiment = aiAnalysis.sentiment || 'neutral';\nconst urgency = aiAnalysis.urgency || 'low';\n\n// Generate mention ID for dedup tracking\nconst mentionId = item.mentionId || `gen_${Date.now()}`;\n\n// Check duplicate via static data\nconst processedMentions = $getWorkflowStaticData('global').processedMentions || {};\nconst isDuplicate = !!processedMentions[mentionId];\n\nif (!isDuplicate) {\n processedMentions[mentionId] = {\n timestamp: new Date().toISOString(),\n sentiment,\n urgency\n };\n // Clean up mentions older than 7 days\n const sevenDaysAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);\n for (const key in processedMentions) {\n if (new Date(processedMentions[key].timestamp).getTime() < sevenDaysAgo) {\n delete processedMentions[key];\n }\n }\n $getWorkflowStaticData('global').processedMentions = processedMentions;\n}\n\n// Update cumulative stats\nconst stats = $getWorkflowStaticData('global').mentionStats || {\n total: 0, positive: 0, negative: 0, neutral: 0, critical: 0, byPlatform: {}\n};\nif (!isDuplicate) {\n stats.total++;\n if (sentiment === 'positive') stats.positive++;\n else if (sentiment === 'negative') stats.negative++;\n else stats.neutral++;\n if (urgency === 'critical') stats.critical++;\n stats.byPlatform[item.platform] = (stats.byPlatform[item.platform] || 0) + 1;\n $getWorkflowStaticData('global').mentionStats = stats;\n}\n\nconst requiresAlert = (sentiment === 'negative' && urgency !== 'low') || urgency === 'critical';\n\nreturn {\n json: {\n ...item,\n mentionId,\n sentiment,\n sentimentScore: aiAnalysis.sentimentScore || 0,\n urgency,\n topics: aiAnalysis.topics || [],\n aiSummary: aiAnalysis.summary || '',\n requiresResponse: aiAnalysis.requiresResponse || false,\n language: aiAnalysis.language || 'en',\n isDuplicate,\n requiresAlert,\n processedAt: new Date().toISOString()\n }\n};"
},
"typeVersion": 2
},
{
"id": "d74607a5-73b7-48ae-90fa-5ef7f0b2722c",
"name": "Route by sentiment and urgency",
"type": "n8n-nodes-base.switch",
"position": [
64,
-176
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Critical \u2014 Immediate Alert",
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.urgency }}",
"rightValue": "critical"
}
]
},
"renameOutput": true
},
{
"outputKey": "Negative \u2014 Needs Attention",
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.sentiment }}",
"rightValue": "negative"
}
]
},
"renameOutput": true
},
{
"outputKey": "Positive or Neutral",
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "or",
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.sentiment }}",
"rightValue": "positive"
},
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.sentiment }}",
"rightValue": "neutral"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3
},
{
"id": "56f4a0f6-87ae-48b3-8c63-356a4938a057",
"name": "Send critical mention alert",
"type": "n8n-nodes-base.httpRequest",
"position": [
288,
-352
],
"parameters": {
"url": "https://api.example.com/alerts/send",
"method": "POST",
"options": {},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "alert_type",
"value": "CRITICAL_BRAND_MENTION"
},
{
"name": "severity",
"value": "critical"
},
{
"name": "platform",
"value": "={{ $json.platform }}"
},
{
"name": "mention_id",
"value": "={{ $json.mentionId }}"
},
{
"name": "sentiment",
"value": "={{ $json.sentiment }}"
},
{
"name": "message",
"value": "={{ 'CRITICAL brand mention on ' + $json.platform + ': ' + $json.aiSummary + ' \u2014 URL: ' + $json.url }}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "bcc14722-99ac-42a7-8558-63db38e82b2c",
"name": "Log mention to Airtable",
"type": "n8n-nodes-base.httpRequest",
"position": [
288,
-160
],
"parameters": {
"url": "https://api.airtable.com/v0/YOUR_BASE_ID/brand_mentions",
"method": "POST",
"options": {},
"jsonBody": "={\n \"fields\": {\n \"Mention ID\": \"{{ $json.mentionId }}\",\n \"Platform\": \"{{ $json.platform }}\",\n \"Text\": \"{{ $json.text.slice(0, 500) }}\",\n \"Author\": \"{{ $json.author }}\",\n \"URL\": \"{{ $json.url }}\",\n \"Sentiment\": \"{{ $json.sentiment }}\",\n \"Sentiment Score\": {{ $json.sentimentScore }},\n \"Urgency\": \"{{ $json.urgency }}\",\n \"Topics\": \"{{ $json.topics.join(', ') }}\",\n \"AI Summary\": \"{{ $json.aiSummary }}\",\n \"Requires Response\": {{ $json.requiresResponse }},\n \"Published At\": \"{{ $json.publishedAt }}\",\n \"Processed At\": \"{{ $json.processedAt }}\",\n \"Is Duplicate\": {{ $json.isDuplicate }},\n \"Reach\": {{ $json.reach }}\n }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_TOKEN_HERE"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "06e26387-1dc9-46c9-9af2-41b4f73509fb",
"name": "Generate HTML daily digest report",
"type": "n8n-nodes-base.code",
"position": [
512,
-240
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Generate HTML daily digest report for brand mentions\nconst mention = $input.item.json;\nconst stats = $getWorkflowStaticData('global').mentionStats || { total: 0, positive: 0, negative: 0, neutral: 0, critical: 0, byPlatform: {} };\n\nconst sentimentColor = mention.sentiment === 'positive' ? '#22c55e' : mention.sentiment === 'negative' ? '#ef4444' : '#94a3b8';\nconst urgencyColor = mention.urgency === 'critical' ? '#ef4444' : mention.urgency === 'high' ? '#f97316' : mention.urgency === 'medium' ? '#f59e0b' : '#22c55e';\nconst sentimentIcon = mention.sentiment === 'positive' ? '\ud83d\ude0a' : mention.sentiment === 'negative' ? '\ud83d\ude20' : '\ud83d\ude10';\n\nconst platformRows = Object.entries(stats.byPlatform).map(([p, count]) => `<tr><td>${p}</td><td>${count}</td></tr>`).join('') || '<tr><td colspan=\"2\">No data yet</td></tr>';\n\nconst positiveRate = stats.total > 0 ? Math.round((stats.positive / stats.total) * 100) : 0;\nconst negativeRate = stats.total > 0 ? Math.round((stats.negative / stats.total) * 100) : 0;\nconst neutralRate = stats.total > 0 ? Math.round((stats.neutral / stats.total) * 100) : 0;\n\nconst reportHtml = `\n<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"UTF-8\">\n <title>Brand Mention Digest \u2014 ${mention.reportDate}</title>\n <style>\n body { font-family: Arial, sans-serif; color: #1e293b; margin: 0; padding: 24px; background: #f8fafc; }\n .header { background: #0f172a; color: white; padding: 24px; border-radius: 8px; margin-bottom: 24px; }\n .header h1 { margin: 0 0 8px 0; font-size: 22px; }\n .header p { margin: 0; opacity: 0.7; font-size: 13px; }\n .badge { display: inline-block; padding: 6px 16px; border-radius: 20px; font-weight: bold; font-size: 14px; background: ${sentimentColor}; color: white; margin-top: 12px; }\n .cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 24px; }\n .card { background: white; border-radius: 8px; padding: 16px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n .card .value { font-size: 28px; font-weight: bold; }\n .card .label { font-size: 12px; color: #64748b; margin-top: 4px; }\n .section { background: white; border-radius: 8px; padding: 20px; margin-bottom: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }\n .section h2 { margin: 0 0 16px 0; font-size: 16px; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; }\n table { width: 100%; border-collapse: collapse; font-size: 13px; }\n th { background: #f1f5f9; text-align: left; padding: 8px 12px; }\n td { padding: 8px 12px; border-bottom: 1px solid #e2e8f0; }\n .mention-card { border-left: 4px solid ${sentimentColor}; padding: 12px 16px; background: #f8fafc; border-radius: 4px; margin-bottom: 8px; }\n .footer { text-align: center; font-size: 11px; color: #94a3b8; margin-top: 24px; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>\ud83d\udce1 Brand Social Listening Digest</h1>\n <p>Brand: ${mention.brandName} | Report Date: ${mention.reportDate} | Platforms: Twitter/X, Reddit, News</p>\n <div class=\"badge\">${sentimentIcon} Latest: ${mention.sentiment?.toUpperCase()}</div>\n </div>\n\n <div class=\"cards\">\n <div class=\"card\"><div class=\"value\">${stats.total}</div><div class=\"label\">Total Mentions</div></div>\n <div class=\"card\"><div class=\"value\" style=\"color:#22c55e\">${positiveRate}%</div><div class=\"label\">Positive Sentiment</div></div>\n <div class=\"card\"><div class=\"value\" style=\"color:#ef4444\">${negativeRate}%</div><div class=\"label\">Negative Sentiment</div></div>\n <div class=\"card\"><div class=\"value\" style=\"color:#f59e0b\">${stats.critical}</div><div class=\"label\">Critical Alerts</div></div>\n </div>\n\n <div class=\"section\">\n <h2>\ud83d\udcca Sentiment Breakdown</h2>\n <table><thead><tr><th>Sentiment</th><th>Count</th><th>Rate</th></tr></thead><tbody>\n <tr><td>\u2705 Positive</td><td style=\"color:#22c55e;font-weight:bold\">${stats.positive}</td><td>${positiveRate}%</td></tr>\n <tr><td>\u274c Negative</td><td style=\"color:#ef4444;font-weight:bold\">${stats.negative}</td><td>${negativeRate}%</td></tr>\n <tr><td>\ud83d\ude10 Neutral</td><td style=\"color:#94a3b8\">${stats.neutral}</td><td>${neutralRate}%</td></tr>\n </tbody></table>\n </div>\n\n <div class=\"section\">\n <h2>\ud83c\udf10 Mentions by Platform</h2>\n <table><thead><tr><th>Platform</th><th>Mentions</th></tr></thead><tbody>${platformRows}</tbody></table>\n </div>\n\n <div class=\"section\">\n <h2>\ud83d\udd14 Latest Mention</h2>\n <div class=\"mention-card\">\n <strong>${mention.platform}</strong> \u2014 <span style=\"color:${sentimentColor}\">${mention.sentiment?.toUpperCase()}</span> | Urgency: <span style=\"color:${urgencyColor}\">${mention.urgency?.toUpperCase()}</span><br>\n <p style=\"margin:8px 0;font-size:13px\">${mention.aiSummary || mention.text?.slice(0, 200)}</p>\n <small>Topics: ${(mention.topics || []).join(', ') || 'N/A'} | Author: ${mention.author} | <a href=\"${mention.url}\">View Original</a></small>\n </div>\n </div>\n\n <div class=\"footer\">Automated report generated by AI Social Listening Agent | ${mention.processedAt}</div>\n</body>\n</html>`;\n\nconst notificationMessage = `${sentimentIcon} *BRAND MENTION \u2014 ${mention.platform}*\\n\\n` +\n `*Brand:* ${mention.brandName}\\n` +\n `*Sentiment:* ${mention.sentiment?.toUpperCase()} (${mention.sentimentScore > 0 ? '+' : ''}${mention.sentimentScore?.toFixed(2)})\\n` +\n `*Urgency:* ${mention.urgency?.toUpperCase()}\\n` +\n `*Summary:* ${mention.aiSummary}\\n` +\n `*Topics:* ${(mention.topics || []).join(', ') || 'N/A'}\\n` +\n `*Author:* ${mention.author}\\n` +\n `*Platform:* ${mention.platform}\\n` +\n `*URL:* ${mention.url}\\n\\n` +\n `*Session Stats:* ${stats.total} mentions | ${positiveRate}% positive | ${negativeRate}% negative`;\n\nreturn {\n json: {\n ...mention,\n reportHtml,\n notificationMessage,\n notificationTitle: `${sentimentIcon} [${mention.platform}] ${mention.sentiment?.toUpperCase()} brand mention \u2014 ${mention.urgency?.toUpperCase()} urgency`,\n shouldAlert: mention.requiresAlert || mention.urgency === 'critical',\n sessionStats: stats\n }\n};"
},
"typeVersion": 2
},
{
"id": "f146210a-6a32-406e-8798-8a779df66147",
"name": "Filter mentions requiring alerts",
"type": "n8n-nodes-base.filter",
"position": [
736,
-240
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": false,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "alert-filter",
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.shouldAlert }}"
}
]
}
},
"typeVersion": 2
},
{
"id": "72fb1a15-ce54-48cb-bd79-7e78689bc5dc",
"name": "Post mention alert to Slack",
"type": "n8n-nodes-base.httpRequest",
"position": [
960,
-256
],
"parameters": {
"url": "YOUR_SLACK_WEBHOOK_URL",
"method": "POST",
"options": {},
"jsonBody": "={\n \"text\": \"{{ $json.notificationTitle }}\",\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"{{ $json.notificationMessage }}\"\n }\n }\n ]\n}",
"sendBody": true,
"specifyBody": "json"
},
"typeVersion": 4.2
},
{
"id": "64a6aa14-c229-45c8-b818-f245f8868bbd",
"name": "Email HTML digest to marketing team",
"type": "n8n-nodes-base.emailSend",
"position": [
960,
-64
],
"parameters": {
"html": "={{ $json.reportHtml }}",
"options": {},
"subject": "={{ $json.notificationTitle }}",
"toEmail": "user@example.com",
"fromEmail": "user@example.com"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "3eda856c-07fe-4eb2-8876-b8d8433c24be",
"name": "Log success and update listening statistics",
"type": "n8n-nodes-base.code",
"position": [
1184,
-240
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "// Log successful mention processing and track statistics\nconst timestamp = new Date().toISOString();\nconst mention = $input.item.json;\n\nconsole.log(`\u2705 SUCCESS: Mention ${mention.mentionId} | Platform: ${mention.platform} | Sentiment: ${mention.sentiment} | Urgency: ${mention.urgency} | Duplicate: ${mention.isDuplicate} | Time: ${timestamp}`);\n\nconst stats = $getWorkflowStaticData('global').mentionStats || {};\n\nreturn {\n json: {\n success: true,\n mentionId: mention.mentionId,\n platform: mention.platform,\n sentiment: mention.sentiment,\n urgency: mention.urgency,\n requiresResponse: mention.requiresResponse,\n isDuplicate: mention.isDuplicate,\n alertSent: mention.shouldAlert,\n timestamp,\n sessionStats: {\n totalMentions: stats.total || 0,\n positiveCount: stats.positive || 0,\n negativeCount: stats.negative || 0,\n neutralCount: stats.neutral || 0,\n criticalAlerts: stats.critical || 0,\n byPlatform: stats.byPlatform || {}\n }\n }\n};"
},
"typeVersion": 2
},
{
"id": "a9cc90cf-9c9c-481a-afc2-67af5d0de035",
"name": "Wait For Result",
"type": "n8n-nodes-base.wait",
"position": [
-384,
-160
],
"parameters": {},
"typeVersion": 1.1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "7a1be7c0-e86e-4a4c-9003-f703640dd3bf",
"connections": {
"Wait For Result": {
"main": [
[
{
"node": "Process AI analysis results",
"type": "main",
"index": 0
}
]
]
},
"Fetch Reddit mentions": {
"main": [
[
{
"node": "Merge all platform mentions",
"type": "main",
"index": 1
}
]
]
},
"Log mention to Airtable": {
"main": [
[
{
"node": "Generate HTML daily digest report",
"type": "main",
"index": 0
}
]
]
},
"Fetch Twitter/X mentions": {
"main": [
[
{
"node": "Merge all platform mentions",
"type": "main",
"index": 0
}
]
]
},
"Fetch news article mentions": {
"main": [
[
{
"node": "Merge all platform mentions",
"type": "main",
"index": 1
}
]
]
},
"Merge all platform mentions": {
"main": [
[
{
"node": "Normalize mentions into unified schema",
"type": "main",
"index": 0
}
]
]
},
"Post mention alert to Slack": {
"main": [
[
{
"node": "Log success and update listening statistics",
"type": "main",
"index": 0
}
]
]
},
"Process AI analysis results": {
"main": [
[
{
"node": "Route by sentiment and urgency",
"type": "main",
"index": 0
}
]
]
},
"Send critical mention alert": {
"main": [
[
{
"node": "Generate HTML daily digest report",
"type": "main",
"index": 0
}
]
]
},
"Set brand monitoring config": {
"main": [
[
{
"node": "Fetch Twitter/X mentions",
"type": "main",
"index": 0
},
{
"node": "Fetch Reddit mentions",
"type": "main",
"index": 0
},
{
"node": "Fetch news article mentions",
"type": "main",
"index": 0
}
]
]
},
"Route by sentiment and urgency": {
"main": [
[
{
"node": "Send critical mention alert",
"type": "main",
"index": 0
},
{
"node": "Log mention to Airtable",
"type": "main",
"index": 0
},
{
"node": "Generate HTML daily digest report",
"type": "main",
"index": 0
}
],
[
{
"node": "Log mention to Airtable",
"type": "main",
"index": 0
},
{
"node": "Generate HTML daily digest report",
"type": "main",
"index": 0
}
],
[
{
"node": "Log mention to Airtable",
"type": "main",
"index": 0
},
{
"node": "Generate HTML daily digest report",
"type": "main",
"index": 0
}
]
]
},
"Filter mentions requiring alerts": {
"main": [
[
{
"node": "Post mention alert to Slack",
"type": "main",
"index": 0
},
{
"node": "Email HTML digest to marketing team",
"type": "main",
"index": 0
}
]
]
},
"AI sentiment and urgency analysis": {
"main": [
[
{
"node": "Wait For Result",
"type": "main",
"index": 0
}
]
]
},
"Generate HTML daily digest report": {
"main": [
[
{
"node": "Filter mentions requiring alerts",
"type": "main",
"index": 0
}
]
]
},
"Monitor brand mentions every hour": {
"main": [
[
{
"node": "Set brand monitoring config",
"type": "main",
"index": 0
}
]
]
},
"Email HTML digest to marketing team": {
"main": [
[
{
"node": "Log success and update listening statistics",
"type": "main",
"index": 0
}
]
]
},
"Normalize mentions into unified schema": {
"main": [
[
{
"node": "AI sentiment and urgency analysis",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
smtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Monitors brand mentions across Twitter/X, Reddit, and News APIs in real-time (or scheduled), fetches mentions in parallel, normalizes data, uses AI to analyze sentiment/urgency/topics, detects duplicates, filters critical mentions, logs everything to Airtable, posts alerts to…
Source: https://n8n.io/workflows/13653/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Tech Daily Digest. Uses rssFeedRead, emailSend, httpRequest. Scheduled trigger; 22 nodes.
Daily AI Research Agent. Uses httpRequest, telegram, emailSend. Scheduled trigger; 11 nodes.
Agent Studio - Weekly Analytics Report. Uses httpRequest, emailSend. Scheduled trigger; 8 nodes.
E-Décor - AI Agent Assistant. Uses httpRequest, emailSend. Scheduled trigger; 6 nodes.
Online Marketing Weekly Report. Uses scheduleTrigger, lmChatOpenAi, toolWorkflow, executeWorkflowTrigger. Scheduled trigger; 51 nodes.