AutomationFlowsData & Sheets › Sitemap.xml Metadata Export to Google Sheets (title, Meta Description, and Urls)

Sitemap.xml Metadata Export to Google Sheets (title, Meta Description, and Urls)

ByJemee @jemeeroy on n8n.io

This workflow automates the extraction of SEO metadata (URL, page title, and meta description) from every page listed in your website's sitemap and exports it to Google Sheets. Ideal for SEO audits, content inventories, and tracking on-page elements.

Event trigger★★★★☆ complexity12 nodesGoogle SheetsHTTP Request
Data & Sheets Trigger: Event Nodes: 12 Complexity: ★★★★☆ Added:

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

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

Download .json
{
  "nodes": [
    {
      "id": "a34c9e89-88bc-4b65-8fb0-906d96623f24",
      "name": "Append or update row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1632,
        128
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $json.loc }}",
            "Title": "={{ $json.title }}",
            "meta description": "={{ $json.description }}"
          },
          "schema": [
            {
              "id": "Title",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Title",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "meta description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "meta description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "URL"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1784271309,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1M3A5XS7kASYmFAhRWRIuH5bgdU711cYCiGkxrEgiJsQ/edit#gid=1784271309",
          "cachedResultName": "Sheet4"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1M3A5XS7kASYmFAhRWRIuH5bgdU711cYCiGkxrEgiJsQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1M3A5XS7kASYmFAhRWRIuH5bgdU711cYCiGkxrEgiJsQ/edit?usp=drivesdk",
          "cachedResultName": "WP Adminify site data before sep 7"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "465ed5f1-6a24-454f-8e15-b536eb5f0654",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        736,
        192
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "81163f56-f0b3-4b82-8535-e9c86f17e9af",
      "name": "When clicking \u2018Execute workflow\u2019",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        64,
        192
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "e79ea547-93d8-4325-ad23-5a5b58ef266e",
      "name": "Get Sitemap XML",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        288,
        192
      ],
      "parameters": {
        "url": "https://example.com/sitemap.xml",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "2e18cc0f-d3bd-4267-9beb-c790491c121f",
      "name": "Split the title and url",
      "type": "n8n-nodes-base.code",
      "position": [
        512,
        192
      ],
      "parameters": {
        "jsCode": "// 1. Grab the raw XML string (adjust \"body\" vs \"data\" if needed)\nconst xml = items[0].json.body || items[0].json.data;\n\n// 2. Use a global regex to capture all <loc>\u2026</loc> values\nconst urls = Array.from(\n  xml.matchAll(/<loc>(.*?)<\\/loc>/g),\n  match => match[1]\n);\n\n// 3. Emit one item per URL\nreturn urls.map(u => ({ json: { loc: u } }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5e8cc53a-07d9-4f36-9136-e316262d0afd",
      "name": "Get specific link html",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        960,
        48
      ],
      "parameters": {
        "url": "={{ $json.loc }}",
        "options": {}
      },
      "typeVersion": 4.2
    },
    {
      "id": "25dcfa97-0ea6-42e0-b0de-ebba4d549bc2",
      "name": "Get the meta description",
      "type": "n8n-nodes-base.code",
      "position": [
        1184,
        48
      ],
      "parameters": {
        "jsCode": "// 1. Read raw HTML from the HTTP Request node\nconst html = items[0].json.body || items[0].json.data;\n\n// 2. Extract <title>\u2026</title>\nconst titleMatch = html.match(/<title>([\\s\\S]*?)<\\/title>/i);\nconst title = titleMatch ? titleMatch[1].trim() : '';\n\n// 3. Extract <meta name=\"description\" content=\"\u2026\"/>\nconst descMatch = html.match(\n  /<meta\\b[^>]*\\bname=[\"']description[\"'][^>]*\\bcontent=[\"']([\\s\\S]*?)[\"']/i\n);\nconst description = descMatch ? descMatch[1].trim() : '';\n\n// 4. Return a single item with both fields\nreturn [\n  {\n    json: { title, description }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "cb0dccd4-1a14-4392-9b47-673086a584db",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -400
      ],
      "parameters": {
        "width": 528,
        "height": 464,
        "content": "# \ud83d\udd0d Sitemap Metadata Exporter\n\n**Purpose:** Automatically extracts the `<title>` and meta description from every URL in your sitemap and sends the data to Google Sheets.\n\n**Perfect for:** SEO audits, content inventories, and migration planning.\n\n---\n**How to Start:**\n1.  Configure the `sitemap_url` in the HTTP Request node.\n2.  Set up your Google Sheets credentials and node.\n3.  Click **Execute Workflow**."
      },
      "typeVersion": 1
    },
    {
      "id": "232e416e-ba6d-488e-9805-95e51602beb4",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        -512
      ],
      "parameters": {
        "width": 624,
        "height": 464,
        "content": "# \u2699\ufe0f Configuration Required\n\n**Replace the Sitemap URL!**\n\n**Current Value:** `https://example.com/sitemap.xml`\n\n**Action:** Double-click this node and replace the URL with your actual, live sitemap URL (e.g., `https://yourwebsite.com/sitemap.xml`).\n\n\n**Connect your Google Sheet.**\n\n**Steps:**\n1.  **Credentials:** Ensure you have Google Sheets OAuth2 credentials set up in n8n.\n2.  **Document ID:** Paste your Google Sheet's ID here.\n3.  **Sheet Name:** Select the correct sheet/tab from your spreadsheet.\n4.  **Columns:** This node expects your sheet to have columns named:\n    - `URL`\n    - `Title`\n    - `meta description`"
      },
      "typeVersion": 1
    },
    {
      "id": "28eb6dfd-2bc3-48ab-a9ac-e325062d8913",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1792,
        -224
      ],
      "parameters": {
        "width": 400,
        "height": 336,
        "content": "# \u23f8\ufe0f Rate Limiting\n\nThis wait node adds a pause between page fetches to avoid getting blocked by the server.\n\n**Default:** 2 seconds.\n\n**If you see `429 Too Many Requests` errors,** increase the wait time in this node's parameters."
      },
      "typeVersion": 1
    },
    {
      "id": "54d6ad61-aa54-433a-8fba-2824168d9c05",
      "name": "Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        1856,
        192
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "7a23c4c2-06d7-45d9-b4d2-99310fe67915",
      "name": "Merge Meta Description with Title and URL",
      "type": "n8n-nodes-base.merge",
      "position": [
        1408,
        128
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    }
  ],
  "connections": {
    "Wait": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Sitemap XML": {
      "main": [
        [
          {
            "node": "Split the title and url",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "Get specific link html",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Meta Description with Title and URL",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Get specific link html": {
      "main": [
        [
          {
            "node": "Get the meta description",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split the title and url": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get the meta description": {
      "main": [
        [
          {
            "node": "Merge Meta Description with Title and URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append or update row in sheet": {
      "main": [
        [
          {
            "node": "Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking \u2018Execute workflow\u2019": {
      "main": [
        [
          {
            "node": "Get Sitemap XML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Meta Description with Title and URL": {
      "main": [
        [
          {
            "node": "Append or update row in sheet",
            "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.

Pro

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

About this workflow

This workflow automates the extraction of SEO metadata (URL, page title, and meta description) from every page listed in your website's sitemap and exports it to Google Sheets. Ideal for SEO audits, content inventories, and tracking on-page elements.

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

More Data & Sheets workflows → · Browse all categories →

Related workflows

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

Data & Sheets

This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.

HTTP Request, Gmail, Twilio +3
Data & Sheets

PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.

Google Sheets, HTTP Request, @N Octo N/N8N Nodes Json Database +3
Data & Sheets

The workflow automates the process of gathering extensive keyword data for a "Main Keyword." It starts by reading initial parameters from a Google Sheets template, creates a new dedicated Google Sheet

Google Sheets, Google Drive, HTTP Request
Data & Sheets

🔥 March Sale – n8n Community Members Get ideoGener8r for Just $27! (Reg. $47) Use Coupon Code: (Valid until 3/31/2025 for n8n community members)

HTTP Request, Google Drive, Google Sheets
Data & Sheets

📄 Documentation: Notion Guide

Google Sheets, Google Drive, HTTP Request +2