AutomationFlowsMarketing & Ads › Generate B2b Leads by Industry & Location with Google Places API and Google…

Generate B2b Leads by Industry & Location with Google Places API and Google…

Original n8n title: Generate B2b Leads by Industry & Location with Google Places API and Google Sheets

ByAyis Saliaris Fasseas @ayissf on n8n.io

How it works A form trigger accepts an Industry + Location query (e.g. Accountants London). Text Search Page 1 calls Google Places Text Search to return results and a nextpagetoken. Conditional checks + 5s wait nodes fetch page 2 and page 3 when a next page exists. All pages are…

Event trigger★★★★☆ complexity19 nodesHTTP RequestForm TriggerGoogle Sheets
Marketing & Ads Trigger: Event Nodes: 19 Complexity: ★★★★☆ Added:

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

This workflow follows the Form 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
{
  "nodes": [
    {
      "id": "639000ce-f6c5-41ab-a593-907c2b6008c4",
      "name": "Text Search Page 2",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        704,
        272
      ],
      "parameters": {
        "url": "https://maps.googleapis.com/maps/api/place/textsearch/json",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "pagetoken",
              "value": "={{ $json.next_page_token }}"
            },
            {
              "name": "key",
              "value": "<YOUR KEY>"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "f4368da1-c340-4753-800b-a7dec5821882",
      "name": "Text Search Page 1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        704,
        80
      ],
      "parameters": {
        "url": "https://maps.googleapis.com/maps/api/place/textsearch/json",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "query",
              "value": "={{ $json.Query }}"
            },
            {
              "name": "key",
              "value": "<YOUR KEY>"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c29c09a1-ca61-44d7-8c45-df0addc6d0e5",
      "name": "Text Search Page 3",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        704,
        464
      ],
      "parameters": {
        "url": "https://maps.googleapis.com/maps/api/place/textsearch/json",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "pagetoken",
              "value": "={{ $json.next_page_token }}"
            },
            {
              "name": "key",
              "value": "<YOUR KEY>"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b1d0e24f-4fc3-4271-a705-b4bec3e85834",
      "name": "Get Place Details",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1504,
        272
      ],
      "parameters": {
        "url": "https://maps.googleapis.com/maps/api/place/details/json",
        "options": {},
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "place_id",
              "value": "={{ $json.place_id }}"
            },
            {
              "name": "fields",
              "value": "name,formatted_phone_number,website,formatted_address"
            },
            {
              "name": "key",
              "value": "<YOUR KEY>"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "20d694c8-a729-4ec9-9f36-b7bca1b34052",
      "name": "Wait 5s (1)",
      "type": "n8n-nodes-base.wait",
      "position": [
        464,
        272
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "a42f166a-1297-4d65-8059-4f940744562f",
      "name": "Wait 5s (2)",
      "type": "n8n-nodes-base.wait",
      "position": [
        464,
        464
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "0687a2d7-c1c2-410c-b72a-0ecba38c5d05",
      "name": "Has Next Page? (Page 3)",
      "type": "n8n-nodes-base.if",
      "position": [
        240,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "edd655eb-d1f5-486f-b120-91b822cc1021",
              "operator": {
                "type": "string",
                "operation": "exists"
              },
              "leftValue": "={{ $json.next_page_token }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b01aee55-ca4a-4c59-97c5-5287cd7359d7",
      "name": "Has Next Page? (Page 2)",
      "type": "n8n-nodes-base.if",
      "position": [
        240,
        272
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "e59c4f7a-dee0-4b3f-b9c5-9833f3fdea1d",
              "operator": {
                "type": "string",
                "operation": "exists"
              },
              "leftValue": "={{ $json.next_page_token }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "78546956-7aef-4833-8e60-90f7a0ccefb9",
      "name": "Merge All Pages",
      "type": "n8n-nodes-base.merge",
      "position": [
        992,
        256
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.2
    },
    {
      "id": "221d1f7f-245e-45ef-80e7-8c91c0ebe7ff",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 528,
        "height": 640,
        "content": "## Find and merge results"
      },
      "typeVersion": 1
    },
    {
      "id": "333884c1-5dd8-45a8-a18a-45c3daebb7da",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1184,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 640,
        "content": "## Split out results and find places' details"
      },
      "typeVersion": 1
    },
    {
      "id": "1879c67b-70d0-4e23-ac24-9f0a8075a9c4",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 640,
        "content": "## Format output and upload to Google Sheet"
      },
      "typeVersion": 1
    },
    {
      "id": "53f9e7ae-d822-4d06-ae69-5508582765e6",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 640,
        "content": "## Check if Google Maps next page exists (Wait nodes for API call quota)"
      },
      "typeVersion": 1
    },
    {
      "id": "642387ad-57ae-4452-9c35-4c451c1e9f3d",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        352,
        -352
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 192,
        "content": "## Form Trigger"
      },
      "typeVersion": 1
    },
    {
      "id": "8bf00721-e5af-4525-898d-de316de48c41",
      "name": "Submit Search Query",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        400,
        -304
      ],
      "parameters": {
        "options": {},
        "formTitle": "Enter your Query",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Query",
              "placeholder": "Ex. Accountants London",
              "requiredField": true
            }
          ]
        },
        "formDescription": "Enter Industry + Location"
      },
      "typeVersion": 2.3
    },
    {
      "id": "111b2fe9-59f5-4b0e-9f9e-3e3eef5fb44d",
      "name": "Split out the Results",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1280,
        272
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "results"
      },
      "typeVersion": 1
    },
    {
      "id": "dce85a88-9dd6-4c1c-8c9d-19dd3740c0ba",
      "name": "Format the Output for Google Sheets",
      "type": "n8n-nodes-base.code",
      "position": [
        1808,
        272
      ],
      "parameters": {
        "jsCode": "return $input.all().map(item => {\n  const data = item.json.result || {};\n  let phone = data.formatted_phone_number || null;\n\n  return {\n    json: {\n      companyName: data.name || null,\n      number: phone,\n      address: data.formatted_address || null,\n      website: data.website || null\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "cb484a57-209c-4402-a876-a732b4c4c90a",
      "name": "Append rows in the Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2016,
        272
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [
            {
              "id": "Company Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Company Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Website",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Website",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Phone Number",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Phone Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email Sent?",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Email Sent?",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "1st Follow Up Sent?",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "1st Follow Up Sent?",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "2nd Follow Up Sent?",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "2nd Follow Up Sent?",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Replied?",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Replied?",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 761417546,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/178cjDnXdsPPFJCQ9oyw6yCpEYdvvS39sotD4nZFeoEs/edit#gid=761417546",
          "cachedResultName": "Results"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "178cjDnXdsPPFJCQ9oyw6yCpEYdvvS39sotD4nZFeoEs",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/178cjDnXdsPPFJCQ9oyw6yCpEYdvvS39sotD4nZFeoEs/edit?usp=drivesdk",
          "cachedResultName": "Runwise Lead List"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "462ba5ac-48c9-44a5-9927-4d80023977c2",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        -480
      ],
      "parameters": {
        "width": 896,
        "height": 880,
        "content": "## How it works\n1. A form trigger accepts an Industry + Location query (e.g. Accountants London).\n2. Text Search Page 1 calls Google Places Text Search to return results and a next_page_token.\n3. Conditional checks + 5s wait nodes fetch page 2 and page 3 when a next page exists.\n4. All pages are merged, split into individual place results, and each place_id is passed to Place Details.\n5. Place Details returns name, formatted_phone_number, website, formatted_address.\n6. Results are formatted and appended to a Google Sheet.\n## Setup steps\n- Enable Google Cloud project billing and Places API (Text Search + Details).\n- Create an API key and add it to the three Text Search and Place Details HTTP request nodes (<YOUR KEY>).\n- Add Google Sheets OAuth credentials to the Google Sheets node.\n- Create a Google Sheet with columns: Company Name, Phone Number, Website, Address\n- Update the Google Sheets node documentId and sheetName to your spreadsheet.\n- Import/paste this workflow into n8n and test with a small query.\n## Customization\n- Edit Place Details fields to retrieve more/less info (address_components, opening_hours, etc.).\n- Adjust the number of pages fetched (workflow currently supports up to 3 pages).\n- Alter output mapping in the code node to add/remove columns or change column order.\n- Add further nodes after the sheet (e.g., email scraper/ sender, CRM integration, enrichment API)\n## Use cases\n- B2B lead generation for targeted industries and locations.\n- Building outreach lists for sales teams and agencies.\n- Enriching CRM with phone, website, and address data from Google Places.\n- Rapid market mapping for local competitors, vendors, or partners.\n## Troubleshooting tips\n- No results / invalid API key: verify API key is correct, not restricted incorrectly, and Places API is enabled.\n- next_page_token not working: the token can take a couple of seconds to activate. Keep the 5s wait nodes; if still failing, increase to ~10s+\n- Quota / billing errors: confirm billing is enabled on the Google Cloud project and check your Places API quota.\n- Missing phone/website: not all places provide all fields; fallback handling is already included (nulls).\n- Duplicates in Sheets: run tests on small queries and inspect the Merge/Split logic; add a dedupe step before appending if needed.\n- Place Details rate limits: if you plan high volume, throttle requests or add longer waits to avoid quota/rate-limit errors.\n- Permissions / OAuth: ensure the Google Sheets OAuth user has edit access to the target spreadsheet."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Wait 5s (1)": {
      "main": [
        [
          {
            "node": "Text Search Page 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 5s (2)": {
      "main": [
        [
          {
            "node": "Text Search Page 3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge All Pages": {
      "main": [
        [
          {
            "node": "Split out the Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Place Details": {
      "main": [
        [
          {
            "node": "Format the Output for Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text Search Page 1": {
      "main": [
        [
          {
            "node": "Has Next Page? (Page 2)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge All Pages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Text Search Page 2": {
      "main": [
        [
          {
            "node": "Has Next Page? (Page 3)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge All Pages",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Text Search Page 3": {
      "main": [
        [
          {
            "node": "Merge All Pages",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Submit Search Query": {
      "main": [
        [
          {
            "node": "Text Search Page 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split out the Results": {
      "main": [
        [
          {
            "node": "Get Place Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Next Page? (Page 2)": {
      "main": [
        [
          {
            "node": "Wait 5s (1)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Next Page? (Page 3)": {
      "main": [
        [
          {
            "node": "Wait 5s (2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append rows in the Google Sheet": {
      "main": [
        []
      ]
    },
    "Format the Output for Google Sheets": {
      "main": [
        [
          {
            "node": "Append rows in the Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

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

About this workflow

How it works A form trigger accepts an Industry + Location query (e.g. Accountants London). Text Search Page 1 calls Google Places Text Search to return results and a nextpagetoken. Conditional checks + 5s wait nodes fetch page 2 and page 3 when a next page exists. All pages are…

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

This repository contains an SLA-based lead routing workflow built in n8n, designed to ensure fast lead response, fair sales distribution, and controlled escalation without relying on a full CRM system

Form Trigger, Google Sheets, Slack +1
Marketing & Ads

Agencies, sales teams, and service businesses who want to instantly qualify inbound leads with an AI-powered phone call — no manual follow-up needed.

Form Trigger, Google Sheets, HTTP Request
Marketing & Ads

This n8n template automates lead generation by scraping Google Maps using the Olostep API. It extracts business names, locations, websites, phone numbers, and decision-maker names (CEO, Founder, etc.)

Form Trigger, HTTP Request, Google Sheets
Marketing & Ads

This workflow is a powerful B2B Lead Generation engine designed specifically for SDRs (Sales Development Representatives). It automates the entire process of finding, enriching, and qualifying prospec

Form Trigger, HTTP Request, Google Sheets
Marketing & Ads

This workflow automates the process of generating niche-specific business leads from Google Maps, leveraging the Google Places API and Google Sheets for seamless data collection and storage. Business

HTTP Request, Form Trigger, Google Sheets