
Weekly SEO Watchlist Audit to Google Sheets with Gemini and Decodo
描述
分类
📢 Marketing🤖 AI & Machine Learning
使用的节点
n8n-nodes-base.setn8n-nodes-base.coden8n-nodes-base.coden8n-nodes-base.noOpn8n-nodes-base.mergen8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNoten8n-nodes-base.stickyNote
价格免费
浏览量0
最后更新11/28/2025
workflow.json
{
"meta": {
"instanceId": "689fa22e68cd4198e4ae37f3cc44f498087edd235a867e22515be823bab694c7",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "86c62450-e1e0-46b6-af12-610c8ee01d99",
"name": "Done",
"type": "n8n-nodes-base.noOp",
"position": [
2560,
672
],
"parameters": {},
"typeVersion": 1
},
{
"id": "59e31df6-6f38-4005-a739-8fe91b2686ba",
"name": "Read Input URLs (Google Sheets)",
"type": "n8n-nodes-base.googleSheets",
"position": [
2112,
864
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1quBpAwPIcUzjPERE2icKM-bhKnoe7cJvz1-UK81aKVE/edit#gid=0",
"cachedResultName": "Input"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $json.sheet_id }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "TOelCQp3VgiaqzOT",
"name": "Google Sheets - Kevin"
}
},
"typeVersion": 4.7
},
{
"id": "c3c71ccf-8f5d-41e2-ab8b-71d64ee4fc72",
"name": "Loop URLs (Split in Batches)",
"type": "n8n-nodes-base.splitInBatches",
"position": [
2336,
864
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "cd40c863-11ac-4cec-9eed-2e7c70f23dec",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
944,
464
],
"parameters": {
"width": 576,
"height": 720,
"content": "## Weekly SEO Watchlist Audit to Google Sheets (Gemini + Decodo)\n\nSign up for Decodo [HERE](https://visit.decodo.com/discount) for Discount\n\nAutomatically fetches page content, generates a compact SEO audit (score, issues, fixes), and writes both a per-URL summary and a normalized “All Issues” table to Google Sheets—great for weekly monitoring and prioritization.\n\n## Who’s it for?\nContent/SEO teams that want lightweight, scheduled audits of key pages with actionable next steps and spreadsheet reporting.\n\n## How it works\n1. Weekly trigger loads the Google Sheet of URLs.\n2. Split in Batches processes each URL.\n3. Decodo fetches page content (markdown + status).\n4. Gemini produces a strict JSON audit via the AI Chain + Output Parser.\n5. Code nodes flatten data for two tabs.\n6. Google Sheets nodes append Summary and All Issues rows.\n7. Split in Batches continues to the next URL.\n\n## How to set up\n- Add credentials for Google Sheets, [Decodo](https://visit.decodo.com/discount), and Gemini.\n- Set `sheet_id` and Sheet GIDs in the Set node.\n- Ensure input sheet has a `URL` column.\n- Configure your Google Sheets tabs with proper headers matching each field being appended (e.g., URL, Decodo Score, Priority, etc.).\n- Adjust schedule as needed.\n- Activate the workflow.\n"
},
"typeVersion": 1
},
{
"id": "1e47c593-bd87-443f-b5ba-b01efa82cdf8",
"name": "AI Model: Google Gemini",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"position": [
2800,
1088
],
"parameters": {
"options": {}
},
"credentials": {
"googlePalmApi": {
"id": "858IDdJ9nuIsYkCZ",
"name": "Hendra Gemini"
}
},
"typeVersion": 1
},
{
"id": "92eaa21b-d44a-4787-9c54-7e7d3207d347",
"name": "Output Parser: Enforce SEO JSON",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
2928,
1088
],
"parameters": {
"schemaType": "manual",
"inputSchema": "{\n \"output\": [\n {\n \"url\": \"string\",\n \"decodo_score\": 0,\n \"top_issues\": \"string\",\n \"priority\": \"High|Medium|Low\",\n \"recommended_actions\": [\"string\"],\n \"suggested_meta\": \"string\",\n \"suggested_title\": \"string\",\n \"status\": \"ok|no_content|error\",\n \"raw_decodo\": {},\n \"last_checked\": \"string\",\n \"all_issues\": [\n {\n \"id\": \"string\",\n \"title\": \"string\",\n \"category\": \"On-Page|Technical|Content|Performance|Accessibility|Indexing|Internal Linking|Other\",\n \"severity\": \"High|Medium|Low\",\n \"evidence\": \"string\",\n \"recommendation\": \"string\",\n \"impact\": \"High|Medium|Low\",\n \"effort\": \"Low|Medium|High\",\n \"score_delta\": -1,\n \"examples\": [\"string\"]\n }\n ]\n }\n ]\n}\n"
},
"typeVersion": 1.3
},
{
"id": "e4c7f3c3-21dd-4bb6-b3d9-1276e60ef63e",
"name": "Trigger: Weekly",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
1664,
864
],
"parameters": {
"rule": {
"interval": [
{
"field": "weeks"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "de019aee-a770-4b76-a52e-7cf4e0ce9298",
"name": "Decodo: Fetch Page Content",
"type": "@decodo/n8n-nodes-decodo.decodo",
"onError": "continueRegularOutput",
"position": [
2560,
864
],
"parameters": {
"geo": "",
"url": "={{ $json.URL_list }}"
},
"credentials": {
"decodoApi": {
"id": "kfy3Vs5AgxfDGzpC",
"name": "Johan Decodo"
}
},
"retryOnFail": true,
"typeVersion": 1
},
{
"id": "59484847-90ae-4ff6-96f5-df85847b0c2f",
"name": "Generate SEO Audit",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
2784,
864
],
"parameters": {
"text": "=System:\nYou are an SEO Watchlist Agent.\nReturn only a valid JSON object and nothing else.\nOutput MUST be exactly this shape (no extra keys, no markdown):\n{\"output\":[{...}]}\nDo not return plain objects, arrays, strings, or explanations.\nAll numbers must be numeric (not strings).\nIf a field has no data, use null (except raw_decodo must be {}).\n\nUser:\nAnalyze the following webpage content (markdown) and produce an SEO audit JSON object.\n\nINPUT\n- url_hint: {{ $('Loop URLs (Split in Batches)').item.json.URL_list }}\n- status_code: {{ $json.data.results[0].status_code }}\n- fetched_at: {{ $json.data.results[0].updated_at }}\n- content:\n{{ $json.data.results[0].content }}\n\nREQUIREMENTS\nReturn only this JSON object (with the \"output\" wrapper and a single-item array):\n\n{\n \"output\": [\n {\n \"url\": \"string\",\n \"decodo_score\": 0,\n \"top_issues\": \"semicolon-separated list of 3–5 key issues\",\n \"priority\": \"High|Medium|Low\",\n \"recommended_actions\": [\"up to 10 short, actionable fixes\"],\n \"suggested_meta\": \"120–155 chars\",\n \"suggested_title\": \"≤70 chars\",\n \"status\": \"ok|no_content|error\",\n \"raw_decodo\": {},\n \"last_checked\": \"UTC ISO 8601 with Z\",\n \"all_issues\": [\n {\n \"id\": \"kebab-case identifier\",\n \"title\": \"short issue name\",\n \"category\": \"On-Page|Technical|Content|Performance|Accessibility|Indexing|Internal Linking|Other\",\n \"severity\": \"High|Medium|Low\",\n \"evidence\": \"≤240 chars concrete proof from the page text\",\n \"recommendation\": \"how to fix\",\n \"impact\": \"High|Medium|Low\",\n \"effort\": \"Low|Medium|High\",\n \"score_delta\": -1,\n \"examples\": [\"example selector/url/snippet\"]\n }\n ]\n }\n ]\n}\n\nSCORING & RULES\n- \"url\": use url_hint if present; otherwise null.\n- \"status\": \"no_content\" if content is empty/null/whitespace; else \"ok\".\n- \"last_checked\": current UTC timestamp with Z.\n- \"decodo_score\": 0–100 based on on-page basics + content quality.\n- Order \"all_issues\" High → Medium → Low; max 10 items.\n- Evidence must come only from provided content (≤240 chars).\n- If content empty: status=\"no_content\", priority=\"Low\", decodo_score=0, top_issues=\"No content detected\", recommended_actions=[], all_issues=[].\n\nSTRICT OUTPUT RULES\n- Return exactly one JSON object with a top-level \"output\" key whose value is an array with exactly one object.\n- Do not emit any keys other than \"output\".\n- Do not include code fences, prose, or additional arrays/objects.\n",
"batching": {},
"messages": {
"messageValues": [
{
"message": "=You are an SEO Watchlist Agent.\nReturn only a valid JSON object that matches the specified schema.\nDo not include explanations, markdown, or arrays.\nAll numbers must be numeric, not strings."
},
{
"type": "AIMessagePromptTemplate",
"message": "={\n \"output\": [\n {\n \"url\": \"string\",\n \"decodo_score\": 0,\n \"top_issues\": \"semicolon-separated list of 3–5 key issues\",\n \"priority\": \"High|Medium|Low\",\n \"recommended_actions\": [\"up to 10 short, actionable fixes\"],\n \"suggested_meta\": \"120–155 chars\",\n \"suggested_title\": \"≤70 chars\",\n \"status\": \"ok|no_content|error\",\n \"raw_decodo\": {},\n \"last_checked\": \"UTC ISO 8601 with Z\",\n \"all_issues\": [\n {\n \"id\": \"kebab-case identifier\",\n \"title\": \"short issue name\",\n \"category\": \"On-Page|Technical|Content|Performance|Accessibility|Indexing|Internal Linking|Other\",\n \"severity\": \"High|Medium|Low\",\n \"evidence\": \"≤240 chars concrete proof from the page text\",\n \"recommendation\": \"how to fix\",\n \"impact\": \"High|Medium|Low\",\n \"effort\": \"Low|Medium|High\",\n \"score_delta\": -1,\n \"examples\": [\"example selector/url/snippet\"]\n }\n ]\n }\n ]\n}"
}
]
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 1.7
},
{
"id": "83ce0059-037d-46e6-afb7-b7d9b4e13603",
"name": "Transform: Summary Row",
"type": "n8n-nodes-base.code",
"position": [
3136,
768
],
"parameters": {
"jsCode": "const data = $json.output?.[0] ?? {};\nreturn [{\n url: data.url,\n decodo_score: data.decodo_score,\n top_issues: data.top_issues,\n priority: data.priority,\n suggested_title: data.suggested_title,\n suggested_meta: data.suggested_meta,\n status: data.status,\n last_checked: data.last_checked,\n // optional: ubah jadi JSON string supaya tetap 1 kolom\n recommended_actions: (data.recommended_actions || []).join('\\n'),\n all_issues: JSON.stringify(data.all_issues || [])\n}];\n"
},
"typeVersion": 2
},
{
"id": "af1007cb-3c36-4138-b327-2a8ca05ab2f8",
"name": "Google Sheets: Append Summary",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
3360,
768
],
"parameters": {
"columns": {
"value": {
"URL": "={{ $json.url }}",
"Status": "={{ $json.status }}",
"Priority": "={{ $json.priority }}",
"Top Issues": "={{ $json.top_issues }}",
"Decodo Score": "={{ $json.decodo_score }}",
"Last Checked": "={{ $json.last_checked }}",
"Suggested Meta": "={{ $json.suggested_meta }}",
"Suggested Title": "={{ $json.suggested_title }}",
"Recommended Actions": "={{ $json.recommended_actions }}"
},
"schema": [
{
"id": "URL",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Decodo Score",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Decodo Score",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Top Issues",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Top Issues",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Priority",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Priority",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Status",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Suggested Title",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Suggested Title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Suggested Meta",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Suggested Meta",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Last Checked",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Last Checked",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Recommended Actions",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "Recommended Actions",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 2024550449,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1quBpAwPIcUzjPERE2icKM-bhKnoe7cJvz1-UK81aKVE/edit#gid=2024550449",
"cachedResultName": "Output"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Set: Configure Workflow').item.json.sheet_id }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "TOelCQp3VgiaqzOT",
"name": "Google Sheets - Kevin"
}
},
"typeVersion": 4.7
},
{
"id": "b339a9c2-5fd2-4a60-9780-ad6a238fe081",
"name": "Transform: Explode Issues",
"type": "n8n-nodes-base.code",
"position": [
3136,
960
],
"parameters": {
"jsCode": "const data = $json.output?.[0];\nif (!data || !Array.isArray(data.all_issues)) return [];\nreturn data.all_issues.map(issue => ({\n url: data.url,\n id: issue.id,\n title: issue.title,\n category: issue.category,\n severity: issue.severity,\n evidence: issue.evidence,\n recommendation: issue.recommendation,\n impact: issue.impact,\n effort: issue.effort,\n score_delta: issue.score_delta,\n examples: (issue.examples || []).join(\"; \")\n}));"
},
"typeVersion": 2
},
{
"id": "3c4daffd-10a8-4414-8f9a-212e55241bc0",
"name": "Google Sheets: Append Issues",
"type": "n8n-nodes-base.googleSheets",
"onError": "continueRegularOutput",
"position": [
3360,
960
],
"parameters": {
"columns": {
"value": {
"URL": "={{ $json.url }}",
"Title": "={{ $json.title }}",
"Effort": "={{ $json.effort }}",
"Impact": "={{ $json.impact }}",
"Category": "={{ $json.category }}",
"Evidence": "={{ $json.evidence }}",
"Examples": "={{ $json.examples }}",
"Issue ID": "={{ $json.id }}",
"Severity": "={{ $json.severity }}",
"Score Delta": "={{ $json.score_delta }}",
"Recommendation": "={{ $json.recommendation }}"
},
"schema": [
{
"id": "URL",
"type": "string",
"display": true,
"required": false,
"displayName": "URL",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Issue ID",
"type": "string",
"display": true,
"required": false,
"displayName": "Issue ID",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Title",
"type": "string",
"display": true,
"required": false,
"displayName": "Title",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Category",
"type": "string",
"display": true,
"required": false,
"displayName": "Category",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Severity",
"type": "string",
"display": true,
"required": false,
"displayName": "Severity",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Evidence",
"type": "string",
"display": true,
"required": false,
"displayName": "Evidence",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Recommendation",
"type": "string",
"display": true,
"required": false,
"displayName": "Recommendation",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Impact",
"type": "string",
"display": true,
"required": false,
"displayName": "Impact",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Effort",
"type": "string",
"display": true,
"required": false,
"displayName": "Effort",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Score Delta",
"type": "string",
"display": true,
"required": false,
"displayName": "Score Delta",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "Examples",
"type": "string",
"display": true,
"required": false,
"displayName": "Examples",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": 1837304635,
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1quBpAwPIcUzjPERE2icKM-bhKnoe7cJvz1-UK81aKVE/edit#gid=1837304635",
"cachedResultName": "All Issues"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "={{ $('Set: Configure Workflow').item.json.sheet_id }}"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "TOelCQp3VgiaqzOT",
"name": "Google Sheets - Kevin"
}
},
"typeVersion": 4.7
},
{
"id": "15bee2a7-4865-4864-b7d8-4be5c159235a",
"name": "Join Summary + Issues",
"type": "n8n-nodes-base.merge",
"position": [
3584,
960
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "cefd0438-5e52-476e-922e-cdadd984d860",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
1616,
752
],
"parameters": {
"color": 4,
"width": 192,
"height": 272,
"content": "### Adjust interval to your reporting cadence (e.g., every Monday 09:00 UTC)."
},
"typeVersion": 1
},
{
"id": "de45ca35-5e5b-4c2f-8648-06a3d535d6d9",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1840,
752
],
"parameters": {
"color": 4,
"width": 192,
"height": 272,
"content": "### Enter sheet_id for Input, Output, and All Issues tabs."
},
"typeVersion": 1
},
{
"id": "3e3b1dc4-e3fb-4f46-ad91-9597d62fb676",
"name": "Set: Configure Workflow",
"type": "n8n-nodes-base.set",
"position": [
1888,
864
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "16ed2967-7c19-48ad-86c1-10367f650253",
"name": "sheet_id",
"type": "string",
"value": "change me!"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "905b51b3-a594-4e84-ba46-b03fecb3ca38",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
2064,
752
],
"parameters": {
"color": 4,
"width": 192,
"height": 288,
"content": "### Make sure your Input tab contains a column named URL.\n"
},
"typeVersion": 1
},
{
"id": "7749b33c-a7af-4ea3-af31-45e473424408",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
3312,
640
],
"parameters": {
"color": 4,
"width": 192,
"height": 480,
"content": "### Ensure all columns match the expected field names in this node."
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"Trigger: Weekly": {
"main": [
[
{
"node": "Set: Configure Workflow",
"type": "main",
"index": 0
}
]
]
},
"Generate SEO Audit": {
"main": [
[
{
"node": "Transform: Summary Row",
"type": "main",
"index": 0
},
{
"node": "Transform: Explode Issues",
"type": "main",
"index": 0
}
]
]
},
"Join Summary + Issues": {
"main": [
[
{
"node": "Loop URLs (Split in Batches)",
"type": "main",
"index": 0
}
]
]
},
"Transform: Summary Row": {
"main": [
[
{
"node": "Google Sheets: Append Summary",
"type": "main",
"index": 0
}
]
]
},
"AI Model: Google Gemini": {
"ai_languageModel": [
[
{
"node": "Generate SEO Audit",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Set: Configure Workflow": {
"main": [
[
{
"node": "Read Input URLs (Google Sheets)",
"type": "main",
"index": 0
}
]
]
},
"Transform: Explode Issues": {
"main": [
[
{
"node": "Google Sheets: Append Issues",
"type": "main",
"index": 0
}
]
]
},
"Decodo: Fetch Page Content": {
"main": [
[
{
"node": "Generate SEO Audit",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets: Append Issues": {
"main": [
[
{
"node": "Join Summary + Issues",
"type": "main",
"index": 1
}
]
]
},
"Loop URLs (Split in Batches)": {
"main": [
[
{
"node": "Done",
"type": "main",
"index": 0
}
],
[
{
"node": "Decodo: Fetch Page Content",
"type": "main",
"index": 0
}
]
]
},
"Google Sheets: Append Summary": {
"main": [
[
{
"node": "Join Summary + Issues",
"type": "main",
"index": 0
}
]
]
},
"Output Parser: Enforce SEO JSON": {
"ai_outputParser": [
[
{
"node": "Generate SEO Audit",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Read Input URLs (Google Sheets)": {
"main": [
[
{
"node": "Loop URLs (Split in Batches)",
"type": "main",
"index": 0
}
]
]
}
}
}