Génération de leads sur Google Maps : un guide pratique

Une catégorie et une liste de villes, transformées en CSV de leads filtré et enrichi. Boucle Python et coût en crédits d'une campagne sur 100 villes.

Toute liste de leads locaux commence de la même façon : une catégorie, un ensemble de villes, et un filtre qui vous dit qui vaut réellement la peine d’être appelé. Voici la version de bout en bout de ce workflow, de la requête au CSV, avec le coût en crédits calculé pour une taille de campagne réelle.

Si vous voulez la référence de l’endpoint lui-même, les paramètres, les champs de réponse, ce que coûte une seule recherche, c’est couvert dans comment scraper les résultats Google Maps avec Python. Cet article est le guide construit par-dessus : comment transformer des résultats Maps en une liste que vous remettriez à un commercial.

Étape 1 : définir l’ICP avant d’écrire une requête

« Les entreprises à Austin » n’est pas un filtre. Un ICP utilisable pour de la prospection locale a besoin de trois choses fixées avant de lancer la moindre requête :

  • Catégorie. Le terme de recherche que vous associerez à chaque ville : « plombier », « dentiste », « installateur de climatisation ». Testez-le d’abord manuellement sur Maps et vérifiez qu’il ne ramène pas des catégories voisines dont vous ne voulez pas.
  • Un seuil de traction. Un nombre minimum d’avis (reviews) vous indique que l’entreprise est assez établie pour valoir le contact, pas une fiche ouverte le mois dernier.
  • Un signal de douleur. Pour une agence web, c’est un champ website manquant. Pour un pitch d’outil de réservation, ça peut être un type qui implique un travail sur rendez-vous. Le signal est ce que votre produit résout.

Tout ce qui suit consiste juste à exécuter cette définition à grande échelle.

Étape 2 : interroger catégorie et ville, avec pagination

Bouclez la catégorie sur votre liste de villes, et traitez chaque page comme une requête facturable séparée :

import requests

API_KEY = "faf_live_..."  # votre clé FastAF

def maps_search(query, page=0):
    resp = requests.get(
        "https://api.fastaf.co/v1/maps",
        params={"query": query, "page": page},
        headers={"Authorization": f"Bearer {API_KEY}"},
        timeout=60,
    )
    resp.raise_for_status()
    return resp.json().get("search_results", [])

Deux pages par ville (environ 40 établissements, puisqu’une page Maps compte environ 20 résultats) suffit généralement pour des villes de taille moyenne. Les métropoles denses peuvent en nécessiter trois ou quatre avant d’atteindre des rendements décroissants.

Étape 3 : filtrer sur les champs, pas sur le jugement

C’est ici que l’ICP de l’étape 1 devient du code. Aucune revue manuelle de la liste brute :

CATEGORY = "plumber"
CITIES = ["Austin TX", "Tampa FL", "Boise ID"]  # votre liste de 100 villes
MIN_REVIEWS = 25
MIN_RATING = 4.0
PAGES_PER_CITY = 2

leads = []
for city in CITIES:
    for page in range(PAGES_PER_CITY):
        for place in maps_search(f"{CATEGORY} in {city}", page=page):
            if place.get("reviews", 0) < MIN_REVIEWS:
                continue
            if place.get("rating", 0) < MIN_RATING:
                continue
            if place.get("website"):
                continue  # a déjà un site, ne correspond pas à l'ICP pour un pitch d'agence web
            leads.append(place)

print(f"{len(leads)} raw leads from {len(CITIES)} cities")

Inversez la logique pour un pitch différent : rating < 4.0 et reviews > 50 trouve des entreprises avec un vrai trafic et un problème de réputation, un ICP différent mais tout aussi courant.

Étape 4 : enrichir la shortlist, pas tout le lot

Ne récupérez pas à nouveau chaque établissement scrapé, seulement ceux qui ont survécu au filtre. Chaque résultat porte un place_id, que vous pouvez interroger à nouveau juste avant qu’un lead ne parte chez un commercial, pour que la fiche soit à jour plutôt que vieille de plusieurs jours comme au moment du pull initial :

def maps_lookup(place_id):
    resp = requests.get(
        "https://api.fastaf.co/v1/maps",
        params={"place_id": place_id},
        headers={"Authorization": f"Bearer {API_KEY}"},
        timeout=60,
    )
    resp.raise_for_status()
    results = resp.json().get("search_results", [])
    return results[0] if results else {}

enriched = [maps_lookup(lead["place_id"]) if lead.get("place_id") else lead for lead in leads]

C’est aussi l’ordre d’opérations le moins cher : filtrer d’abord signifie que vous ne payez le coût d’enrichissement que sur les leads que vous allez réellement utiliser, pas sur chaque établissement de chaque ville.

Étape 5 : exporter le CSV

import csv

with open("leads.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=["title", "phone", "address", "rating", "reviews", "type"])
    writer.writeheader()
    for lead in enriched:
        writer.writerow({k: lead.get(k, "") for k in writer.fieldnames})

Voilà un fichier que vous pouvez importer directement dans un CRM ou un outil de prospection à froid.

Combien coûte une campagne sur 100 villes ?

Une requête /maps coûte 5 crédits quelle que soit la requête. À 2 pages par ville :

Étape Requêtes Crédits
Découverte : 100 villes x 2 pages 200 1 000
Enrichissement : ~150 leads shortlistés 150 750
Total 350 1 750

Sur le pack Growth (29 $ pour 75 000 crédits), 1 750 crédits représentent environ 0,68 $ du pack. Si vous testez d’abord la catégorie et le filtre, l’offre gratuite est de 500 crédits sans carte, assez pour lancer la découverte et l’enrichissement sur 20 à 25 villes avant de décider que l’ICP est le bon. Les requêtes échouées ne sont pas facturées, les crédits sont réservés au démarrage d’une requête et rendus si rien ne revient, donc une mauvaise requête sur une ville ne vous coûte rien au-delà de l’appel gaspillé.

En bref

Verrouillez l’ICP sur une catégorie, un seuil de traction et un signal de douleur avant d’écrire du code. Interrogez large, filtrez dur, et ne dépensez des crédits d’enrichissement que sur les leads qui ont déjà passé le filtre. Un balayage complet sur 100 villes avec enrichissement reste sous les 2 000 crédits, assez petit pour que la contrainte sur une campagne comme celle-ci ne soit jamais la facture d’API, mais la qualité du filtre.