
Automatiser les leads Google Maps avec n8n : guide pratique
Oui, n8n peut automatiser une prospection Google Maps sans clics répétés ni script sur mesure. Le workflow lance une tâche BasedOnB avec l'API REST, contrôle son état à intervalles limités, récupère toutes les pages de résultats et envoie les entreprises vers Google Sheets ou un CRM.
Le POST initial est la partie facile. Un flux fiable doit aussi éviter les doublons lors d'une relance, arrêter le polling après un nombre défini d'essais, séparer les échecs et suivre le cursor de pagination. L'exemple ci-dessous cherche des agences immobilières à Lyon et garde chaque étape visible dans n8n.
Si votre cible ou vos colonnes ne sont pas encore claires, commencez par le guide de création d'une liste de leads Google Maps. La suite suppose que la catégorie, la ville, le volume et la destination sont déjà choisis.
Ce qu'il faut préparer
- Une instance n8n autorisée à envoyer des requêtes HTTPS.
- Une clé API BasedOnB avec les droits de lecture et d'écriture des tâches. Elle commence par
bdb_live_. - Une feuille ou un CRM avec une colonne d'identifiant externe.
- Un identifiant de campagne stable pour l'idempotence.
- Une requête, un pays, une région, une ville et un nombre de leads.
Créez la clé dans le tableau de bord, puis enregistrez-la dans un identifiant Header Auth de n8n. Ne placez jamais une vraie clé dans Edit Fields, un export de workflow, une capture ou un message d'assistance. Les endpoints et les réponses à jour sont dans la documentation API BasedOnB.
Respectez aussi les limites de travail. Une tâche accepte au plus 10 requêtes. Un compte peut avoir 2 tâches ouvertes et 5 000 leads cibles au total dans ces tâches. Les états pending, submitted et running sont ouverts. Une soumission au-delà de ces limites reçoit une réponse de capacité 429.
Vue d'ensemble du workflow
- Schedule Trigger ou Webhook reçoit la campagne.
- Edit Fields prépare les valeurs et la clé d'idempotence.
- HTTP Request envoie
POST /api/v1/scrapes. - IF vérifie
statusCodeet transforme une réponse réussie en état de polling à un élément. - Wait et Edit Fields augmentent
attemptdans cette branche d'état. - HTTP Request appelle
GET /api/v1/scrapes/:id; Merge réunit la réponse et l'état. - Switch sépare les erreurs HTTP,
done,failed,cancelledet les états ouverts. - Après
done, HTTP Request charge les pages et vérifie d'abordstatusCode. - Chaque page se divise une fois :
body.resultsva vers Split Out et un élément de contrôle litbody.page. - La branche de contrôle demande le cursor suivant une seule fois et ramène la réponse au même point de division.
La documentation officielle du nœud HTTP Request détaille l'authentification, les en-têtes et les paramètres. Celle du nœud Wait explique la pause et la reprise.
1. Préparer une requête stable
Ajoutez Edit Fields après le déclencheur. Pour Lyon, le corps peut rester simple :
{
"query": "real estate agencies",
"country": "FR",
"state": "FR.84",
"city": "Lyon",
"target_leads": 250
}
query décrit l'activité. Les trois champs de lieu délimitent la zone. target_leads indique le nombre de fiches souhaité et doit rester compatible avec les crédits et les tâches déjà ouvertes.
Ajoutez aussi idempotency_key, par exemple lyon-immobilier-2026-08-lot-01. Une référence CRM ou l'identifiant de l'événement source est encore préférable. Ne créez pas cette valeur avec l'heure actuelle. Une nouvelle heure lors d'une relance ressemblerait à une nouvelle demande.
2. Lancer la tâche
Réglez HTTP Request ainsi :
- Method :
POST - URL :
https://www.basedonb.com/api/v1/scrapes - Authentication : Header Auth avec
Authorization: Bearer bdb_live_... - Header :
Idempotency-Keylu depuis Edit Fields - Body Content Type : JSON
- Body : les cinq champs ci-dessus
- Options > Response > Include Response Headers and Status : activé
- Options > Response > Never Error : activé
- Options > Response > Response Format : JSON
Ces options demandent à n8n de fournir aussi les réponses hors 2xx en output. L'élément complet expose statusCode, headers et body. Commencez par une branche sur $json.statusCode. Seule une réponse 2xx passe à la logique métier. Créez alors un élément Poll State dans Edit Fields avec job_id = {{$json.body.id}}, job_status = {{$json.body.status}} et attempt = 0. Les autres codes vont vers la branche HTTP d'erreur commune.
Une nouvelle tâche renvoie souvent submitted, mais un résultat déjà disponible peut renvoyer done immédiatement. Après le contrôle 2xx, lisez donc $json.body.status avant de passer à Wait.
La même clé avec le même corps renvoie la tâche d'origine. La même clé avec une autre ville, requête ou cible crée un conflit. Enregistrez toujours la clé et son corps ensemble.
3. Faire un polling borné
Utilisez l'élément Poll State créé après le POST réussi. Routez son champ job_status :
doneva vers les résultats.failedoucancelledva vers la branche finale d'erreur.pending,submittedourunningva vers Wait.
Une attente fixe de 15 secondes est un exemple raisonnable. Après Wait, utilisez Edit Fields pour garder job_id et définir attempt = {{$json.attempt + 1}}. Reliez cet unique élément d'état à deux branches. L'Input 1 d'un nœud Merge le reçoit directement. L'autre branche appelle :
GET https://www.basedonb.com/api/v1/scrapes/{{$json.job_id}}
Utilisez le même identifiant Header Auth et les trois mêmes options Response que pour le POST. Reliez la réponse HTTP d'état à l'Input 2 de Merge. Réglez Merge sur Mode: Combine et Combine By: Position. L'élément réuni garde ainsi job_id et attempt avec statusCode et body; la réponse GET ne supprime pas le compteur.
Après Merge, vérifiez $json.statusCode avant de lire le corps. Les réponses hors 2xx vont vers la branche HTTP d'erreur commune. Pour une réponse 2xx, Switch lit $json.body.status et route done, failed, cancelled ou un état ouvert. Un IF séparé dans la branche ouverte contrôle $json.attempt avant le retour vers Wait.
Avant de revenir à Wait, ajoutez un IF sur le nombre de tentatives. À la limite, arrêtez le contrôle et envoyez une alerte avec l'identifiant de tâche. Quarante essais espacés de 15 secondes bornent cette exécution n8n, mais ne promettent pas que toute tâche finit en dix minutes. N'annulez pas automatiquement la tâche serveur à cette limite. Elle peut encore se terminer.
Les branches failed et cancelled ne doivent jamais revenir dans la boucle. Enregistrez l'état, l'identifiant de tâche, la campagne et si possible l'identifiant de requête. Examinez la cause avant toute nouvelle soumission.
4. Paginer tous les résultats
Appelez les résultats uniquement après done :
GET https://www.basedonb.com/api/v1/scrapes/{{$json.id}}/results
Ajoutez limit=500. Activez Include Response Headers and Status et Never Error, puis choisissez JSON comme Response Format, comme dans les autres nœuds HTTP Request. Vérifiez d'abord $json.statusCode; une réponse hors 2xx va vers la branche d'erreur commune. Une réponse complète réussie ressemble à ceci :
{
"statusCode": 200,
"body": {
"id": "scrape-job-id",
"status": "done",
"results": [],
"page": {
"limit": 500,
"next_cursor": "next-page-token",
"has_more": true,
"total": 1250
}
}
}
Gardez la réponse réussie de la page comme un seul élément et reliez-la à deux branches. La branche de données applique Split Out à body.results, puis mappe et met à jour les lignes. La branche de contrôle ne passe pas par Split Out. Son IF lit $json.body.page.has_more et s'exécute donc une fois par page, pas une fois par entreprise.
Dans la branche true, Edit Fields définit job_id = {{$json.body.id}} et cursor = {{$json.body.page.next_cursor}}. Un HTTP Request nommé Next Results rappelle le même endpoint avec limit=500, ce cursor et les mêmes options Response. Reliez sa réponse au même contrôle statusCode et au même point de division que la première page. La branche false termine la pagination. Avec une limite de 500, 1 250 lignes demandent trois appels.
N'inventez pas un numéro de page et ne confondez pas total avec la taille de la première réponse. Suivez exactement le cursor renvoyé. Écrivez chaque page avant de charger la suivante pour garder un point de reprise clair.
5. Mapper Google Sheets ou le CRM
Dans la branche de données, Split Out transforme body.results en éléments. Edit Fields garde ensuite un schéma explicite :
| Champ BasedOnB | Champ cible |
|---|---|
place_id | external_id |
title | company_name |
category | category |
address | address |
phone | phone |
website | website |
rating | google_rating |
reviews_count | google_review_count |
Utilisez place_id pour contrôler les doublons. Dans un CRM, préférez un upsert à une création aveugle. Dans Google Sheets, cherchez cette clé, puis mettez à jour ou ajoutez la ligne. Un simple append dupliquera les entreprises si une exécution n8n est rejouée.
Utilisez des upserts et conservez l'identifiant de tâche ainsi que le cursor de chaque page. La branche de contrôle à un seul élément peut charger la suite pendant que la branche de données écrit. Si l'ordre strict est nécessaire, bloquez le contrôle avec un unique signal page terminée provenant de la destination. Ne placez jamais l'IF de page suivante après Split Out, sinon le même cursor sera appelé pour chaque résultat.
Après l'import, la grille de qualité des listes aide à vérifier les champs, les doublons, la fraîcheur et la provenance. Pour une analyse par assistant, le guide de génération de leads avec l'IA sépare le travail du modèle de celui de la source de données.
Erreurs courantes
Comme Never Error est activé, chaque nœud HTTP doit d'abord router $json.statusCode. Pour une réponse hors 2xx, inspectez $json.body.error.code et $json.body.error.details; le corps reste disponible dans cette branche d'erreur volontaire.
401 Unauthorized : clé absente, incorrecte ou révoquée. Vérifiez le credential n8n sans écrire le secret dans les logs.
403 Forbidden : la clé existe mais n'a pas le bon droit. Utilisez les droits minimaux de lecture et d'écriture des tâches.
402 Payment Required : les crédits, l'abonnement ou le paiement demandent une action. Arrêtez la branche et informez le propriétaire du compte.
409 Conflict : la clé d'idempotence a servi avec un autre corps. Comparez la clé et le corps enregistrés. Réutilisez cette clé seulement après avoir restauré le corps d'origine. Pour une nouvelle tâche volontaire, créez une nouvelle clé stable.
429 Too Many Requests : inspectez $json.body.error.details.reason. too_many_open_scrapes demande d'attendre la fin de l'une des 2 tâches ouvertes. open_leads_limit demande d'attendre ou de réduire la nouvelle cible pour que le total ouvert reste au plus à 5 000. Si reason manque, traitez la réponse comme une limite de fréquence et utilisez l'en-tête Retry-After ou $json.body.error.details.retry_after_seconds dans un Wait borné.
Résultats vides : contrôlez l'état. Tant que la tâche est active, l'endpoint de résultats peut renvoyer une page vide.
Le guide d'automatisation avec Zapier et Make présente d'autres flux événementiels. L'identité stable, les états finaux et l'écriture sans doublon restent les mêmes.
Polling ou webhook ?
Le polling est facile à construire et à lire. Il convient aux tâches isolées et aux plannings peu fréquents. Il produit toutefois des appels de statut répétés et oblige l'exécution à suivre ses tentatives.
Le webhook convient mieux aux tâches fréquentes ou de durée variable. n8n reçoit l'événement de fin, vérifie sa signature et lance alors la pagination. Les erreurs, les cursors et les upserts restent nécessaires. Seule la détection de fin change.
Commencez par un polling borné si cela aide l'équipe à comprendre les états. Passez au webhook quand les contrôles répétés deviennent du bruit opérationnel.
FAQ
n8n peut-il collecter automatiquement des leads Google Maps ?
Oui. n8n peut appeler l'API REST de BasedOnB, lancer une recherche d'entreprises, attendre sa fin, récupérer toutes les pages de résultats et envoyer les lignes vers Google Sheets ou un CRM. Gardez la clé API dans un credential n8n et non dans un champ du workflow.
Quels nœuds n8n faut-il pour ce workflow ?
Utilisez un déclencheur, Edit Fields, HTTP Request, Wait, IF ou Switch, Merge, Split Out et le nœud de destination. Merge conserve le compteur de polling avec la réponse d'état. Split Out reste dans la branche de données afin que le contrôle de pagination garde un seul élément.
Pourquoi envoyer un Idempotency-Key ?
Il sécurise une nouvelle tentative du POST. La même clé avec la même requête renvoie la tâche d'origine au lieu d'en créer une autre. Utilisez un identifiant de campagne ou d'événement enregistré, jamais l'heure actuelle.
À quelle fréquence n8n doit-il vérifier l'état de la tâche ?
Placez un nœud Wait entre les contrôles et fixez un nombre maximal de tentatives. Un intervalle de 10 à 20 secondes est un point de départ pratique, pas une promesse de délai. À la limite, arrêtez la boucle et prévenez un responsable.
Comment récupérer plus de 500 résultats ?
Demandez au plus 500 lignes, puis lisez body.page.has_more et body.page.next_cursor dans la réponse HTTP complète. Gardez la pagination dans une branche de contrôle à un seul élément et continuez jusqu'à ce que has_more soit false.
Faut-il choisir le polling ou un webhook dans n8n ?
Le polling est plus simple pour un premier workflow et des tâches occasionnelles. Un webhook signé convient mieux aux traitements fréquents ou longs, car n8n attend l'événement de fin. Dans les deux cas, les résultats restent paginés par cursor.
Que faire si la tâche est failed ou cancelled ?
Traitez failed et cancelled comme des états finaux. Ne demandez pas les résultats et ne renvoyez pas cette branche vers Wait. Enregistrez l'identifiant et l'état, prévenez le responsable, puis décidez séparément s'il faut lancer une nouvelle tâche.
Commencer par une petite tâche récupérable
Choisissez une catégorie, une ville et une table que vous pouvez contrôler. Un nouveau compte BasedOnB reçoit une fois 50 crédits d'export sans carte bancaire. Utilisez-les pour vérifier le mapping, l'idempotence, la branche d'erreur et l'upsert avant d'augmenter le volume.
Conservez l'identifiant de tâche avec chaque ligne importée. Cette petite information de provenance simplifie fortement les contrôles et les reprises.