This workflow corresponds to n8n.io template #15119 — we link there as the canonical source.
This workflow follows the Agent → 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": "1blKL30BZbXvbsoX",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Generative Engine Optimization (GEO) Content Booster",
"tags": [],
"nodes": [
{
"id": "9b6d6858-99ff-46f2-8d07-5c79465f1bfa",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
0,
-64
],
"parameters": {
"width": 960,
"height": 944,
"content": "## Generative Engine Optimization (GEO) Content Booster\n\nThis workflow automatically monitors blog posts or product pages for new/updated content, analyzes Google AI Overviews to identify optimization gaps, auto-generates optimized titles, summaries, and schema markup, and applies these improvements to enhance visibility in AI search results.\n\n### Who's it for\n\u2022 SEO managers optimizing for AI-driven search results\n\u2022 Content teams publishing 5+ articles per week\n\u2022 E-commerce teams managing product page visibility\n\u2022 Digital marketers tracking AI Overview presence\n\n### How it works / What it does\n1. Detects new or updated blog posts / product pages via webhook or schedule\n2. Fetches raw content and existing metadata\n3. Queries Google Search API to analyze AI Overview coverage gaps\n4. AI generates optimized title, meta summary, and JSON-LD schema markup\n5. Pushes improvements back to CMS or target endpoint\n6. Logs all changes and scores to Google Sheet tracker\n\n### How to set up\n1. Import this workflow\n2. Set up credentials (Google Search API, OpenAI/Anthropic, CMS/HTTP, Google Sheets)\n3. Update your site URL and content preferences\n4. Activate workflow\n\n### Requirements\n\u2022 Webhook endpoint or CMS trigger\n\u2022 Google Custom Search API key\n\u2022 OpenAI / Anthropic / Grok API\n\u2022 CMS REST API or target HTTP endpoint\n\u2022 Google Sheets for tracking\n\n### How to customize the workflow\n\u2022 Change AI tone and schema type in the AI node\n\u2022 Modify Python keyword/gap detection logic\n\u2022 Update Google Sheet columns and Sheet ID\n\u2022 Adjust polling interval or wait times"
},
"typeVersion": 1
},
{
"id": "7f4d83fb-9773-48ab-92fb-0ecfff25c728",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1072,
272
],
"parameters": {
"color": 4,
"width": 760,
"height": 500,
"content": "## 1. Trigger & Content Intake"
},
"typeVersion": 1
},
{
"id": "5510df8f-8e5c-42b0-91bf-344bd70cc5e4",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1872,
256
],
"parameters": {
"color": 3,
"width": 1104,
"height": 640,
"content": "## 2. AI Overview Gap Analysis"
},
"typeVersion": 1
},
{
"id": "c3fb0111-5dfa-4150-9a65-da7587692e48",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
3008,
224
],
"parameters": {
"color": 6,
"width": 980,
"height": 600,
"content": "## 3. GEO Optimization & Publish"
},
"typeVersion": 1
},
{
"id": "ce3f6556-dd5d-4018-8114-796ef1bac83c",
"name": "Webhook - New or Updated Content",
"type": "n8n-nodes-base.webhook",
"position": [
1232,
384
],
"parameters": {
"path": "geo-content-inbound",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 1.1
},
{
"id": "dfce174f-6af6-44dc-9fb5-e0deb48a67d5",
"name": "Poll CMS for Updated Pages",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
1232,
592
],
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 */6 * * *"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "066195c8-c234-41a9-9355-92737c4c1006",
"name": "Prepare Content Context",
"type": "n8n-nodes-base.set",
"position": [
1472,
480
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"name": "pageUrl",
"type": "string",
"value": "={{ $json.url || $json.body?.url || '' }}"
},
{
"name": "pageTitle",
"type": "string",
"value": "={{ $json.title || $json.body?.title || '' }}"
},
{
"name": "pageContent",
"type": "string",
"value": "={{ $json.content || $json.body?.content || $json.body || '' }}"
},
{
"name": "pageType",
"type": "string",
"value": "={{ $json.type || $json.body?.type || 'blog' }}"
},
{
"name": "existingMeta",
"type": "string",
"value": "={{ $json.meta || $json.body?.meta || '' }}"
},
{
"name": "contentId",
"type": "string",
"value": "={{ $json.id || $json.body?.id || Date.now().toString() }}"
},
{
"name": "targetKeyword",
"type": "string",
"value": "={{ $json.keyword || $json.body?.keyword || '' }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "fe007108-65ab-481c-86cf-6d7c0cb30ea9",
"name": "Fetch Google AI Overview Data",
"type": "n8n-nodes-base.httpRequest",
"position": [
1888,
480
],
"parameters": {
"url": "=https://www.googleapis.com/customsearch/v1?key=YOUR_GOOGLE_API_KEY&cx=YOUR_SEARCH_ENGINE_ID&q={{ encodeURIComponent($json.targetKeyword || $json.pageTitle) }}&num=5",
"options": {}
},
"typeVersion": 4.2
},
{
"id": "bbf69c13-d111-4bd7-a398-bd76adea87bc",
"name": "Python - Detect GEO Gaps",
"type": "n8n-nodes-base.code",
"position": [
2128,
480
],
"parameters": {
"mode": "runOnceForEachItem",
"language": "python"
},
"typeVersion": 2
},
{
"id": "82e2a78c-bd29-4678-a02c-a5da0f046ec2",
"name": "Filter Pages Needing Optimization",
"type": "n8n-nodes-base.filter",
"position": [
2352,
480
],
"parameters": {
"options": {},
"conditions": {
"conditions": [
{
"operator": {
"type": "boolean",
"operation": "true"
},
"leftValue": "={{ $json.hasGeoGap }}"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "bbe3dc5e-8c38-4dde-af13-5b51209d55aa",
"name": "Wait 1 - Rate Limit",
"type": "n8n-nodes-base.wait",
"position": [
2528,
480
],
"parameters": {},
"typeVersion": 1
},
{
"id": "1d808144-1aa2-4a4b-96dd-41bec42d9795",
"name": "AI - Generate GEO Optimizations",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
2704,
480
],
"parameters": {
"text": "=Act as an expert SEO strategist specializing in Generative Engine Optimization (GEO) for Google AI Overviews and AI-driven search results.\n\nPage Details:\nURL: {{ $json.pageUrl }}\nType: {{ $json.pageType }}\nCurrent Title: {{ $json.pageTitle }}\nTarget Keyword: {{ $json.targetKeyword }}\nExisting Meta: {{ $json.existingMeta }}\n\nContent Snippet:\n{{ ($json.pageContent || '').substring(0, 800) }}\n\nIdentified GEO Gaps:\n{{ $json.geoGapSummary || 'Missing structured answers, low entity coverage, weak schema.' }}\n\nTop Competing Snippets from Google:\n{{ $json.competitorSnippets || 'No data available.' }}\n\nYour task:\n1. Write an optimized SEO title (60 chars max) that improves AI Overview inclusion chances.\n2. Write a concise meta description / AI summary (155 chars max) with direct answer format.\n3. Generate a valid JSON-LD schema markup (Article or Product depending on page type) with all recommended fields for AI crawlers.\n4. Provide a GEO score (0-100) estimating the page's current AI Overview readiness.\n\nRespond ONLY in this exact JSON format:\n{\n \"optimizedTitle\": \"...\",\n \"optimizedSummary\": \"...\",\n \"schemaMarkup\": { ... },\n \"geoScore\": 0,\n \"recommendations\": \"...\"\n}",
"options": {},
"promptType": "define"
},
"typeVersion": 1.6
},
{
"id": "d9225991-0699-4924-a46a-58094158dff1",
"name": "JS - Format GEO Output",
"type": "n8n-nodes-base.code",
"position": [
3088,
480
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const item = $input.item.json;\nlet aiOutput = {};\ntry {\n const raw = item.output || item.response || item.text || '{}';\n const clean = raw.replace(/```json|```/g, '').trim();\n aiOutput = JSON.parse(clean);\n} catch (e) {\n aiOutput = {\n optimizedTitle: item.pageTitle || 'Optimized Page Title',\n optimizedSummary: 'AI-optimized summary pending manual review.',\n schemaMarkup: {},\n geoScore: 0,\n recommendations: 'Manual review required.'\n };\n}\nreturn {\n json: {\n ...item,\n optimizedTitle: aiOutput.optimizedTitle || '',\n optimizedSummary: aiOutput.optimizedSummary || '',\n schemaMarkup: JSON.stringify(aiOutput.schemaMarkup || {}),\n geoScore: aiOutput.geoScore || 0,\n recommendations: aiOutput.recommendations || '',\n status: 'Optimized',\n processedDate: new Date().toISOString().split('T')[0],\n processedAt: new Date().toISOString()\n }\n};"
},
"typeVersion": 2
},
{
"id": "055ae27e-7cde-412c-b81e-e5ae4b573bae",
"name": "Wait 2 - Review Buffer",
"type": "n8n-nodes-base.wait",
"position": [
3248,
480
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d70f0144-b884-4d7f-802a-1b3279fba463",
"name": "Push Optimizations to CMS",
"type": "n8n-nodes-base.httpRequest",
"position": [
3472,
384
],
"parameters": {
"url": "=https://your-cms-api.com/api/pages/{{ $json.contentId }}",
"method": "PATCH",
"options": {},
"jsonBody": "={\n \"title\": \"{{ $json.optimizedTitle }}\",\n \"meta_description\": \"{{ $json.optimizedSummary }}\",\n \"schema_markup\": {{ $json.schemaMarkup }},\n \"geo_optimized\": true,\n \"geo_score\": {{ $json.geoScore }}\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": "3b95bb94-2ac7-473a-96b9-0a541c99d955",
"name": "Update GEO Tracker Sheet",
"type": "n8n-nodes-base.httpRequest",
"position": [
3472,
608
],
"parameters": {
"url": "https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID/values/GEO_Tracker!A1:append?valueInputOption=USER_ENTERED",
"method": "POST",
"options": {},
"jsonBody": "={\n \"values\": [[\"{{ $json.processedDate }}\", \"{{ $json.pageUrl }}\", \"{{ $json.pageType }}\", \"{{ $json.targetKeyword }}\", \"{{ $json.optimizedTitle }}\", \"{{ $json.geoScore }}\", \"Optimized\", \"{{ $json.recommendations }}\", \"{{ $json.processedAt }}\"]]\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": "1fe3c865-71d3-4843-80df-c8f6a7d9c84a",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
2672,
704
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4.1-mini"
},
"options": {},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "c4f09534-4545-4b2a-ac75-9464e7f9de35",
"name": "Wait For Data",
"type": "n8n-nodes-base.wait",
"position": [
1680,
480
],
"parameters": {},
"typeVersion": 1.1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "d72c2ef2-6106-4dd3-93a0-9abb4d64f043",
"connections": {
"Wait For Data": {
"main": [
[
{
"node": "Fetch Google AI Overview Data",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI - Generate GEO Optimizations",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Wait 1 - Rate Limit": {
"main": [
[
{
"node": "AI - Generate GEO Optimizations",
"type": "main",
"index": 0
}
]
]
},
"JS - Format GEO Output": {
"main": [
[
{
"node": "Wait 2 - Review Buffer",
"type": "main",
"index": 0
}
]
]
},
"Wait 2 - Review Buffer": {
"main": [
[
{
"node": "Push Optimizations to CMS",
"type": "main",
"index": 0
},
{
"node": "Update GEO Tracker Sheet",
"type": "main",
"index": 0
}
]
]
},
"Prepare Content Context": {
"main": [
[
{
"node": "Wait For Data",
"type": "main",
"index": 0
}
]
]
},
"Python - Detect GEO Gaps": {
"main": [
[
{
"node": "Filter Pages Needing Optimization",
"type": "main",
"index": 0
}
]
]
},
"Poll CMS for Updated Pages": {
"main": [
[
{
"node": "Prepare Content Context",
"type": "main",
"index": 0
}
]
]
},
"Fetch Google AI Overview Data": {
"main": [
[
{
"node": "Python - Detect GEO Gaps",
"type": "main",
"index": 0
}
]
]
},
"AI - Generate GEO Optimizations": {
"main": [
[
{
"node": "JS - Format GEO Output",
"type": "main",
"index": 0
}
]
]
},
"Webhook - New or Updated Content": {
"main": [
[
{
"node": "Prepare Content Context",
"type": "main",
"index": 0
}
]
]
},
"Filter Pages Needing Optimization": {
"main": [
[
{
"node": "Wait 1 - Rate Limit",
"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.
openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically monitors blog posts or product pages for new/updated content, analyzes Google AI Overviews to identify optimization gaps, auto-generates optimized titles, summaries, and schema markup, and applies these improvements to enhance visibility in AI search…
Source: https://n8n.io/workflows/15119/ — 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
L&D_AgentsAI_ATIVO. Uses httpRequest, agent, googleCalendarTool, toolSerpApi. Webhook trigger; 93 nodes.
CLINICAINTEGRAL_secretary. Uses postgres, mcpClientTool, googleDriveTool, toolWorkflow. Webhook trigger; 89 nodes.
Remi 1.1. Uses lmChatOpenAi, memoryPostgresChat, openAi, postgres. Webhook trigger; 89 nodes.
This n8n workflow orchestrates a powerful suite of AI Agents and automations to manage and optimize various aspects of an e-commerce operation, particularly for platforms like Shopify. It leverages La