AutomationFlowsMarketing & Ads › Automate Lead Generation From Google Search & Maps to Google Sheets

Automate Lead Generation From Google Search & Maps to Google Sheets

ByIntuz @intuz on n8n.io

It acts as a powerful scraping agent that takes a simple chat query, scours both Google Search and Google Maps for relevant businesses, scrapes their websites for contact details, and compiles an enriched lead list directly in Google Sheets. Sales Development Representatives…

Chat trigger trigger★★★★★ complexityAI-powered40 nodesChat TriggerGoogle SheetsHTTP Request
Marketing & Ads Trigger: Chat trigger Nodes: 40 Complexity: ★★★★★ AI nodes: yes Added:
Automate Lead Generation From Google Search & Maps to Google Sheets — n8n workflow card showing Chat Trigger, Google Sheets, HTTP Request integration

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

This workflow follows the Chat Trigger → 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": "J3HFTy4HBCyARaO4",
  "name": "Automate Lead Generation from Google Search & Maps to Google Sheets",
  "tags": [
    {
      "id": "m1paRrANi4GrQXxX",
      "name": "AI Internal",
      "createdAt": "2025-09-18T04:05:25.667Z",
      "updatedAt": "2025-09-18T04:05:25.667Z"
    }
  ],
  "nodes": [
    {
      "id": "9f1247da-3797-481a-b835-a5c780b050d4",
      "name": "When chat message received",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -1344,
        496
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.3
    },
    {
      "id": "f8df5c5f-af30-4f62-9aab-e010dd9c9c91",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        256,
        -96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "79d732fc-8a88-4a84-8a18-8cc9b689b3c0",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json[\"Email ID\"] }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a496c6f6-fa85-4a33-85f4-98e9b00f4af2",
      "name": "Append row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        880,
        -128
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $json.URL }}",
            "Type": "={{ $json.Type }}",
            "Socials": "={{ $json.Socials }}",
            "Description": "={{ $json.Description }}",
            "Search Query": "={{ $('When chat message received').item.json.chatInput }}",
            "Business Name": "={{ $json[\"Business Name\"] }}",
            "Primary Email": "={{ $json[\"Email ID\"] }}",
            "Contact Number": "={{ $json[\"Contact Number\"] }}"
          },
          "schema": [
            {
              "id": "Search Query",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Search Query",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Business Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Business Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Primary Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Primary Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Rest Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Rest Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Contact Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Contact Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Socials",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Socials",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_AWS_SECRET_KEY_HERE_ou8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit?usp=drivesdk",
          "cachedResultName": "Leads Via Google Search"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "82cf4f94-509f-4698-9982-af48caa035de",
      "name": "Remove Duplicates",
      "type": "n8n-nodes-base.removeDuplicates",
      "position": [
        1056,
        1136
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "ff0491b3-1695-48be-863d-d7e8bd6529cd",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1312,
        1104
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "d441d472-e687-44d7-9ddb-fb1f8baa7c45",
      "name": "Extract URLs",
      "type": "n8n-nodes-base.code",
      "position": [
        592,
        1120
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json.data\nconst regex = /https?:\\/\\/[^\\/\\s\"'>]+/g\nconst websites = input.match(regex)\nreturn websites.map(website => ({json:{website}}))"
      },
      "typeVersion": 2
    },
    {
      "id": "30354b5f-e671-42fb-be46-38dcd63a6b10",
      "name": "Scrape Google Maps",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        368,
        1136
      ],
      "parameters": {
        "url": "=https://www.google.com/maps/search/{{ $json.searchQuery }}",
        "options": {
          "response": {
            "response": {
              "fullResponse": true
            }
          },
          "allowUnauthorizedCerts": true
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "bdba745f-cec0-4df6-8f95-cff4eb9ea1ff",
      "name": "Filter Google URLs",
      "type": "n8n-nodes-base.filter",
      "position": [
        832,
        1136
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "bf0a5053-9660-457c-9581-964793bb6d7d",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "schema"
            },
            {
              "id": "9110b9e0-12aa-45cc-bde0-9eda8c10970e",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "google"
            },
            {
              "id": "fb9b6ed6-96a5-4560-ab10-b8a4b9a61a2b",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "gg"
            },
            {
              "id": "10500c0b-cdbd-4816-aba3-df60d69845dc",
              "operator": {
                "type": "string",
                "operation": "notContains"
              },
              "leftValue": "={{ $json.website }}",
              "rightValue": "gstatic"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "ed333dd0-1e0d-4c97-8b63-7535427f8a8d",
      "name": "Wait2",
      "type": "n8n-nodes-base.wait",
      "position": [
        1696,
        1120
      ],
      "parameters": {
        "amount": 1
      },
      "typeVersion": 1.1
    },
    {
      "id": "34b415fd-db46-4914-b005-236b5aaee205",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        112,
        448
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_AWS_SECRET_KEY_HERE_ou8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit?usp=drivesdk",
          "cachedResultName": "Leads Via Google Search"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "e631f027-7a37-4899-89d6-0b0c7f18c6fa",
      "name": "Get row(s) in sheet1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        96,
        1760
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_AWS_SECRET_KEY_HERE_ou8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit?usp=drivesdk",
          "cachedResultName": "Leads Via Google Search"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "cb140551-a551-47ae-97b7-d64048c43be6",
      "name": "Remove Duplicates3",
      "type": "n8n-nodes-base.removeDuplicates",
      "position": [
        1296,
        1728
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "13770160-49fe-4a3e-b60d-81a9ff86368a",
      "name": "Append row in sheet2",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1632,
        1728
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $json.URL }}",
            "Type": "website",
            "Socials": "={{ $json.socials }}",
            "Rest Email": "={{ $json.email2 }}",
            "Description": "={{ $json.description }}",
            "Search Query": "={{ $('When chat message received').item.json.chatInput }}",
            "Business Name": "={{ $json.businessName }}",
            "Primary Email": "={{ $json.email1 }}",
            "Contact Number": "={{ $json.phone }}"
          },
          "schema": [
            {
              "id": "Search Query",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Search Query",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Business Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Business Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Primary Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Primary Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Rest Email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Rest Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Contact Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Contact Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Socials",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Socials",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_AWS_SECRET_KEY_HERE_ou8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit?usp=drivesdk",
          "cachedResultName": "Leads Via Google Search"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "a1d0ac38-853a-40f1-8268-201e17d3d82e",
      "name": "Loop Over Items1",
      "type": "n8n-nodes-base.splitInBatches",
      "onError": "continueRegularOutput",
      "position": [
        608,
        368
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "d16c9b61-e5fc-414e-ad4d-6f4b62a3822c",
      "name": "Setting Pagination",
      "type": "n8n-nodes-base.code",
      "position": [
        160,
        -368
      ],
      "parameters": {
        "jsCode": "// Array of start indices for pagination\nconst starts = [ 1, 11, 21, 31];\n\n// Create an array of items, one per start value\nreturn starts.map(s => ({ json: { start: s } }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "37cdc904-b273-49f9-b0f1-e00ec4fe2895",
      "name": "Loop for Multiple Page Search",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        400,
        -368
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "b05aecbc-243e-418f-ab55-cb20e12f5116",
      "name": "Custom Google Search API",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        704,
        -352
      ],
      "parameters": {
        "url": "https://www.googleapis.com/customsearch/v1",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "key",
              "value": "AIzaYOUR_GOOGLE_API_KEY_HERE"
            },
            {
              "name": "cx",
              "value": "2788643fa0be84497"
            },
            {
              "name": "q",
              "value": "={{ $('When chat message received').item.json.chatInput }}"
            },
            {
              "name": "cr",
              "value": "countryUS"
            },
            {
              "name": "gl",
              "value": "us"
            },
            {
              "name": "lr",
              "value": "lang_en"
            },
            {
              "name": "start",
              "value": "={{ $json.start }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "79df0f3d-6211-4f5f-9b76-263da7db8edb",
      "name": "Flatten Output Items",
      "type": "n8n-nodes-base.code",
      "position": [
        944,
        -352
      ],
      "parameters": {
        "jsCode": "// Each input item from HTTP Request node\nreturn $input.all().map(item => {\n  // Extract only the 'items' array from the API response\n  const results = item.json.items || [];\n\n  // Return each search result as a separate item\n  return results.map(r => ({\n    json: r\n  }));\n}).flat();\n"
      },
      "typeVersion": 2
    },
    {
      "id": "2c3e8958-595e-4e11-9d01-158657691667",
      "name": "Information Extraction",
      "type": "n8n-nodes-base.code",
      "position": [
        1280,
        -352
      ],
      "parameters": {
        "jsCode": "// For each input item (already a search result)\nreturn $input.all().map(item => {\n    const r = item.json;\n    const metatags = (r.pagemap && r.pagemap.metatags && r.pagemap.metatags[0]) || {};\n\n    return {\n        json: {\n            \"Business Name\": r.title || null,\n            \"Email ID\": metatags['og:email'] || null,\n            \"Contact Number\": metatags['og:phone_number'] || null,\n            \"URL\": r.link || null,\n            \"Description\": r.snippet || metatags['og:description'] || null,\n            \"Type\": metatags['og:type'] || null,\n            \"Socials\": metatags['og:see_also'] || null\n        }\n    };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e0d64378-c004-44b3-a9d9-cee43a157989",
      "name": "Remove Duplicates From Searches",
      "type": "n8n-nodes-base.removeDuplicates",
      "position": [
        1680,
        -352
      ],
      "parameters": {
        "compare": "selectedFields",
        "options": {},
        "fieldsToCompare": "=URL"
      },
      "typeVersion": 2
    },
    {
      "id": "5e59a9c6-6b03-4361-8505-974a74fea15f",
      "name": "Scrape Site2",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        944,
        352
      ],
      "parameters": {
        "url": "={{ $json.URL }}",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          },
          "response": {
            "response": {
              "responseFormat": "text"
            }
          },
          "allowUnauthorizedCerts": true
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {}
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "5cc43a8c-9ae5-49e6-8c55-d5e9839424c7",
      "name": "If Site scrapped",
      "type": "n8n-nodes-base.if",
      "onError": "continueRegularOutput",
      "position": [
        1248,
        352
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8cade239-5400-45e5-923d-5bccb689e523",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.data }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "81d1f254-b195-4ba3-bf85-f14ad3422a1f",
      "name": "Extract Required Fields",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        1488,
        336
      ],
      "parameters": {
        "jsCode": "// Get current batch of items\nconst items = $input.all();\n\n// Regex patterns\nconst emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-z]{2,}/g;\nconst phoneRegex = /(?:\\+?\\d{1,2}\\s?)?(?:\\(\\d{3}\\)|\\d{3})[-.\\s]?\\d{3}[-.\\s]?\\d{4}/g;\nconst socialRegex = /(https?:\\/\\/(?:www\\.)?(?:facebook|twitter|instagram|linkedin|youtube)\\.com\\/[^\\s\"'<>]+)/gi;\n\n// Helper to remove duplicates\nfunction uniqueArray(arr) {\n    return arr ? [...new Set(arr)] : [];\n}\n\n// Function to extract data\nfunction extractFromHTML(html) {\n    const emails = uniqueArray(html.match(emailRegex));\n    const phones = uniqueArray(html.match(phoneRegex));\n    const socials = uniqueArray(html.match(socialRegex));\n\n    return {\n        email1: emails.length > 0 ? emails[0] : null,\n        email2: emails.length > 1 ? emails.slice(1).join(\", \") : null, // all remaining emails\n        phone: phones.length > 0 ? phones.join(\", \") : null, // string instead of array\n        socials: socials.length > 0 ? socials.join(\", \") : null // string instead of array\n    };\n}\n\n// Process each item\nconst output = items.map(item => {\n    const htmlData = item.json.data || \"\"; // assuming HTML content is in 'data'\n    const extracted = extractFromHTML(htmlData);\n\n    return { json: extracted };\n});\n\nreturn output;\n"
      },
      "typeVersion": 2,
      "alwaysOutputData": false
    },
    {
      "id": "66f68935-9577-4b95-a235-f8a720aa7dc1",
      "name": "Set All Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        1776,
        336
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a4dec390-76fa-42b3-acaf-93b2449aaa3f",
              "name": "Phone",
              "type": "string",
              "value": "={{ $json.phone }}"
            },
            {
              "id": "78749360-6d15-42d1-8017-ec626eaeb24b",
              "name": "Social",
              "type": "string",
              "value": "={{ $json.socials }}"
            },
            {
              "id": "f90b4f19-bc8f-4638-96ba-458c0cafe7c5",
              "name": "Email1",
              "type": "string",
              "value": "={{ $json.email1 }}"
            },
            {
              "id": "507b5231-f31b-4587-82dd-eb4c03e44bcd",
              "name": "Name",
              "type": "string",
              "value": "={{ $('Loop Over Items1').item.json[\"Business Name\"] }}"
            },
            {
              "id": "722bf218-e8b5-4e69-8602-bf1b858abc44",
              "name": "URL",
              "type": "string",
              "value": "={{ $('Loop Over Items1').item.json.URL }}"
            },
            {
              "id": "c42325ba-b870-4296-af68-833df670497d",
              "name": "Type",
              "type": "string",
              "value": "={{ $('Loop Over Items1').item.json.Type }}"
            },
            {
              "id": "6b4ec29b-31da-429b-bd60-89a6c0705c48",
              "name": "Description",
              "type": "string",
              "value": "={{ $('Loop Over Items1').item.json.Description }}"
            },
            {
              "id": "265bd1d6-6a89-42ea-b7da-994715e3806d",
              "name": "Email 2",
              "type": "string",
              "value": "={{ $json.email2 }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "27f9e051-ccde-42a0-974d-806de632135a",
      "name": "Set URL for Validation",
      "type": "n8n-nodes-base.set",
      "position": [
        336,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "f20a894e-3505-404b-a2f8-8648bbed8301",
              "name": "URL",
              "type": "string",
              "value": "={{ $json.URL }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "72008dea-4b9c-4b0a-8df0-befb25c64220",
      "name": "Not Duplicate Search Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        624,
        624
      ],
      "parameters": {
        "mode": "combine",
        "options": {
          "fuzzyCompare": true
        },
        "joinMode": "keepNonMatches",
        "outputDataFrom": "input1",
        "fieldsToMatchString": "['URL']"
      },
      "typeVersion": 3.2
    },
    {
      "id": "a9063fa4-00fa-4279-be72-df006d6a36ea",
      "name": "If Site Exists",
      "type": "n8n-nodes-base.if",
      "position": [
        928,
        624
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "fc7625cf-225d-4d8e-8dd2-474bd65b6d8d",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.URL }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "64635b25-9b96-4473-b876-c058ef977593",
      "name": "Exclude Articles and Blogs",
      "type": "n8n-nodes-base.if",
      "position": [
        1280,
        624
      ],
      "parameters": {
        "options": {
          "ignoreCase": false
        },
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "ce6a31cc-e1ac-4786-8300-c3d7553598fe",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.Type }}",
              "rightValue": "article"
            },
            {
              "id": "89453f8b-f6b7-4c69-bac3-6f10e0a30046",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Type }}",
              "rightValue": "blog"
            },
            {
              "id": "e3d4cbe5-549a-4f17-b551-59e18adae86a",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "310820f4-5ebe-436d-9069-ead7678c29fd",
      "name": "Remove Duplicates For Sheets",
      "type": "n8n-nodes-base.removeDuplicates",
      "position": [
        1616,
        608
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "96c4b66d-f5f4-4026-8ec6-429ab727a10f",
      "name": "Add Search Results in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1888,
        608
      ],
      "parameters": {
        "columns": {
          "value": {
            "URL": "={{ $json.URL }}",
            "Type": "={{ $json.Type }}",
            "Socials": "={{ $json.Social }}",
            "Rest Email": "={{ $json[\"Email 2\"] }}",
            "Description": "={{ $json.Description }}",
            "Search Query": "={{ $('When chat message received').item.json.chatInput }}",
            "Business Name": "={{ $json.Name }}",
            "Primary Email": "={{ $json.Email1 }}",
            "Contact Number": "={{ $json.Phone }}"
          },
          "schema": [
            {
              "id": "Search Query",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Search Query",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Business Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Business Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Primary Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Primary Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Rest Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Rest Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Contact Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Contact Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "URL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "URL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Socials",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Socials",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_AWS_SECRET_KEY_HERE_ou8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_AWS_SECRET_KEY_HERE_ou8/edit?usp=drivesdk",
          "cachedResultName": "Leads Via Google Search"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "6fccec45-a3b6-420c-b627-33b15b02cbb4",
      "name": "Prepare Query for Maps",
      "type": "n8n-nodes-base.code",
      "position": [
        128,
        1120
      ],
      "parameters": {
        "jsCode": "const item = items[0];\nconst chatInput = item.json.chatInput;\nconst formattedQuery = chatInput.replaceAll(' ', '+');\n\nreturn [{\n  json: {\n    \"searchQuery\": formattedQuery\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b4c0a560-6368-47cc-a9b4-284a4072e2e0",
      "name": "Scrape Map Sites",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        1504,
        1120
      ],
      "parameters": {
        "url": "={{ $json.website }}",
        "options": {
          "redirect": {
            "redirect": {
              "followRedirects": false
            }
          }
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "274a3ed6-18fe-47f9-9571-ddd57bdc31c8",
      "name": "Extract Information",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        1904,
        1104
      ],
      "parameters": {
        "jsCode": "// --- Safety Check (Guard Clause) ---\nif (!items[0] || !items[0].json || !items[0].json.data) {\n  return [{\n    json: {\n      error: \"Input data from the previous node is missing or in the wrong format.\",\n      businessName: null,\n      description: null,\n      phone: null,\n      socials: null,\n      email1: null,\n      email2: null,\n      URL: null\n    }\n  }];\n}\n\nconst htmlString = items[0].json.data;\n\n// --- Business Name Extraction ---\nlet businessName = \"\";\nconst jsonLdRegex = /<script[^>]*type=[\"']?application\\/ld\\+json[\"']?[^>]*>([\\s\\S]*?)<\\/script>/gi;\nconst jsonLdMatches = [...htmlString.matchAll(jsonLdRegex)];\nfor (const match of jsonLdMatches) {\n    try {\n        const jsonContent = JSON.parse(match[1]);\n        if (!businessName) {\n            if (jsonContent.name && (jsonContent['@type'] === 'Dentist' || jsonContent['@type'] === 'Organization')) {\n                businessName = jsonContent.name;\n            } else if (Array.isArray(jsonContent['@graph'])) {\n                for (const item of jsonContent['@graph']) {\n                    if (item.name && (item['@type'] === 'Dentist' || item['@type'] === 'WebSite')) {\n                        businessName = item.name.replace(/ New York New York$/, '').trim();\n                        break;\n                    }\n                }\n            }\n        }\n    } catch (e) { /* Ignore */ }\n}\nif (!businessName) {\n    const ogTitleRegex = /<meta[^>]*property=[\"']?og:title[\"']?[^>]*content=[\"']?([^\"'>]*)[\"']?/i;\n    const ogTitleMatch = htmlString.match(ogTitleRegex);\n    if (ogTitleMatch && ogTitleMatch[1]) {\n        businessName = ogTitleMatch[1].split(/[-|]/)[0].trim();\n    }\n}\nif (!businessName) {\n    const titleRegex = /<title>([\\s\\S]*?)<\\/title>/i;\n    const titleMatch = htmlString.match(titleRegex);\n    if (titleMatch && titleMatch[1]) {\n      businessName = titleMatch[1].split(/[-|]/)[0].trim();\n    }\n}\n\n// --- Other Data Extraction ---\nconst descriptionRegex = /<meta[^>]*name=[\"']?description[\"']?[^>]*content=[\"']?([^\"'>]*)[\"']?/i;\nconst descriptionMatch = htmlString.match(descriptionRegex);\nconst description = descriptionMatch ? descriptionMatch[1].trim() : \"\";\n\nconst phoneRegex = /(?:\\+?1[ -]?)?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}/g;\nconst foundPhones = htmlString.match(phoneRegex) || [];\nconst phoneNumbers = [...new Set(foundPhones)];\n\nfunction findSameAsLinks(obj, links = []) {\n    if (obj === null || typeof obj !== 'object') return links;\n    if (obj.sameAs && Array.isArray(obj.sameAs)) {\n        links.push(...obj.sameAs.filter(item => typeof item === 'string'));\n    }\n    Object.values(obj).forEach(value => {\n        if (typeof value === 'object') findSameAsLinks(value, links);\n    });\n    return links;\n}\nlet jsonLdLinks = [];\nfor (const match of jsonLdMatches) {\n  try {\n    const jsonContent = JSON.parse(match[1]);\n    findSameAsLinks(jsonContent, jsonLdLinks);\n  } catch(e) {/* Ignore */}\n}\nconst socialAnchorRegex = /href=[\"']?(https?:\\/\\/(?:www\\.)?(?:facebook|instagram|twitter|linkedin|yelp|pinterest|plus\\.google)\\.com\\/[^\"'\\s>]+)/gi;\nconst socialAnchorLinks = [...htmlString.matchAll(socialAnchorRegex)].map(match => match[1]);\nconst allSocials = [...jsonLdLinks, ...socialAnchorLinks];\nconst socials = [...new Set(allSocials)];\n\nconst plainTextEmailRegex = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\nconst plainTextEmails = htmlString.match(plainTextEmailRegex) || [];\nconst mailtoRegex = /href=[\"']?mailto:([^\"'\\?\\s>]+)/gi;\nconst mailtoEmails = [...htmlString.matchAll(mailtoRegex)].map(match => match[1]);\nconst allEmails = [...plainTextEmails, ...mailtoEmails];\nconst emails = [...new Set(allEmails)];\n\n// --- Final Output Formatting ---\nconst socialString = socials.join(', ');\nconst phoneString = phoneNumbers.join(', ');\n\nconst email1 = emails[0] || null;\nconst email2 = emails[1] || null;\n\n// **UPDATED:** Get the URL and add a trailing slash if needed.\nlet websiteUrl = $('Loop Over Items').first().json.website;\nif (websiteUrl && typeof websiteUrl === 'string' && !websiteUrl.endsWith('/')) {\n  websiteUrl += '/';\n}\n\nreturn [{\n  json: {\n    businessName,\n    description,\n    phone: phoneString,\n    socials: socialString,\n    email1,\n    email2,\n    URL: websiteUrl,\n  }\n}];"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "1575bc32-cf8f-4409-99ee-268f51feba52",
      "name": "Set URL Validaiton",
      "type": "n8n-nodes-base.set",
      "position": [
        368,
        1760
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "f20a894e-3505-404b-a2f8-8648bbed8301",
              "name": "URL",
              "type": "string",
              "value": "={{ $json.URL }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "387ef4ed-617a-4421-900f-05c6e84ff7b1",
      "name": "Validating Unique Results",
      "type": "n8n-nodes-base.merge",
      "position": [
        672,
        1744
      ],
      "parameters": {
        "mode": "combine",
        "options": {
          "fuzzyCompare": true
        },
        "joinMode": "keepNonMatches",
        "outputDataFrom": "input1",
        "fieldsToMatchString": "['URL']"
      },
      "typeVersion": 3.2
    },
    {
      "id": "3e6771bb-fdf6-48ce-a3c5-5e4b49f042fa",
      "name": "If Site exists",
      "type": "n8n-nodes-base.if",
      "position": [
        976,
        1744
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "fc7625cf-225d-4d8e-8dd2-474bd65b6d8d",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.URL }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e07c2d9a-d9ce-4cc1-9e11-5e502325ac40",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        -656
      ],
      "parameters": {
        "color": 3,
        "width": 1824,
        "height": 704,
        "content": "## Phase 1: Google Custom Search Branch\n\n \n1. When chat message received: \ud83d\udcac Chat Input: Captures the user's search query to start the lead generation process.\n2. Setting Pagination: \ud83d\udcc4 Google Search Paginator: Creates a sequence (1, 11, 21) to search multiple pages of Google results.\n3. Loop for Multiple Page Search: \ud83d\udd04 Page Loop: Processes each page number individually to perform a separate Google search for each.\n4. Custom Google Search API: \ud83d\udd0d Google Search API Call: Executes the search using the user's query and current page number to get web results.\n5. Flatten Output Items: \ud83d\udcc2 Flatten Search Results: Un-nests the API response, turning one block of 10 results into 10 individual items.\n6. Information Extraction: \u2728 Initial Data Structuring: Extracts key details like business name, URL, and description from the raw search results.\n7. Remove Duplicates From Searches: \ud83d\udeab Deduplicate Search Results: Ensures each unique business URL from the Google search is processed only once."
      },
      "typeVersion": 1
    },
    {
      "id": "e10066d0-7805-46e1-94fc-b1606477adbf",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        96
      ],
      "parameters": {
        "width": 2032,
        "height": 704,
        "content": "## Phase 2: Google Maps Search Branch\n\n \n1.Prepare Query for Maps: \ud83d\uddfa\ufe0f Format Maps Query: Converts the chat input (e.g., \"dentists in New York\") into a URL-friendly format.\n2. Scrape Google Maps: \ud83d\udccd Google Maps Scraper: Scrapes the Google Maps search results page to find local business websites.\n3. Extract URLs: \ud83d\udd17 URL Extractor (Maps): Uses regex to pull all website links found on the Google Maps search results page.\n4. Filter Google URLs: \ud83d\uddd1\ufe0f Clean Maps URLs: Removes irrelevant links like google.com or schema.org from the scraped results.\n5. Remove Duplicates: \ud83d\udeab Deduplicate Maps Results: Ensures each unique business URL from the Maps scrape is processed only once.\n6. Loop Over Items: \ud83d\udd04 Maps URL Loop: Processes each unique URL from the Maps scrape one by one for deeper analysis.\n7. Scrape Map Sites: \ud83c\udf10 Website Scraper (Maps): Visits the business's website URL found via Maps to download its HTML content.\n8. Wait2: \u23f3 Rate Limiter: Pauses for 1 second between scraping sites to avoid being blocked.\n9. Extract Information: \ud83d\udd75\ufe0f Contact Extractor (Maps): Scans the website's HTML to find emails, phone numbers, and social media links."
      },
      "typeVersion": 1
    },
    {
      "id": "60c0c125-0be0-4cb6-8a53-eb7c01ecd83a",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        816
      ],
      "parameters": {
        "color": 5,
        "width": 2032,
        "height": 560,
        "content": "## Phase 3: Data Enrichment & Saving\n\n \n1. If: \ud83e\udd14 Email Checkpoint: Checks if an email was found; if not, it sends the URL for deeper website scraping.\n2. Loop Over Items1: \ud83d\udd04 Website Scrape Loop: Processes each lead that needs more data by visiting its website individually.\n3. Scrape Site2: \ud83c\udf10 Website Scraper (Search): Visits the business's website URL found via Google Search to download its HTML content.\n4. If Site scrapped: \u2705 Scrape Success Check: Proceeds only if the website was successfully downloaded, skipping failed attempts.\n5. Extract Required Fields: \ud83d\udd75\ufe0f Contact Extractor (Search): Scans the website's HTML to find emails, phone numbers, and social links.\n6. Set All Fields: \ud83d\udccb Consolidate Data: Gathers all newly found contact details into a single, structured item."
      },
      "typeVersion": 1
    },
    {
      "id": "e9b69fd8-053b-42e7-9b46-108e987b684c",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        16,
        1440
      ],
      "parameters": {
        "color": 3,
        "width": 1808,
        "height": 480,
        "content": "## Phase 4: Final Validation & Output\n\n1. Get row(s) in sheet / Get row(s) in sheet1: \ud83d\udcda Load Existing Leads: Fetches all previously saved leads from the Google Sheet for deduplication.\n2. Set URL for Validation / Set URL Validaiton: \ud83d\udd16 Prepare for Matching: Isolates the URL field from all leads to prepare for the duplication check.\n3. Not Duplicate Search Results / Validating Unique Results: \ud83d\udee1\ufe0f Final Duplicate Check: Compares new leads against the existing Google Sheet to ensure only unique businesses are saved.\n4. If Site Exists / If Site exists: \ud83d\udd17 URL Existence Check: Ensures the lead has a valid URL before proceeding.\n5. Exclude Articles and Blogs: \ud83d\udcf0 Filter Content Sites: Removes results that are likely articles or blogs, focusing on business websites.\n6. Remove Duplicates For Sheets / Remove Duplicates3: \ud83d\udeab Final Deduplication: A final check to remove any possible duplicates before writing to the sheet.\n7. Append row in sheet / Append row in sheet2: \u270d\ufe0f Save Lead to Sheet: Appends the final, enriched, and unique lead data as a new row in Google Sheets.\n "
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d33f9984-9987-4df7-916f-14b1f42c3e39",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Append row in sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait2": {
      "main": [
        [
          {
            "node": "Extract Information",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract URLs": {
      "main": [
        [
          {
            "node": "Filter Google URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Site2": {
      "main": [
        [
          {
            "node": "If Site scrapped",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Site Exists": {
      "main": [
        [
          {
            "node": "Exclude Articles and Blogs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Site exists": {
      "main": [
        [
          {
            "node": "Remove Duplicates3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set All Fields": {
      "main": [
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Validating Unique Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Scrape Map Sites",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Site scrapped": {
      "main": [
        [
          {
            "node": "Extract Required Fields",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items1": {
      "main": [
        [
          {
            "node": "Not Duplicate Search Results",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Scrape Site2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Map Sites": {
      "main": [
        [
          {
            "node": "Wait2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Google URLs": {
      "main": [
        [
          {
            "node": "Remove Duplicates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates3": {
      "main": [
        [
          {
            "node": "Append row in sheet2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Google Maps": {
      "main": [
        [
          {
            "node": "Extract URLs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set URL Validaiton": {
      "main": [
        [
          {
            "node": "Validating Unique Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Setting Pagination": {
      "main": [
        [
          {
            "node": "Loop for Multiple Page Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Information": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "Set URL for Validation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Flatten Output Items": {
      "main": [
        [
          {
            "node": "Information Extraction",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet1": {
      "main": [
        [
          {
            "node": "Set URL Validaiton",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Information Extraction": {
      "main": [
        [
          {
            "node": "Remove Duplicates From Searches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Query for Maps": {
      "main": [
        [
          {
            "node": "Scrape Google Maps",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set URL for Validation": {
      "main": [
        [
          {
            "node": "Not Duplicate Search Results",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Extract Required Fields": {
      "main": [
        [
          {
            "node": "Set All Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Custom Google Search API": {
      "main": [
        [
          {
            "node": "Flatten Output Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validating Unique Results": {
      "main": [
        [
          {
            "node": "If Site exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Exclude Articles and Blogs": {
      "main": [
        [
          {
            "node": "Remove Duplicates For Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "Setting Pagination",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Prepare Query for Maps",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get row(s) in sheet1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Not Duplicate Search Results": {
      "main": [
        [
          {
            "node": "If Site Exists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates For Sheets": {
      "main": [
        [
          {
            "node": "Add Search Results in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop for Multiple Page Search": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Custom Google Search API",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates From Searches": {
      "main": [
        [
          {
            "node": "Loop for Multiple Page Search",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

It acts as a powerful scraping agent that takes a simple chat query, scours both Google Search and Google Maps for relevant businesses, scrapes their websites for contact details, and compiles an enriched lead list directly in Google Sheets. Sales Development Representatives…

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

More Marketing & Ads workflows → · Browse all categories →

Related workflows

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

Marketing & Ads

Master Social Scraper (Google Sheets). Uses chatTrigger, textClassifier, lmChatOpenAi, httpRequest. Chat trigger; 36 nodes.

Chat Trigger, Text Classifier, OpenAI Chat +4
Marketing & Ads

What Native n8n chat-operated AI employee for a single wellness SaaS brand Handles three intents: send campaign, report campaign, reactivate cold subscribers

Chat Trigger, OpenRouter Chat, Agent +4
Marketing & Ads

The Recap AI - Insurance Lawyer Lead Gen. Uses executeWorkflowTrigger, formTrigger, @mendable/n8n-nodes-firecrawl, googleSheets. Event-driven trigger; 33 nodes.

Execute Workflow Trigger, Form Trigger, @Mendable/N8N Nodes Firecrawl +4
Marketing & Ads

Lead Generation + Outreach. Uses httpRequest, manualTrigger, googleSheets, scheduleTrigger. Event-driven trigger; 15 nodes.

HTTP Request, Google Sheets, Chain Llm +1
Marketing & Ads

My workflow 11. Uses manualTrigger, splitOut, httpRequest, splitInBatches. Event-driven trigger; 14 nodes.

HTTP Request, OpenAI, Google Sheets +2