AutomationFlowsAI & RAG › AI Google Maps Business Scraper & Google Sheets Export

AI Google Maps Business Scraper & Google Sheets Export

Original n8n title: Ai-powered Google Maps Business Scraper with Enrichment & Export to Sheets

ByMsaid Mohamed el hadi @mohamedgb00714 on n8n.io

This workflow automates the discovery, extraction, enrichment, and storage of business information from Google Maps search queries using AI tools, scrapers, and Google Sheets.

Event trigger★★★★☆ complexityAI-powered25 nodesHTTP RequestExecute Workflow TriggerAgentOpenRouter ChatGoogle Sheets
AI & RAG Trigger: Event Nodes: 25 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Execute Workflow Trigger 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": "79df5316-c210-478d-a4de-35b5d31924ee",
      "name": "Remove Duplicate URLs",
      "type": "n8n-nodes-base.removeDuplicates",
      "position": [
        2000,
        980
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "985ac7e3-b501-4079-a043-780677c94b52",
      "name": "Loop over queries",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1500,
        580
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "3a478935-781b-4fb1-bdc7-fcf8be1334bc",
      "name": "Search Google Maps with query",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1280,
        980
      ],
      "parameters": {
        "url": "=https://www.google.com/maps/search/{{ $json.query }}",
        "options": {
          "allowUnauthorizedCerts": false
        }
      },
      "executeOnce": false,
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "477e7d55-b7d6-4b20-ac44-dd1f443e270a",
      "name": "Scrape URLs from results",
      "type": "n8n-nodes-base.code",
      "position": [
        1480,
        980
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json.data\n\nconst regex = /https?:\\/\\/[^\\/]+/g\n\nconst urls = data.match(regex)\n\nreturn urls.map(url => ({json: {url: url}}))"
      },
      "typeVersion": 2
    },
    {
      "id": "a5b67e45-a3f6-41d2-aa58-c26a441c41b2",
      "name": "Filter irrelevant URLs",
      "type": "n8n-nodes-base.filter",
      "position": [
        1680,
        980
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "041797f2-2fe2-41dc-902a-d34050b9b304",
              "operator": {
                "type": "string",
                "operation": "notRegex"
              },
              "leftValue": "={{ $json.url }}",
              "rightValue": "=(google|gstatic|ggpht|schema\\.org|example\\.com|sentry-next\\.wixpress\\.com|imli\\.com|sentry\\.wixpress\\.com|ingest\\.sentry\\.io)"
            },
            {
              "id": "eb499a7e-17bc-453c-be08-a47286f726dd",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "12f662a8-c55f-409a-b381-f37ab6dd3794",
      "name": "Loop over URLs",
      "type": "n8n-nodes-base.splitInBatches",
      "onError": "continueErrorOutput",
      "position": [
        2640,
        980
      ],
      "parameters": {
        "options": {
          "reset": false
        }
      },
      "typeVersion": 3
    },
    {
      "id": "93437e8b-4f8d-40a1-9585-cab1b556164a",
      "name": "Starts scraper workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        800,
        980
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "dffaf04e-d1d2-4002-9a69-f0904b61fc2d",
      "name": "Wait between executions",
      "type": "n8n-nodes-base.wait",
      "position": [
        2300,
        600
      ],
      "parameters": {
        "unit": "minutes",
        "amount": 20
      },
      "typeVersion": 1.1
    },
    {
      "id": "18787007-1d11-41b9-89c3-d5f69756eda7",
      "name": "Execute scraper for query",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        1800,
        600
      ],
      "parameters": {
        "mode": "each",
        "options": {
          "waitForSubWorkflow": false
        },
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "9fa06f2a-0e7a-43e1-b997-4b4288a990cd",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        4260,
        1360
      ],
      "parameters": {
        "text": "={{ $json.prompt }}",
        "options": {
          "systemMessage": "You are an expert business analyst.\n\nGiven a business website data, generate a JSON object with key business information and a detailed, insightful description that could be used to prepare for outreach or partnership discussions.\n\nFocus the description on:\n\n- What the business does (products/services)\n- Their strengths or market position\n- Technologies or platforms used (if identifiable)\n- Unique value proposition\n- Target customers\n- Any possible gaps, pain points, or areas for improvement\n- Why this business could benefit from external collaboration (e.g., automation, digital transformation, SEO, AI tools)\n\nFormat the output as a single JSON object with these fields:\n\n- business_name\n- website_url\n- email\n- phone_number\n- address\n- city\n- postal_code\n- country\n- latitude\n- longitude\n- category\n- subcategory\n- opening_hours\n- social_media_links (array)\n- about_us\n- services (array)\n- contact_page_url\n- privacy_policy_url\n- terms_conditions_url\n- logo_url\n- languages (array)\n- keywords (array)\n- google_maps_url\n- ai_description_detailed (a detailed paragraph or two with everything above)\n\nOnly output valid JSON.\nif prompt is empty just return empty json data "
        },
        "promptType": "define"
      },
      "typeVersion": 2
    },
    {
      "id": "c191a15f-2457-49c1-976b-90b0caaf3835",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        4260,
        1620
      ],
      "parameters": {
        "model": "google/gemini-2.5-flash-lite-preview-06-17",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "20c5612b-8fbf-4eb4-8f95-ca17acc5f0e2",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        4680,
        960
      ],
      "parameters": {
        "jsCode": "const allPromptResults = $input.first().json.data.map(item => item.promptResult).join('\\n');\n\n\nreturn {\n  \"prompt\":allPromptResults\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "53d2251a-f7bb-43b1-8035-c7ac74e0aa62",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        4420,
        960
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "67dfef97-0fc2-4fa8-a7a8-08c491f8785f",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1060,
        580
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "cb651c6d-eac0-44bc-8d80-c07c5a65ce6a",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1280,
        580
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupColumn": "processed"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1652190371,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit#gid=1652190371",
          "cachedResultName": "keywords"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit?usp=drivesdk",
          "cachedResultName": "google maps  bussiness informations"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "423dce21-e06d-4bd2-833b-976b3ce9e231",
      "name": "Update row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2040,
        600
      ],
      "parameters": {
        "columns": {
          "value": {
            "query": "={{ $json.query }}",
            "processed": "TRUE"
          },
          "schema": [
            {
              "id": "query",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "query",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "processed",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "processed",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "query"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1652190371,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit#gid=1652190371",
          "cachedResultName": "keywords"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit?usp=drivesdk",
          "cachedResultName": "google maps  bussiness informations"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "a996171f-c358-471d-91ba-b6c9950e7edf",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        3940,
        980
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7eec5545-99ac-410a-87ec-4e5f79e30202",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.dontExist }}",
              "rightValue": ""
            },
            {
              "id": "96fe4cf5-4689-4140-8a75-8bdbc893b363",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "4575083d-5d45-497e-a5d1-5c369f2d7b91",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        3660,
        980
      ],
      "parameters": {
        "mode": "combineBySql",
        "query": "SELECT * FROM input1 LEFT JOIN input2 ON 1=1",
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "73814b4e-ab19-4a06-b180-a2997e43bdbd",
      "name": "convert string to json object",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        4640,
        1360
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "\n\nlet raw = $json.output;\n\n// Remove ```json or ``` wrapping if it exists\nraw = raw.replace(/^```json\\s*|\\s*```$/g, '').trim();\n\nlet outputJson;\n\ntry {\n  outputJson = JSON.parse(raw);\n} catch (err) {\n  outputJson = { error: 'Invalid JSON format in promptResult' };\n}\n\nreturn {\n  json: outputJson\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "54d94ef2-84cf-4568-a9d5-28ec9a818ffd",
      "name": "Save DATA to Google Sheet1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        5060,
        1360
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "Business Name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Business Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Website URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Website URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone Number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Phone Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Address",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "City",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "City",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Postal Code",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Postal Code",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Country",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Country",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Latitude",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Latitude",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Longitude",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Longitude",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Subcategory",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Subcategory",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Opening Hours",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Opening Hours",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Social Media Links",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Social Media Links",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "About Us",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "About Us",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Services",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Services",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Contact Page URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Contact Page URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Privacy Policy URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Privacy Policy URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Terms & Conditions URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Terms & Conditions URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Logo URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Logo URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Languages",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Languages",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Keywords",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Keywords",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Google Maps URL",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Google Maps URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Description",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "AI Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit?usp=drivesdk",
          "cachedResultName": "google maps  bussiness informations"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "40ec6d1f-1c98-4c9f-8499-c5893c3df7b9",
      "name": "use APIFY",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        4200,
        960
      ],
      "parameters": {
        "url": "=https://api.apify.com/v2/acts/mohamedgb00714~firescraper-ai-prompt-website-content-markdown-scraper/run-sync-get-dataset-items?token=apify_api_YOUR_TOKEN_HERE_TOKEN",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"enqueue\": true,\n  \"getHtml\": false,\n  \"getText\": false,\n  \"prompt\": \"You are an expert business analyst.\\n\\nGiven a business website URL, generate a JSON object with key business information and a detailed, insightful description that could be used to prepare for outreach or partnership discussions.\\n\\nFocus the description on:\\n\\n- What the business does (products/services)\\n- Their strengths or market position\\n- Technologies or platforms used (if identifiable)\\n- Unique value proposition\\n- Target customers\\n- Any possible gaps, pain points, or areas for improvement\\n- Why this business could benefit from external collaboration (e.g., automation, digital transformation, SEO, AI tools)\\n\\nFormat the output as a single JSON object with these fields:\\n\\n- business_name\\n- website_url\\n- email\\n- phone_number\\n- address\\n- city\\n- postal_code\\n- country\\n- latitude\\n- longitude\\n- category\\n- subcategory\\n- opening_hours\\n- social_media_links (array)\\n- about_us\\n- services (array)\\n- contact_page_url\\n- privacy_policy_url\\n- terms_conditions_url\\n- logo_url\\n- languages (array)\\n- keywords (array)\\n- google_maps_url\\n- ai_description_detailed (a detailed paragraph or two with everything above)\\n\\nOnly output valid JSON.\",\n  \"screenshot\": false,\n  \"startUrls\": [\n    {\n      \"url\": \"{{$json.url}}\",\n      \"method\": \"GET\"\n    }\n  ]\n}\n",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "e4997964-dc80-4778-9f79-ae4dc9e41284",
      "name": "get records if exist",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueErrorOutput",
      "position": [
        2900,
        1300
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1si2IQusnIF-Br8JdXSVd_Z9QvnXrKcieXOkxI0Xz9ks/edit?usp=drivesdk",
          "cachedResultName": "google maps  bussiness informations"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6,
      "alwaysOutputData": true
    },
    {
      "id": "d2380d4e-20a5-48bb-9d87-3f2c638f2fc7",
      "name": "Code1",
      "type": "n8n-nodes-base.code",
      "position": [
        3400,
        1280
      ],
      "parameters": {
        "jsCode": "let dontExist = true;\n\n// Get reference domain from 'Loop over URLs' node\nconst referenceUrl = $('Loop over URLs').first().json.url;\nconst referenceDomain = referenceUrl.match(/^https?:\\/\\/([^\\/?#]+)(?:[\\/?#]|$)/i)?.[1]?.toLowerCase();\n\nif (!referenceDomain) {\n  throw new Error('Invalid reference URL');\n}\n\n// Loop over input items\nfor (const item of $input.all()) {\n  const urls = item.json.website_url;\n\n  for (const url of urls) {\n    const domain = url.match(/^https?:\\/\\/([^\\/?#]+)(?:[\\/?#]|$)/i)?.[1]?.toLowerCase();\n    if (!domain) continue;\n\n    if (domain === referenceDomain) {\n      dontExist = false;\n      break;\n    }\n  }\n\n  if (!dontExist) break;\n}\n\n// Return result\nreturn {\n  json: {\n    dontExist\n  }\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "0273b1f4-5912-41fd-9899-3ec0a5a24f6c",
      "name": "Aggregate1",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        3160,
        1280
      ],
      "parameters": {
        "options": {},
        "fieldsToAggregate": {
          "fieldToAggregate": [
            {
              "fieldToAggregate": "website_url"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2adf371b-2b7b-4ce9-9666-95a4b892a963",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20,
        240
      ],
      "parameters": {
        "width": 680,
        "height": 2220,
        "content": "\n### Overview\n\nThis workflow automates the discovery, extraction, enrichment, and storage of business information from **Google Maps** search queries using AI tools, scrapers, and Google Sheets.\n\nIt is ideal for:\n\n* Lead generation agencies\n* Local business researchers\n* Digital marketing firms\n* Automation & outreach specialists\n\n---\n\n### \ud83d\udd27 Tools & APIs Used\n\n* **Google Maps Search (via HTTP)**\n* **Custom JavaScript Parsing**\n* **URL Filtering & De-duplication**\n* **Google Sheets (Read/Write)**\n* **APIFY Actor** for business scraping\n* **LangChain AI Agent** (OpenRouter - Gemini 2.5)\n* **n8n Built-in Logic** (Loops, Conditions, Aggregators)\n\n---\n\n### \ud83e\udde0 Workflow Summary\n\n1. **Trigger**\n   The automation starts via schedule (every hour).\n\n2. **Read Queries from Google Sheet**\n   Loads unprocessed keywords from a Google Sheet tab named `keywords`.\n\n3. **Loop Through Keywords**\n   Each keyword is used to search Google Maps for relevant businesses.\n\n4. **Extract URLs**\n   JavaScript parses HTML to find all external website URLs from the search results.\n\n5. **Clean URLs**\n   Filters out irrelevant domains (e.g., Google-owned, example.com, etc.), and removes duplicates.\n\n6. **Loop Through URLs**\n   For each URL:\n\n   * Checks if it already exists in the Google Sheet (to prevent duplication).\n   * Calls the **APIFY Actor** to extract full business data.\n   * Optionally uses **AI Agent (Gemini)** to provide detailed insight on the business, including:\n\n     * Services, About, Market Position, Weaknesses, AI suggestions, etc.\n   * Converts the AI result (text) to a structured JSON object.\n\n7. **Save to Google Sheet**\n   Adds all extracted and AI-enriched business information to a separate tab (`Sheet1`).\n\n8. **Mark Queries as Processed**\n   Updates the original row in `keywords` to avoid reprocessing.\n\n---\n\n### \ud83d\uddc3\ufe0f Output Fields Saved\n\nThe following information is saved per business:\n\n* Business Name, Website, Email, Phone\n* Address, City, Postal Code, Country, Coordinates\n* Category, Subcategory, Services\n* About Us, Opening Hours, Social Media Links\n* Legal Links (Privacy, Terms)\n* Logo, Languages, Keywords\n* **AI-Generated Description**\n* Google Maps URL\n\n---\n\n### \ud83d\udcc8 Use Cases\n\n* Build a **prospect database** for B2B cold outreach.\n* Extract **local SEO insights** per business.\n* Feed CRMs or analytics systems with **enriched business profiles**.\n* Automate market research for **regional opportunity detection**.\n\n---\n\n### \ud83d\udce9 Want a Similar Workflow?\n\nIf you\u2019d like a custom AI-powered automation like this for your business or agency, feel free to contact me:\n\n**\ud83d\udce7 [msaidwolfltd@gmail.com](mailto:msaidwolfltd@gmail.com)**\n\n\n\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "use APIFY",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop over URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "convert string to json object",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "use APIFY": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate1": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop over URLs": {
      "main": [
        [],
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          },
          {
            "node": "get records if exist",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop over queries": {
      "main": [
        [],
        [
          {
            "node": "Execute scraper for query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Loop over queries",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update row in sheet": {
      "main": [
        [
          {
            "node": "Wait between executions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "get records if exist": {
      "main": [
        [
          {
            "node": "Aggregate1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicate URLs": {
      "main": [
        [
          {
            "node": "Loop over URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter irrelevant URLs": {
      "main": [
        [
          {
            "node": "Remove Duplicate URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Starts scraper workflow": {
      "main": [
        [
          {
            "node": "Search Google Maps with query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait between executions": {
      "main": [
        [
          {
            "node": "Loop over queries",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape URLs from results": {
      "main": [
        [
          {
            "node": "Filter irrelevant URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute scraper for query": {
      "main": [
        [
          {
            "node": "Update row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save DATA to Google Sheet1": {
      "main": [
        [
          {
            "node": "Loop over URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Google Maps with query": {
      "main": [
        [
          {
            "node": "Scrape URLs from results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "convert string to json object": {
      "main": [
        [
          {
            "node": "Save DATA to Google Sheet1",
            "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 discovery, extraction, enrichment, and storage of business information from Google Maps search queries using AI tools, scrapers, and Google Sheets.

Source: https://n8n.io/workflows/6439/ — 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

This workflow is designed for marketers, content creators, agencies, and solo founders who want to publish long‑form posts with visuals on autopilot using n8n and AI agents. ​

Tool Http Request, Agent, HTTP Request +27
AI & RAG

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

Output Parser Structured, Telegram, N8N Nodes Tesseractjs +14
AI & RAG

Faceless Video. Uses httpRequest, agent, googleDrive, stickyNote. Event-driven trigger; 29 nodes.

HTTP Request, Agent, Google Drive +6
AI & RAG

Blog Post. Uses toolHttpRequest, lmChatOpenRouter, agent, httpRequest. Event-driven trigger; 20 nodes.

Tool Http Request, OpenRouter Chat, Agent +6
AI & RAG

LinkedIn Post. Uses toolHttpRequest, lmChatOpenRouter, agent, httpRequest. Event-driven trigger; 20 nodes.

Tool Http Request, OpenRouter Chat, Agent +6