Extraction de contacts commerciaux de Google Maps vers Google Sheets via RapidAPI et Google Sheets
Ceci est unLead Generationworkflow d'automatisation du domainecontenant 16 nœuds.Utilise principalement des nœuds comme Set, Code, Wait, Merge, HttpRequest. Extraire les leads commerciaux de Google Maps vers Google Sheets avec RapidAPI et Google Sheets
- •Peut nécessiter les informations d'identification d'authentification de l'API cible
- •Informations d'identification Google Sheets API
Nœuds utilisés (16)
Catégorie
{
"meta": {
"instanceId": "ea94475e7076b2e72d3d36bb4202c7da062eea5a94e247647c6066ed6cd6f743",
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "a4df4dee-6fda-4051-99d0-63824e197820",
"name": "Démarrer la génération de prospects",
"type": "n8n-nodes-base.manualTrigger",
"notes": "🚀 Click here to start extracting Google Maps business leads. Ensure your search criteria are configured in the Google Sheets 'keyword_searches' tab first.",
"position": [
-360,
-320
],
"parameters": {},
"typeVersion": 1
},
{
"id": "51c45a00-0d87-4ff0-836c-5354e332f802",
"name": "Configurer les paramètres de recherche",
"type": "n8n-nodes-base.set",
"notes": "⚙️ Prepares API search parameters from Google Sheets data. Modify the limit (max 100) and other parameters as needed for your use case.",
"position": [
1100,
-300
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b7344336-0887-40f5-b853-276eb1dba1bf",
"name": "search",
"type": "string",
"value": "={{ $json.query }}"
},
{
"id": "1eb2f614-e6e7-4b0f-bc39-02ce929873e6",
"name": "latitude",
"type": "string",
"value": "={{ $json.lat }}"
},
{
"id": "0cf94d77-ef0d-4b06-bbb1-c3040dd60a24",
"name": "longitude",
"type": "string",
"value": "={{ $json.lon }}"
},
{
"id": "0fc8e386-f81a-44b4-a5c4-162c1d85fd46",
"name": "region",
"type": "string",
"value": "={{ $json.country_iso_code }}"
},
{
"id": "c368eb39-dfc9-4790-987f-b97fd0297245",
"name": "language",
"type": "string",
"value": "EN"
},
{
"id": "cdb5db50-6d2f-4b80-9e47-4ace539290ba",
"name": "zoom",
"type": "string",
"value": "13"
},
{
"id": "d47e2e85-bcc8-48d0-a8a2-8b1d04bd2a16",
"name": "limit",
"type": "string",
"value": "100"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "e6385c2d-4f61-495a-93ab-766541fa4579",
"name": "Google Maps API Request",
"type": "n8n-nodes-base.httpRequest",
"notes": "🗺️ Calls RapidAPI's Local Business Data service to extract comprehensive business information from Google Maps, including emails and social media contacts.",
"onError": "continueRegularOutput",
"position": [
1460,
-300
],
"parameters": {
"url": "https://local-business-data.p.rapidapi.com/search-in-area",
"options": {},
"jsonQuery": "={\"query\":\"{{ $json.search }}\"\n ,\"lat\":\"{{ $json.latitude }}\"\n ,\"lng\":\"{{ $json.longitude }}\"\n ,\"zoom\":\"{{ $json.zoom }}\"\n ,\"limit\":\"{{ $json.limit }}\"\n ,\"language\":\"{{ $json.language }}\"\n ,\"region\":\"{{ $json.region }}\"\n ,\"extract_emails_and_contacts\":\"true\"} ",
"sendQuery": true,
"specifyQuery": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"id": "1UBwOxs2haJZLITp",
"name": "Google Maps API"
}
},
"typeVersion": 4.2
},
{
"id": "5ddb7eca-5989-4572-9ef6-d7f74f566b33",
"name": "Analyser les données d'entreprise",
"type": "n8n-nodes-base.code",
"notes": "🔄 Processes API response and extracts all business information including contact details, social media profiles, and location data into a structured format.",
"position": [
1800,
-300
],
"parameters": {
"jsCode": "// Get the input data\nconst inputData = $input.first().json;\n\n// Try to find the data array and parameters\nlet data, parameters;\n\n// Check if inputData is the array directly\nif (Array.isArray(inputData)) {\n // If inputData is an array, look for the object with data property\n const dataObj = inputData.find(item => item.data);\n if (dataObj) {\n data = dataObj.data;\n parameters = dataObj.parameters;\n }\n} else if (inputData.data) {\n // If inputData is an object with data property\n data = inputData.data;\n parameters = inputData.parameters;\n}\n\n// If we still don't have data, return an error\nif (!data || !Array.isArray(data)) {\n return [{ json: { error: \"Could not find data array\", inputStructure: Object.keys(inputData) } }];\n}\n\n// Helper function to extract emails as comma-separated string\nfunction extractEmails(emailsArray) {\n if (!emailsArray || !Array.isArray(emailsArray) || emailsArray.length === 0) {\n return null;\n }\n return emailsArray.join(', ');\n}\n\n// Process each business\nconst outputData = data.map(business => ({\n // Search parameters\n query: parameters?.query || null,\n language: parameters?.language || null,\n lat: parameters?.lat || null,\n lon: parameters?.lng || parameters?.lon || null,\n zoom: parameters?.zoom || null,\n limit: parameters?.limit || null,\n \n // Business data\n business_id: business.business_id || null,\n place_id: business.place_id || null,\n phone_number: business.phone_number || null,\n name: business.name || null,\n full_address: business.full_address || null,\n review_count: business.review_count || null,\n rating: business.rating || null,\n website: business.website || null,\n verified: business.verified || null,\n type: business.type || null,\n reviews_link: business.reviews_link || null,\n place_link: business.place_link || null,\n about_summary: business.about?.summary || null,\n address: business.address || null,\n price_level: business.price_level || null,\n district: business.district || null,\n street_address: business.street_address || null,\n city: business.city || null,\n zipcode: business.zipcode || null,\n state: business.state || null,\n country: business.country || null,\n \n // Extract emails and social media contacts\n email: extractEmails(business.emails_and_contacts?.emails),\n linkedin: business.emails_and_contacts?.linkedin || null,\n instagram: business.emails_and_contacts?.instagram || null,\n \n // Additional social media fields\n facebook: business.emails_and_contacts?.facebook || null,\n twitter: business.emails_and_contacts?.twitter || null,\n youtube: business.emails_and_contacts?.youtube || null,\n tiktok: business.emails_and_contacts?.tiktok || null,\n pinterest: business.emails_and_contacts?.pinterest || null,\n snapchat: business.emails_and_contacts?.snapchat || null,\n github: business.emails_and_contacts?.github || null,\n yelp: business.emails_and_contacts?.yelp || null,\n \n // Additional phone numbers from emails_and_contacts\n additional_phones: business.emails_and_contacts?.phone_numbers?.length > 0 \n ? business.emails_and_contacts.phone_numbers.join(', ') \n : null\n}));\n\n// Return the processed data\nreturn outputData.map(item => ({ json: item }));"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "e88dbb0c-d2d6-4a3b-a4c1-0862a2755f4a",
"name": "Charger les critères de recherche",
"type": "n8n-nodes-base.googleSheets",
"notes": "📋 Reads search criteria from the 'keyword_searches' sheet. Only processes rows marked with 'X' in the 'select' column for targeted lead generation.",
"position": [
80,
-540
],
"parameters": {
"options": {},
"filtersUI": {
"values": [
{
"lookupValue": "X",
"lookupColumn": "select"
}
]
},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "keyword_searches"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.6
},
{
"id": "c7deb7f2-0df6-4929-9996-7e17bc6c493a",
"name": "Traiter chaque localisation",
"type": "n8n-nodes-base.splitInBatches",
"notes": "🔄 Loops through each selected search criteria to avoid overwhelming the API and ensure reliable processing of multiple locations.",
"position": [
740,
-320
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "932ee9e5-1924-4fa1-b7ed-b76817d8d1a0",
"name": "Sauvegarder les nouveaux prospects",
"type": "n8n-nodes-base.googleSheets",
"notes": "💾 Saves only new business leads to the 'stores_data' sheet. Duplicates are filtered out by the previous merge step.",
"position": [
2100,
-300
],
"parameters": {
"columns": {
"value": {
"lat": "={{ $json.lat }}",
"lon": "={{ $json.lon }}",
"city": "={{ $json.city }}",
"name": "={{ $json.name }}",
"type": "={{ $json.type }}",
"zoom": "={{ $json.zoom }}",
"email": "={{ $json.email }}",
"limit": "={{ $json.limit }}",
"query": "={{ $json.query }}",
"state": "={{ $json.state }}",
"rating": "={{ $json.rating }}",
"address": "={{ $json.full_address }}",
"country": "={{ $json.country }}",
"website": "={{ $json.website }}",
"district": "={{ $json.district }}",
"language": "={{ $json.language }}",
"linkedin": "={{ $json.linkedin }}",
"place_id": "={{ $json.place_id }}",
"verified": "={{ $json.verified }}",
"zip_code": "={{ $json.zipcode }}",
"instagram": "={{ $json.instagram }}",
"place_link": "={{ $json.place_link }}",
"business_id": "={{ $json.business_id }}",
"price_level": "={{ $json.price_level }}",
"full_address": "={{ $json.full_address }}",
"phone_number": "={{ $json.phone_number }}",
"review_count": "={{ $json.review_count }}",
"reviews_link": "={{ $json.reviews_link }}",
"about_summary": "={{ $json.about_summary }}",
"street_address": "={{ $json.street_address }}",
"additional_phones": "={{ $json.additional_phones }}"
},
"schema": [
{
"id": "business_id",
"type": "string",
"display": true,
"required": false,
"displayName": "business_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "query",
"type": "string",
"display": true,
"required": false,
"displayName": "query",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "name",
"type": "string",
"display": true,
"required": false,
"displayName": "name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "phone_number",
"type": "string",
"display": true,
"required": false,
"displayName": "phone_number",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "email",
"type": "string",
"display": true,
"required": false,
"displayName": "email",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "website",
"type": "string",
"display": true,
"required": false,
"displayName": "website",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "full_address",
"type": "string",
"display": true,
"required": false,
"displayName": "full_address",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "rating",
"type": "string",
"display": true,
"required": false,
"displayName": "rating",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "linkedin",
"type": "string",
"display": true,
"required": false,
"displayName": "linkedin",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "instagram",
"type": "string",
"display": true,
"required": false,
"displayName": "instagram",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "stores_data"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"typeVersion": 4.6
},
{
"id": "8a36189b-b07f-4af1-bc55-f0c835251927",
"name": "Délai de limite de taux",
"type": "n8n-nodes-base.wait",
"notes": "⏱️ 10-second delay between API calls to respect rate limits and prevent being blocked. Adjust timing based on your API plan.",
"position": [
2100,
-20
],
"webhookId": "0bb83f04-8260-42b7-b108-632b91040a0e",
"parameters": {
"amount": 10
},
"typeVersion": 1.1
},
{
"id": "53044569-b459-4825-8ce5-a82c2d80fb45",
"name": "Charger les prospects existants",
"type": "n8n-nodes-base.googleSheets",
"notes": "📊 Reads existing leads from the database to enable duplicate detection and prevent re-processing the same businesses.",
"position": [
60,
-40
],
"parameters": {
"options": {},
"sheetName": {
"__rl": true,
"mode": "list",
"value": "stores_data"
},
"documentId": {
"__rl": true,
"mode": "id",
"value": "YOUR_GOOGLE_SHEET_ID"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"id": "YnLHwhwL7bsy8LoY",
"name": "Google Sheets account"
}
},
"typeVersion": 4.6
},
{
"id": "511e0baf-8741-431f-9c88-b2e2237b9ebb",
"name": "Filtrer les nouvelles recherches",
"type": "n8n-nodes-base.merge",
"notes": "🔍 Smart duplicate prevention: Only processes search criteria that haven't been executed before, saving API calls and avoiding duplicate data.",
"position": [
440,
-320
],
"parameters": {
"mode": "combine",
"options": {},
"joinMode": "keepNonMatches",
"outputDataFrom": "input1",
"fieldsToMatchString": "query, lat"
},
"typeVersion": 3.2
},
{
"id": "73efc100-3000-4936-a67b-30bdde13ba7d",
"name": "Note adhésive",
"type": "n8n-nodes-base.stickyNote",
"position": [
-840,
-520
],
"parameters": {
"color": 4,
"width": 400,
"height": 620,
"content": "# Google Maps Lead Generation Workflow\n\n## 🎯 **Overview**\nThis workflow extracts business leads from Google Maps with contact information and stores them in Google Sheets with intelligent duplicate prevention.\n\n## 📋 **Before Starting:**\n1. Set up RapidAPI account with Local Business Data API\n2. Create Google Sheet with 'keyword_searches' and 'stores_data' tabs\n3. Configure credentials in n8n\n4. Add your search queries to Google Sheets\n\n## 🚀 **How to Use:**\n- Mark search queries with 'X' in select column\n- Click 'Start Lead Generation' to begin\n- Workflow automatically prevents duplicates\n- Results saved to 'stores_data' sheet"
},
"typeVersion": 1
},
{
"id": "45ee9c11-3bf7-44dc-8359-cedf43e7c100",
"name": "Note adhésive1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-280,
-940
],
"parameters": {
"color": 5,
"width": 350,
"height": 400,
"content": "## 📊 **INPUT DATA STRUCTURE**\n\n**keyword_searches** sheet columns:\n```\n| select | query | lat | lon | country_iso_code |\n|--------|-------|-----|-----|------------------|\n| X | Restaurants Madrid | 40.4168 | -3.7038 | ES |\n| X | Hair Salons NYC | 40.7589 | -73.9851 | US |\n```\n\n**Tips:**\n- Use 'X' to mark queries for processing\n- Be specific with search terms\n- Include accurate coordinates\n- Use 2-letter country codes"
},
"typeVersion": 1
},
{
"id": "96e90ea0-93e3-4f95-a51a-1d37c17c4476",
"name": "Note adhésive2",
"type": "n8n-nodes-base.stickyNote",
"position": [
340,
-740
],
"parameters": {
"color": 6,
"width": 320,
"height": 740,
"content": "## 🔄 **DUPLICATE PREVENTION**\n\nThis workflow has **2-level duplicate prevention:**\n\n**Level 1: Search Level**\n- Compares new queries with existing data\n- Skips queries already processed\n- Saves API costs (50-80% reduction)\n\n**Level 2: Business Level**\n- Each business has unique business_id\n- Prevents duplicate business entries\n- Maintains data integrity"
},
"typeVersion": 1
},
{
"id": "a31ffc0b-2bdd-419c-97b9-583af5b91e3a",
"name": "Note adhésive3",
"type": "n8n-nodes-base.stickyNote",
"position": [
960,
-520
],
"parameters": {
"color": 7,
"width": 320,
"height": 200,
"content": "## ⚙️ **API CONFIGURATION**\n\n**Search Parameters:**\n- **Limit**: 100 results max per query\n- **Zoom**: 13 (city-wide) to 18 (local)\n- **Language**: EN, ES, FR, etc.\n- **Extract Contacts**: Always enabled\n\n**Rate Limiting:**\n- 10 seconds between requests\n- Prevents API blocking\n- Adjustable based on your plan"
},
"typeVersion": 1
},
{
"id": "20ddcaad-738a-4bed-93ff-c7a044c3fc21",
"name": "Note adhésive4",
"type": "n8n-nodes-base.stickyNote",
"position": [
1420,
-720
],
"parameters": {
"color": 5,
"width": 540,
"height": 400,
"content": "## 📱 **EXTRACTED DATA**\n\n**Business Information:**\n- Name, address, phone, website\n- Rating, reviews, verification status\n- Business type, price level\n\n**Contact Details:**\n- Email addresses\n- LinkedIn, Instagram profiles\n- Facebook, Twitter, YouTube\n- Additional phone numbers\n\n**Location Data:**\n- Full address, coordinates\n- City, state, country, zip code"
},
"typeVersion": 1
},
{
"id": "20ccaa92-bf61-4f75-a81b-d6b1e0f550b5",
"name": "Note adhésive5",
"type": "n8n-nodes-base.stickyNote",
"position": [
2160,
-660
],
"parameters": {
"color": 3,
"width": 350,
"height": 340,
"content": "## 📈 **EXECUTION FLOW**\n\n**1.** Load search criteria (marked with X)\n**2.** Load existing leads for comparison\n**3.** Filter out already processed searches\n**4.** Loop through each new search\n**5.** Configure API parameters\n**6.** Call Google Maps API\n**7.** Parse and structure data\n**8.** Save new leads to sheet\n**9.** Wait 10 seconds (rate limiting)\n**10.** Continue to next search\n\n✅ **Result**: Clean, organized lead database without duplicates!"
},
"typeVersion": 1
}
],
"pinData": {},
"connections": {
"932ee9e5-1924-4fa1-b7ed-b76817d8d1a0": {
"main": [
[
{
"node": "8a36189b-b07f-4af1-bc55-f0c835251927",
"type": "main",
"index": 0
}
]
]
},
"8a36189b-b07f-4af1-bc55-f0c835251927": {
"main": [
[
{
"node": "c7deb7f2-0df6-4929-9996-7e17bc6c493a",
"type": "main",
"index": 0
}
]
]
},
"511e0baf-8741-431f-9c88-b2e2237b9ebb": {
"main": [
[
{
"node": "c7deb7f2-0df6-4929-9996-7e17bc6c493a",
"type": "main",
"index": 0
}
]
]
},
"53044569-b459-4825-8ce5-a82c2d80fb45": {
"main": [
[
{
"node": "511e0baf-8741-431f-9c88-b2e2237b9ebb",
"type": "main",
"index": 1
}
]
]
},
"5ddb7eca-5989-4572-9ef6-d7f74f566b33": {
"main": [
[
{
"node": "932ee9e5-1924-4fa1-b7ed-b76817d8d1a0",
"type": "main",
"index": 0
}
]
]
},
"e88dbb0c-d2d6-4a3b-a4c1-0862a2755f4a": {
"main": [
[
{
"node": "511e0baf-8741-431f-9c88-b2e2237b9ebb",
"type": "main",
"index": 0
}
]
]
},
"c7deb7f2-0df6-4929-9996-7e17bc6c493a": {
"main": [
[],
[
{
"node": "51c45a00-0d87-4ff0-836c-5354e332f802",
"type": "main",
"index": 0
}
]
]
},
"a4df4dee-6fda-4051-99d0-63824e197820": {
"main": [
[
{
"node": "e88dbb0c-d2d6-4a3b-a4c1-0862a2755f4a",
"type": "main",
"index": 0
},
{
"node": "53044569-b459-4825-8ce5-a82c2d80fb45",
"type": "main",
"index": 0
}
]
]
},
"e6385c2d-4f61-495a-93ab-766541fa4579": {
"main": [
[
{
"node": "5ddb7eca-5989-4572-9ef6-d7f74f566b33",
"type": "main",
"index": 0
}
]
]
},
"51c45a00-0d87-4ff0-836c-5354e332f802": {
"main": [
[
{
"node": "e6385c2d-4f61-495a-93ab-766541fa4579",
"type": "main",
"index": 0
}
]
]
}
}
}Comment utiliser ce workflow ?
Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.
Dans quelles scénarios ce workflow est-il adapté ?
Avancé - Génération de leads
Est-ce payant ?
Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.
Workflows recommandés
Javier Hita
@javierhitaBuilding Automation tools as a Data Analyst for over 6 years, N8N is a great tool to leverage that background.
Partager ce workflow