AutomationFlowsAI & RAG › Automated SEO Watchlist: Continuous Audits with Decodo, Gemini & Google Sheets

Automated SEO Watchlist: Continuous Audits with Decodo, Gemini & Google Sheets

ByRully Saputra @rullysaputra15 on n8n.io

Automate continuous SEO audits with Decodo and Gemini AI — live data, smart insights, and Google Sheets tracking with team alerts.

Cron / scheduled trigger★★★★☆ complexityAI-powered16 nodes@Decodo/N8N Nodes DecodoGoogle SheetsGoogle Gemini ChatOutput Parser StructuredChain LlmTelegram
AI & RAG Trigger: Cron / scheduled Nodes: 16 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #10689 — we link there as the canonical source.

This workflow follows the Chainllm → Google Sheets 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 →

Download .json
{
  "id": "Zx5WoAbZTSf18n4J",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "SEO Watchlist",
  "tags": [],
  "nodes": [
    {
      "id": "82daf0e8-8e16-4cbc-8e3b-e7479f34410c",
      "name": "Decodo",
      "type": "@decodo/n8n-nodes-decodo.decodo",
      "position": [
        -240,
        -272
      ],
      "parameters": {
        "url": "={{ $json.url }}"
      },
      "credentials": {
        "decodoApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "59b88a5c-c118-4b38-9d5b-718715a04f22",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1008,
        -256
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "daysInterval": 5
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "123b1816-aebd-445c-8d59-6da6237a7afc",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -688,
        -256
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "c276ad3c-11af-478a-855e-f24c92ca8d23",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -464,
        -256
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "54d54e11-3d6d-46b1-a7ac-b2956fb3a5ae",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -96,
        -112
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "bf125187-f623-4135-86e3-47b1e4f16d56",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        128,
        -112
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"url\": \"string\",\n  \"fetched_at\": \"ISO8601\",\n  \"status\": 200,\n  \"final_url\": \"string\",\n  \"summary\": {\n    \"page_type\": \"string\",\n    \"language\": \"string\",\n    \"primary_keyword\": \"string|null\",\n    \"overall_score\": 0.0\n  },\n  \"checks\": [\n    {\n      \"id\": \"title\",\n      \"status\": \"pass|warn|fail\",\n      \"score\": 0.0,       \n      \"details\": \"short string\",\n      \"evidence\": [\"title tag value\", \"...\"],\n      \"confidence\": 0.0  \n    }\n  ],\n  \"issues\": [\n    {\n      \"id\": \"missing_meta_description\",\n      \"severity\": \"critical|high|medium|low\",\n      \"message\": \"short string\",\n      \"location\": \"head|body|headers|http\",\n      \"examples\": [\"example fix snippet or replacement string\"],\n      \"priority\": 1,\n      \"estimated_impact\": \"high|medium|low\",\n      \"confidence\": 0.0\n    }\n  ],\n  \"recommendations\": [\n    {\n      \"id\": \"fix_title\",\n      \"severity\": \"high\",\n      \"instruction\": \"copyable instruction or code snippet\",\n      \"priority\": 1,\n      \"estimated_time_minutes\": 15,\n      \"confidence\": 0.85\n    }\n  ],\n  \"metrics\": {\n    \"content_word_count\": 0,\n    \"h1_count\": 0,\n    \"image_count\": 0,\n    \"images_missing_alt\": 0,\n    \"internal_links\": 0,\n    \"external_links\": 0,\n    \"word_density\": [{\"term\":\"x\",\"count\":0,\"density\":0.0}],\n    \"lighthouse\": {\"performance\":0,\"accessibility\":0,\"seo\":0,\"best_practices\":0}\n  }\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "d953e10d-8803-41ab-8030-9c1930d5b5c4",
      "name": "SEO Analyzer",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        0,
        -272
      ],
      "parameters": {
        "text": "=Input\n{{ JSON.stringify($json.results[0] )}}\n",
        "batching": {},
        "messages": {
          "messageValues": [
            {
              "message": "=# Role\n* act as an SEO expert\n\n# Instructions\n- Analyze the page, Return JSON based on schema, No explanation or extra text \u2014 only JSON\n- This is very important tasks, analyze carefully\n\n# CHECKS TO ANALYZE:\n* Metadata quality and duplication\n* Content length vs top 3 competitors (approx)\n* H1/H2 structure and keyword signaling\n* Schema.org types and common error\n* Page speed & CWV flags (LCP>2.5s, CLS>0.1, INP>200ms)\n* Mobile friendly\n* Images alt presence and size\n* Internal linking count and broken link detection (only flag if obvious)\n* Canonical alignment (canonical should point to final_url)\n* Noindex or X-Robots headers\n\n# SCORING:\nUse weights: \n* metadata 15\n* content 25\n* perf 20\n* index 15\n* links 10\n* schema 5\n* Provide `overall_score` 0..100."
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "19ee3c62-4603-434a-8a7a-10dea5c2d6ff",
      "name": "Google Gemini Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        160,
        80
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "25a50839-c9c1-4313-b8e0-0e06763f907c",
      "name": "Notify Team",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -128,
        -672
      ],
      "parameters": {
        "text": "=\u26a0\ufe0fINFORMATION\u26a0\ufe0f\n\nDate: {{ new Date() }}\nKindly check the gsheets for the latest analysis result\n",
        "chatId": "=",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "7a300660-f15b-4b09-9ec1-97b74233a6f1",
      "name": "Store Result",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        784,
        -160
      ],
      "parameters": {
        "columns": {
          "value": {
            "url": "={{ $json.url }}",
            "date": "={{ $json.time }}",
            "checks": "={{ $json.checks }}",
            "issues": "={{ $json.issues }}",
            "recommendations": "={{ $json.recommendations }}"
          },
          "schema": [
            {
              "id": "date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "url",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "checks",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "checks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "issues",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "issues",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recommendations",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recommendations",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 955620984,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1uvnAqq36EoJqdTN01oHCsQs7eqP0zVP3BM_ZJ7avepQ/edit#gid=955620984",
          "cachedResultName": "seo watchlist result"
        },
        "documentId": {
          "__rl": true,
          "mode": "url",
          "value": ""
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d6f00305-d35e-4cbe-aa42-af4968b44334",
      "name": "Mapping Result",
      "type": "n8n-nodes-base.code",
      "position": [
        448,
        -272
      ],
      "parameters": {
        "jsCode": "const checks = $input.first().json.output.checks.map((el) => {\n    return `${el.id} - Status: ${el.status} - Score: ${el.score} - ${el.details}`\n})\n\nconst issues = $input.first().json.output.issues.map((el) => {\n    return `${el.id} - Severity: ${el.severity} - Priority: ${el.priority} - ${el.location}`\n})\n\nconst recommendations = $input.first().json.output.recommendations.map((el) => {\n    return `${el.id} - Severity: ${el.severity} - Priority: ${el.priority} - ${el.instruction}`\n})\n\nreturn {\n  time: $input.first().json.output.fetched_at,\n  url: $input.first().json.output.final_url,\n  checks: checks.join(\"\\n\\n\"),\n  issues: issues.join(\"\\n\\n\"),\n  recommendations: recommendations.join(\"\\n\\n\")\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "13be0f47-4c4e-4436-8b6b-43613215ad1f",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -640,
        64
      ],
      "parameters": {
        "width": 720,
        "height": 480,
        "content": "## \u2705 Loop Over Items\n\nTakes each URL one-by-one and processes them separately. This keeps the workflow stable and organized.\n\n## \u2705 Decodo\n\nFetches live data from the website (title, content, tags, speed signals, etc.) so it can be analyzed.\n\n## \u2705 SEO Analyzer\n\nUses AI to review the website and create an SEO report based on scoring rules (content, metadata, links, speed, etc.).\n\n## \u2705 Structured Output Parser\n\nMakes sure the AI\u2019s answer comes back as clean, valid JSON. This prevents messy or unexpected text."
      },
      "typeVersion": 1
    },
    {
      "id": "a0aa3d15-d6fe-46b5-b0bd-4f0b49fbcd96",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -912
      ],
      "parameters": {
        "width": 208,
        "height": 400,
        "content": "## Notify Team (Telegram)\n\nSends a Telegram message telling the team the analysis is complete and results are in the sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "612dfbd1-1d55-4d9c-a233-69373f9b3629",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        -400
      ],
      "parameters": {
        "width": 208,
        "height": 400,
        "content": "## Store Result (Google Sheets)\n\nAdds a new row to the results sheet with the report for that URL, so results are saved historically."
      },
      "typeVersion": 1
    },
    {
      "id": "064068f6-1fcc-41ce-9d12-36cf31d2ce0c",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1472,
        -1040
      ],
      "parameters": {
        "color": 2,
        "width": 944,
        "height": 960,
        "content": "# Automated SEO Watchlist: Continuous Audits Powered by Decodo\n\n## \u2705 What this workflow does\nIt automatically audits website pages for SEO issues, stores results in Google Sheets, and notifies the team \u2014 completely hands-free.\n\n## \u2705 How it works\n- The workflow starts every 5 days on its own.\n- It reads a list of page URLs from Google Sheets.\n- Each page is processed one at a time for reliability.\n- Decodo \u2014 the main tech of this system \u2014 collects real content, tags, headings, speed signals, and more from each page.\n- AI analyzes the data using SEO best practices and creates a structured score/report.\n- Results are turned into short, human-friendly summaries.\n- A new entry is added to Google Sheets for tracking over time.\n- A Telegram message alerts the team when fresh results are ready.\n\n## \u2705 Why Decodo matters\nDecodo powers the entire audit \u2014 it pulls real, live page data so the AI can accurately judge SEO health.\nWithout Decodo, there\u2019s nothing to analyze.\n\n## \u2705 What you get\n- Automatic SEO auditing\n- Clear next steps and recommendations\n- Historical results stored as a log\n- No manual checking or reporting\n\n## \u2705 Great for\nMarketing teams, agencies, product sites, blogs, or anyone who wants continuous SEO monitoring with zero effort."
      },
      "typeVersion": 1
    },
    {
      "id": "f4989071-9c52-4f63-9397-8277eb29de2a",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        592,
        -256
      ],
      "parameters": {
        "width": 208,
        "height": 400,
        "content": "## Mapping Result (Code)\n\nTurns the JSON report into short, readable summaries (checks, issues, recommendations) and prepares them for Sheets."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "1e3a9a25-0d7f-45e7-9822-66decde09df0",
  "connections": {
    "Decodo": {
      "main": [
        [
          {
            "node": "SEO Analyzer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SEO Analyzer": {
      "main": [
        [
          {
            "node": "Mapping Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Store Result": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mapping Result": {
      "main": [
        [
          {
            "node": "Store Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Notify Team",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Decodo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "SEO Analyzer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "SEO Analyzer",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Structured Output Parser",
            "type": "ai_languageModel",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Automate continuous SEO audits with Decodo and Gemini AI — live data, smart insights, and Google Sheets tracking with team alerts.

Source: https://n8n.io/workflows/10689/ — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Effortlessly generate, review, and publish SEO-optimized blog posts to WordPress using AI and automation.

WordPress, Google Gemini Chat, Output Parser Structured +6
AI & RAG

Sign up for Decodo — get better pricing here

@Decodo/N8N Nodes Decodo, Google Gemini Chat, Output Parser Structured +5
AI & RAG

Sign up for Decodo HERE for Discount

Google Sheets, Google Gemini Chat, Output Parser Structured +2
AI & RAG

Sign up for Decodo HERE for Discount

Google Gemini Chat, Chain Llm, Output Parser Structured +3
AI & RAG

This workflow contains community nodes that are only compatible with the self-hosted version of n8n.

Telegram Trigger, Google Sheets, Telegram +6