This workflow corresponds to n8n.io template #16731 — we link there as the canonical source.
This workflow follows the Googlegemini → 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 →
{
"meta": {
"templatecredsSetupCompleted": false
},
"name": "Track AI search citations across ChatGPT, Claude, Gemini and Perplexity",
"tags": [],
"nodes": [
{
"id": "lite-manual",
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [
-40,
200
],
"parameters": {},
"typeVersion": 1
},
{
"id": "lite-sched",
"name": "Weekly Monday 9AM",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-40,
360
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks",
"triggerAtDay": [
1
],
"triggerAtHour": 9
}
]
}
},
"typeVersion": 1.2
},
{
"id": "lite-config",
"name": "Configuration",
"type": "n8n-nodes-base.code",
"position": [
180,
300
],
"parameters": {
"jsCode": "// \u2500\u2500 Lite config: edit these values \u2500\u2500\nconst config = {\n brandName: 'YourBrand',\n wpUrl: 'https://yourdomain.com',\n seedKeywords: ['your main keyword', 'second keyword', 'third keyword'],\n competitors: ['competitor1.com', 'competitor2.com', 'competitor3.com']\n};\nreturn [{ json: config }];\n"
},
"typeVersion": 2
},
{
"id": "57cc4bcf-c1c1-45a5-aa62-2762094f000d",
"name": "Prepare AEO Prompts",
"type": "n8n-nodes-base.code",
"notes": "Builds 5 prompt variants per keyword \u00d7 5 keywords = 25 prompts per client per day.",
"position": [
600,
300
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// Build prompt set for each engine\nconst client = $input.first().json;\nconst keywords = (client.seedKeywords || []).slice(0, 5); // limit to 5 for daily run\nconst competitors = client.competitors || [];\n\nconst promptTemplates = [\n // Brand-mention detection\n `Who are the best {$kw} providers in 2025? List your top 5 with reasons.`,\n `Compare the top {$kw} tools. Which would you recommend for a mid-size company?`,\n `What are the pros and cons of {$brand} for {$kw}?`,\n // Citation-worthy content\n `What is {$kw}? Explain with examples and best practices.`,\n `How to choose the right {$kw} solution? List evaluation criteria.`\n];\n\nconst items = [];\nkeywords.forEach(kw => {\n promptTemplates.forEach((tmpl, i) => {\n const prompt = tmpl.replace('{\\$kw}', kw).replace('{\\$brand}', client.brandName);\n items.push({\n json: {\n ...client,\n keyword: kw,\n promptId: `${kw.replace(/\\s/g, '_')}_${i}`,\n prompt,\n competitors\n }\n });\n });\n});\nreturn items;\n"
},
"notesInFlow": true,
"typeVersion": 2
},
{
"id": "e7c69ce6-e9be-4f7e-988e-793156216c00",
"name": "Loop Prompts",
"type": "n8n-nodes-base.splitInBatches",
"position": [
820,
300
],
"parameters": {
"options": {},
"batchSize": 4
},
"typeVersion": 1
},
{
"id": "60c01125-60fa-49e8-b680-2e5e10fe67a3",
"name": "ChatGPT Response",
"type": "@n8n/n8n-nodes-langchain.openAi",
"notes": "Asks ChatGPT the prompt to detect brand citation.",
"maxTries": 3,
"position": [
1040,
300
],
"parameters": {
"model": "gpt-4o",
"options": {
"temperature": 0.4,
"responseFormat": "text"
},
"messages": {
"messageValues": [
{
"role": "user",
"content": "={{ $json.prompt }}"
}
]
}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 1,
"waitBetweenTries": 2000
},
{
"id": "42397f6a-c928-44fa-a196-53beb52ee645",
"name": "Claude Response",
"type": "@n8n/n8n-nodes-langchain.anthropic",
"notes": "Asks Claude the same prompt for cross-engine citation tracking.",
"maxTries": 3,
"position": [
1260,
300
],
"parameters": {
"model": "claude-3-5-sonnet-20241022",
"options": {
"temperature": 0.4
},
"messages": {
"messageValues": [
{
"role": "user",
"content": "={{ $json.prompt }}"
}
]
}
},
"credentials": {
"anthropicApi": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 1,
"waitBetweenTries": 2000
},
{
"id": "86332a94-f96f-4ce8-937c-c0da23284b2f",
"name": "Gemini Response",
"type": "@n8n/n8n-nodes-langchain.googleGemini",
"notes": "Gemini with Google Search grounding - tracks AI Overview citation probability.",
"maxTries": 3,
"position": [
1480,
300
],
"parameters": {
"prompt": {
"promptMessages": [
{
"message": "={{ $json.prompt }}"
}
]
},
"options": {
"temperature": 0.4
},
"modelName": "gemini-1.5-pro"
},
"credentials": {
"googleGeminiApi": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 1,
"waitBetweenTries": 2000
},
{
"id": "b09d69ef-b5db-48a9-9311-e3c94f179924",
"name": "Perplexity Response",
"type": "n8n-nodes-base.httpRequest",
"notes": "Perplexity API for citation + source tracking (highest citation value).",
"maxTries": 3,
"position": [
1700,
300
],
"parameters": {
"url": "https://api.perplexity.ai/chat/completions",
"method": "POST",
"options": {
"response": {
"response": {
"neverError": true,
"fullResponse": false,
"responseFormat": "json"
}
}
},
"jsonBody": "={\"model\": \"llama-3.1-sonar-large-128k-online\", \"messages\": [{\"role\": \"user\", \"content\": \"{{ $json.prompt }}\"}], \"temperature\": 0.4}",
"sendBody": true,
"sendQuery": false,
"contentType": "json",
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"specifyHeaders": "keypair",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 4,
"waitBetweenTries": 2000
},
{
"id": "674e176f-a206-4836-8010-2ac63b619557",
"name": "Merge AI Responses",
"type": "n8n-nodes-base.merge",
"notes": "Merges responses from all 4 AI engines into one stream.",
"position": [
1920,
300
],
"parameters": {
"mode": "combine",
"options": {},
"mergeByFields": {
"values": []
}
},
"notesInFlow": true,
"typeVersion": 3
},
{
"id": "8b5f065a-d543-41d8-b7f1-1324778e6ad8",
"name": "Analyze Citations",
"type": "n8n-nodes-base.code",
"notes": "Detects brand mentions, citation links, position rank, competitor SoV.",
"position": [
2140,
300
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "// Analyze each response for brand mentions, citations, links\nconst items = $input.all();\nconst results = [];\n\nitems.forEach(item => {\n const json = item.json;\n const brand = (json.brandName || '').toLowerCase();\n const competitors = json.competitors || [];\n\n let responseText = '';\n let engine = '';\n let citations = [];\n\n // Normalize response from each engine\n if (json.message?.content) {\n responseText = typeof json.message.content === 'string' ? json.message.content : JSON.stringify(json.message.content);\n engine = json.engine || 'chatgpt';\n } else if (json.choices?.[0]?.message?.content) {\n responseText = json.choices[0].message.content;\n engine = 'perplexity';\n if (json.citations) citations = json.citations;\n } else if (json.content) {\n responseText = json.content;\n engine = 'gemini';\n }\n\n const lowerResp = responseText.toLowerCase();\n\n // Check brand mention\n const brandMentioned = lowerResp.includes(brand);\n const brandMentionCount = (lowerResp.match(new RegExp(brand, 'g')) || []).length;\n\n // Check competitor mentions\n const compMentions = competitors.map(c => ({\n competitor: c,\n mentioned: lowerResp.includes(c.toLowerCase().split('.')[0]),\n count: (lowerResp.match(new RegExp(c.toLowerCase().split('.')[0], 'g')) || []).length\n }));\n\n // Citation score: 0-100\n const citationScore = Math.min(100, (brandMentionCount * 25) + (citations.length > 0 ? 20 : 0));\n\n // Position rank (1 = mentioned first)\n let brandPosition = 0;\n if (brandMentioned) {\n const brandIdx = lowerResp.indexOf(brand);\n const allMentions = [{name: brand, idx: brandIdx}, ...compMentions.filter(c => c.mentioned).map(c => ({name: c.competitor, idx: lowerResp.indexOf(c.competitor.toLowerCase().split('.')[0])}))];\n allMentions.sort((a, b) => a.idx - b.idx);\n brandPosition = allMentions.findIndex(m => m.name === brand) + 1;\n }\n\n results.push({\n json: {\n ...json,\n engine,\n responseText: responseText.slice(0, 2000),\n citations,\n brandMentioned,\n brandMentionCount,\n brandPosition,\n compMentions,\n citationScore,\n analyzedAt: new Date().toISOString()\n }\n });\n});\n\nreturn results;\n"
},
"notesInFlow": true,
"typeVersion": 2
},
{
"id": "04ea6bc8-df11-4e09-bde9-09f6f39055f5",
"name": "Z.ai GLM Recommendations",
"type": "n8n-nodes-base.httpRequest",
"notes": "Z.ai GLM-4.5 generates cost-effective optimization recommendations.",
"maxTries": 3,
"position": [
2360,
300
],
"parameters": {
"url": "https://open.bigmodel.cn/api/paas/v4/chat/completions",
"method": "POST",
"options": {
"response": {
"response": {
"neverError": true,
"fullResponse": false,
"responseFormat": "json"
}
}
},
"jsonBody": "={\"model\": \"glm-4.5\", \"messages\": [{\"role\": \"system\", \"content\": \"You are an AEO/GEO optimization expert. Given citation analysis data, output 3 specific actionable recommendations as JSON.\"}, {\"role\": \"user\", \"content\": \"{{ JSON.stringify($json) }}\"}], \"temperature\": 0.5, \"response_format\": {\"type\": \"json_object\"}}",
"sendBody": true,
"sendQuery": false,
"contentType": "json",
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"specifyHeaders": "keypair",
"genericAuthType": "httpHeaderAuth",
"queryParameters": {},
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 4,
"waitBetweenTries": 2000
},
{
"id": "0a7e4d14-5201-4944-be71-46c3e66ad71f",
"name": "Store Citation Data",
"type": "n8n-nodes-base.notion",
"notes": "Stores daily citation snapshot in Notion AEO Tracker database.",
"maxTries": 3,
"position": [
2580,
300
],
"parameters": {
"resource": "databasePage",
"operation": "create",
"databaseId": "NOTION_DB_AEO_TRACKER",
"propertiesUi": {
"propertyValues": [
{
"key": "Date|date",
"date": "={{ $today.toISODate() }}"
},
{
"key": "Engine|select",
"select_name": "={{ $json.engine }}"
},
{
"key": "Keyword|rich_text",
"richText": "={{ $json.keyword }}"
},
{
"key": "Brand Mentioned|checkbox",
"checkbox": "={{ $json.brandMentioned }}"
},
{
"key": "Mention Count|number",
"number": "={{ $json.brandMentionCount }}"
},
{
"key": "Position|number",
"number": "={{ $json.brandPosition }}"
},
{
"key": "Citation Score|number",
"number": "={{ $json.citationScore }}"
},
{
"key": "Client|select",
"select_name": "={{ $json.clientKey }}"
}
]
}
},
"credentials": {
"notionApi": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 2,
"waitBetweenTries": 2000
},
{
"id": "b7a42c98-fc43-4ca7-87cf-2addfc9e4c20",
"name": "Citation Dropped?",
"type": "n8n-nodes-base.if",
"notes": "Triggers alert if brand was previously mentioned but now absent.",
"position": [
2800,
300
],
"parameters": {
"options": {},
"conditions": {
"options": {
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"conditions": [
{
"operator": {
"type": "boolean",
"operation": "eq"
},
"leftValue": "={{ $json.brandMentioned }}",
"rightValue": "false"
}
]
}
},
"notesInFlow": true,
"typeVersion": 2
},
{
"id": "eac110f0-6ab2-47ed-91f0-d58fc72bf454",
"name": "Alert Citation Drop",
"type": "n8n-nodes-base.slack",
"notes": "Alerts team when brand citation is lost in any AI engine.",
"maxTries": 3,
"position": [
3020,
300
],
"parameters": {
"text": "=:warning: *Citation drop detected!*\n*Engine*: {{$json.engine}}\n*Keyword*: `{{$json.keyword}}`\n*Brand*: {{$json.brandName}} was NOT mentioned in today's response.\n*Competitors mentioned*: {{($json.compMentions || []).filter(c => c.mentioned).map(c => c.competitor).join(', ')}}\nReview the prompt and content strategy.",
"select": "channel",
"channelId": "={{ $json.clientKey === 'acme' ? 'C_ACME_SEO' : 'C_GLOBEX_SEO' }}",
"operation": "post",
"otherOptions": {}
},
"credentials": {
"slackApi": {
"name": "<your credential>"
}
},
"notesInFlow": true,
"retryOnFail": true,
"typeVersion": 2,
"waitBetweenTries": 2000
},
{
"id": "14e42818-fe95-4e8f-972a-7ba0f80509be",
"name": "Loop Continue",
"type": "n8n-nodes-base.code",
"notes": "Passes through for loop iteration.",
"position": [
3240,
300
],
"parameters": {
"mode": "runOnceForAllItems",
"jsCode": "return $input.all();"
},
"notesInFlow": true,
"typeVersion": 2
},
{
"id": "main",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-140,
-816
],
"parameters": {
"width": 760,
"height": 936,
"content": "## Track AI Search Citations (AEO / GEO)\n\nChecks whether ChatGPT, Claude, Gemini and Perplexity mention your brand when people ask about your topics, scores how often you are cited, stores the results in Notion, and alerts Slack when a brand mention disappears. Runs weekly or on demand, so you can measure your visibility inside AI answers, not just Google.\n\n**Who's it for:** SEO and content teams (and agencies) who need to know if AI search engines cite their brand.\n\n## How it works\n1. Builds a set of prompts from your brand and seed keywords.\n2. Sends each prompt to ChatGPT, Claude, Gemini and Perplexity.\n3. Analyzes every response for brand and competitor mentions.\n4. Asks an AEO model for improvement recommendations.\n5. Stores citation metrics in Notion and alerts Slack on any drop.\n\n## Setup\n1. Add credentials: OpenAI, Anthropic, Google Gemini, Perplexity (Header Auth), Z.ai (Header Auth), Notion, Slack.\n2. Open the Configuration node and set your brand, site URL, seed keywords and competitors.\n3. Create a Notion database for citation data and select it in Store Citation Data.\n4. Set your Slack channel.\n5. Run once with Test workflow, then activate the weekly schedule."
},
"typeVersion": 1
},
{
"id": "bg0",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
555,
205
],
"parameters": {
"color": "color7",
"width": 1340,
"height": 300,
"content": "## 1. Ask the AI engines"
},
"typeVersion": 1
},
{
"id": "bg1",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
1875,
205
],
"parameters": {
"color": "color7",
"width": 680,
"height": 300,
"content": "## 2. Analyze citations"
},
"typeVersion": 1
},
{
"id": "bg2",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
2535,
205
],
"parameters": {
"color": "color7",
"width": 900,
"height": 300,
"content": "## 3. Store & alert"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"connections": {
"Loop Prompts": {
"main": [
[
{
"node": "ChatGPT Response",
"type": "main",
"index": 0
}
]
]
},
"Configuration": {
"main": [
[
{
"node": "Prepare AEO Prompts",
"type": "main",
"index": 0
}
]
]
},
"Loop Continue": {
"main": [
[
{
"node": "Loop Prompts",
"type": "main",
"index": 0
}
]
]
},
"Manual Trigger": {
"main": [
[
{
"node": "Configuration",
"type": "main",
"index": 0
}
]
]
},
"Claude Response": {
"main": [
[
{
"node": "Gemini Response",
"type": "main",
"index": 0
}
]
]
},
"Gemini Response": {
"main": [
[
{
"node": "Perplexity Response",
"type": "main",
"index": 0
}
]
]
},
"ChatGPT Response": {
"main": [
[
{
"node": "Claude Response",
"type": "main",
"index": 0
}
]
]
},
"Analyze Citations": {
"main": [
[
{
"node": "Z.ai GLM Recommendations",
"type": "main",
"index": 0
}
]
]
},
"Citation Dropped?": {
"main": [
[
{
"node": "Alert Citation Drop",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop Continue",
"type": "main",
"index": 0
}
]
]
},
"Weekly Monday 9AM": {
"main": [
[
{
"node": "Configuration",
"type": "main",
"index": 0
}
]
]
},
"Merge AI Responses": {
"main": [
[
{
"node": "Analyze Citations",
"type": "main",
"index": 0
}
]
]
},
"Alert Citation Drop": {
"main": [
[
{
"node": "Loop Continue",
"type": "main",
"index": 0
}
]
]
},
"Perplexity Response": {
"main": [
[
{
"node": "Merge AI Responses",
"type": "main",
"index": 0
}
]
]
},
"Prepare AEO Prompts": {
"main": [
[
{
"node": "Loop Prompts",
"type": "main",
"index": 0
}
]
]
},
"Store Citation Data": {
"main": [
[
{
"node": "Citation Dropped?",
"type": "main",
"index": 0
}
]
]
},
"Z.ai GLM Recommendations": {
"main": [
[
{
"node": "Store Citation Data",
"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.
anthropicApigoogleGeminiApihttpHeaderAuthnotionApiopenAiApislackApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow runs weekly (or manually) to test multiple keyword prompts across ChatGPT, Claude, Gemini, and Perplexity, then analyzes whether your brand is mentioned, stores citation metrics in Notion, and sends a Slack alert when a brand mention is missing. Runs on a weekly…
Source: https://n8n.io/workflows/16731/ — 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.
💡 How It Works
IntelliX.AI - Editorial Automatizado v2. Uses postgres, rssFeedRead, openAi, httpRequest. Event-driven trigger; 62 nodes.
Marketing agencies, digital agencies, and freelancers who need to streamline their client onboarding process and create consistent, professional documentation for new clients. Perfect for teams handli
Clone_Viral_TikToks_with_AI_Avatars___Auto_Post_to_9_Platforms_using_Perplexity___Blotato. Uses httpRequest, telegramTrigger, openAi, googleSheets. Event-driven trigger; 42 nodes.
1-Clone_Viral_TikToks_with_AI_Avatars___Auto_Post_to_9_Platforms_using_Perplexity___Blotato. Uses httpRequest, telegramTrigger, openAi, googleSheets. Event-driven trigger; 42 nodes.