Airtable + n8n : Agent IA commercial qui génère & enrichit des leads (tuto)

Promesse. Voici comment j’ai branché Airtable et n8n pour construire un agent commercial qui : génère des prospects ciblés via Google (Serper), raffine l’ICP, puis enrichit les profils LinkedIn (Apify).
Airtable = colonne vertébrale (données, états, gouvernance).
n8n = exécution (webhooks, API, logique).
1) Vue d’ensemble
[ Airtable / Campaigns ] [ Airtable / ScrapeLeads ]
(paramètres de campagne) (résultats leads)
│ ▲
(Automation #1/#2 → Script) │
▼ │ (n8n crée/enrichit)
[ n8n / Webhook /ai-sales ] → Switch(query.action) ───┘
├─ A: startScraping → Serper → Create records
├─ B: ScrapeICP → construit la requête ICP
└─ C: scrapeLinkedin → Apify enrichissement
2) Prérequis
- Deux tables Airtable :
Campaigns
: JobTitle, Industry, CompanySize, CompanyType, Location, LeadNumber, Query, Action…ScrapeLeads
: Title, LinkedinURL, Subtitle/Snippet, Campaign (link), Status…
n8n (cloud ou self-host) + clés Serper (Google) et Apify.
Lien vers la BD: clique ici
Le fichier .JSON à importer dans N8N:
3) Webhook n8n & routage
Dans n8n, crée un Webhook (méthode GET). En production tu utiliseras : https://…/webhook/ai-sales
. Juste après, un Switch lit {{$json.query.action}}
et route vers :
- startScraping : recherche Google & création des leads
- ScrapeICP : requête ICP plus précise
- scrapeLinkedin : enrichissement des profils (Apify)
4) Automatisation Airtable #1 : déclencher startScraping
Déclencheur : “Quand l’enregistrement correspond aux conditions” (ex. Action = "ScrapeLeads"
ou une case Start?). Action : Exécuter un script avec 2 Saisies : recordId = Enregistrement → Airtable record ID (jeton bleu rec…
) et action = startScraping
.
Script (version production ; en test, utiliser /webhook-test/
après “Execute Workflow” dans n8n) :
<!-- Script Airtable : envoi GET vers n8n avec recordId + action -->
<pre><code>
const { recordId, action } = input.config();
if (!recordId || !action) throw new Error('recordId/action manquants');
const BASE_URL = 'https://…/webhook/ai-sales'; // en test: /webhook-test/ (juste après "Execute Workflow")
const qs = new URLSearchParams({
recordId,
action, // "startScraping"
source: 'airtable',
sentAt: new Date().toISOString(),
});
const url = ${BASE_URL}?${qs.toString()};
5) Branche A : générer des leads via Google (Serper)
5.1 Récupérer la campagne
Nœud n8n Airtable → Get a record (table Campaigns
, recordId depuis query.recordId
). Tu récupères JobTitle, Industry, Location, etc.
5.2 Construire la requête (Edit Fields)
site:linkedin.com/in ("CEO" OR "Founder") (Agency) (Morocco) (Communication)
-inurl:dir -inurl:company -inurl:jobs -intitle:profiles
5.3 Appeler Serper (HTTP Request)
- POST →
https://google.serper.dev/search
- Headers :
X-API-KEY: <ta_clé>
etContent-Type: application/json
Body JSON :
{
"q": "{{$json[\"Query\"]}}",
"gl": "ma",
"hl": "fr",
"num": 10
}
5.4 Créer les leads
Parse items.organic[]
puis Create record dans ScrapeLeads
: Title
, LinkedinURL
, Subtitle/Snippet
, lien vers Campaign
. À la fin, pour enchaîner automatiquement, mets Action = "ScrapeICP" dans la campagne (nœud Update record).
6) Automatisation Airtable #2 : déclencher ScrapeICP
Déclencheur : “Quand Action = "ScrapeICP"
”. Action : Exécuter un script avec recordId (ID de l’enregistrement) et action = ScrapeICP
.
<pre><code>
const { recordId, action } = input.config();
if (!recordId || !action) throw new Error('recordId/action manquants');
const BASE_URL = 'https://…/webhook/ai-sales';
const qs = new URLSearchParams({ recordId, action, source: 'airtable', sentAt: new Date().toISOString() });
const url = `${BASE_URL}?${qs.toString()}`;
const res = await fetch(url, { method: 'GET' });
output.set('status', res.status);
output.set('calledUrl', url);
</code></pre>
7) Branche B : construire / raffiner l’ICP
Assembler dynamiquement la requête à partir des champs de la campagne (poste, industrie, taille, pays) pour réduire le bruit.
const f = $('Get a record1').item.json.fields;
const title = f.JobTitle || 'CEO';
const industry = f.Industry || 'SaaS';
const size = f.CompanySize || '11-50';
const location = f.Location || 'France';
Relancer Serper (même réglages) et upserter les leads dans ScrapeLeads
. En sortie, repasser la campagne en Action = "Idle" ou déclencher scrapeLinkedin
si tu veux enrichir immédiatement.
8) Branche C : enrichir les profils LinkedIn (Apify)
À partir des URLs LinkedIn, appeler un Actor Apify de profil (rate-limit, lotir, statut de traitement). Renseigner les champs enrichis dans ScrapeLeads
(headline, localisation, dernière expérience…).
9) Pourquoi Airtable est le “backbone”
- Source de vérité : tout est rattaché à une campagne.
- Pilotage : un seul champ
Action
orchestre l’ordre des branches. - Contrôle humain : vues, corrections, déduplication.
- Traçabilité : chaque lead est relié à son run.
12) Et après ?
Dans le prochain épisode, Nous ajouterons la partie Outreach pour convertir nos leads.