AutomationFlowsEmail & Gmail › Prospection Sénégal - Email + Whatsapp/jour

Prospection Sénégal - Email + Whatsapp/jour

Prospection Sénégal - Email + WhatsApp/jour. Uses httpRequest, gmail, googleSheets. Scheduled trigger; 20 nodes.

Cron / scheduled trigger★★★★☆ complexity20 nodesHTTP RequestGmailGoogle Sheets
Email & Gmail Trigger: Cron / scheduled Nodes: 20 Complexity: ★★★★☆ Added:

This workflow follows the Gmail → 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
{
  "name": "Prospection S\u00e9n\u00e9gal - Email + WhatsApp/jour",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "50 10 * * 1-5"
            }
          ]
        }
      },
      "id": "node-schedule-1",
      "name": "D\u00e9clencheur 10h50",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        200
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 13 * * 1-5"
            }
          ]
        }
      },
      "id": "node-schedule-2",
      "name": "D\u00e9clencheur 13h00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        340
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 16 * * 1-5"
            }
          ]
        }
      },
      "id": "node-schedule-3",
      "name": "D\u00e9clencheur 16h00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        480
      ]
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 19 * * 1-5"
            }
          ]
        }
      },
      "id": "node-schedule-4",
      "name": "D\u00e9clencheur 19h00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        240,
        620
      ]
    },
    {
      "parameters": {
        "jsCode": "const villes = ['Dakar', 'Thi\u00e8s', 'Saint-Louis', 'Ziguinchor', 'Kaolack', 'Mbour', 'Touba', 'Diourbel', 'Rufisque', 'Pikine'];\nconst categories = [\n  { query: 'restaurant', label: 'Restaurant' },\n  { query: 'agence immobili\u00e8re', label: 'Agence Immobili\u00e8re' },\n  { query: 'salon de coiffure', label: 'Salon de Coiffure' },\n  { query: 'pharmacie', label: 'Pharmacie' },\n  { query: 'boutique v\u00eatements', label: 'Boutique V\u00eatements' },\n  { query: 'h\u00f4tel', label: 'H\u00f4tel' },\n  { query: 'cabinet m\u00e9dical', label: 'Cabinet M\u00e9dical' },\n  { query: 'boulangerie', label: 'Boulangerie' },\n  { query: 'garage m\u00e9canique', label: 'Garage' },\n  { query: '\u00e9cole formation', label: '\u00c9cole/Formation' }\n];\n\nconst shuffle = arr => [...arr].sort(() => Math.random() - 0.5);\nconst villesJour = shuffle(villes).slice(0, 3);\nconst catsJour = shuffle(categories).slice(0, 5);\n\nconst searches = [];\nfor (const ville of villesJour) {\n  for (const cat of catsJour) {\n    searches.push({\n      searchQuery: `${cat.query} ${ville} S\u00e9n\u00e9gal email contact`,\n      placesQuery: `${cat.query} ${ville}`,\n      category: cat.label,\n      ville: ville\n    });\n  }\n}\n\nreturn searches.map(s => ({ json: s }));\n"
      },
      "id": "node-search-gen",
      "name": "G\u00e9n\u00e9rer recherches du jour",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        500,
        400
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://google.serper.dev/search",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-KEY",
              "value": "c47c6843516c558ecb85949cf568143216bfd11d"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"q\": {{ JSON.stringify($json.searchQuery) }},\n  \"gl\": \"sn\",\n  \"hl\": \"fr\",\n  \"num\": 10\n}",
        "options": {}
      },
      "id": "node-serper-search",
      "name": "Serper - Search (emails)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        740,
        280
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://google.serper.dev/places",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-KEY",
              "value": "c47c6843516c558ecb85949cf568143216bfd11d"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"q\": {{ JSON.stringify($json.placesQuery) }},\n  \"gl\": \"sn\",\n  \"hl\": \"fr\"\n}",
        "options": {}
      },
      "id": "node-serper-places",
      "name": "Serper - Places (t\u00e9l\u00e9phones)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        740,
        520
      ]
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\nconst emailRegex = /[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}/g;\nconst phoneRegex = /(?:\\+221|00221|0)?[7][0-9]{8}/g;\nconst results = [];\nconst emailsSeen = new Set();\nconst phonesSeen = new Set();\n\nfor (const item of items) {\n  const data = item.json;\n  const category = data.category || '';\n  const ville = data.ville || '';\n  const organicResults = data.organic || [];\n  const knowledgeGraph = data.knowledgeGraph || {};\n\n  for (const result of organicResults) {\n    const textToSearch = [\n      result.snippet || '',\n      result.title || '',\n      result.link || '',\n      JSON.stringify(result.sitelinks || '')\n    ].join(' ');\n\n    const nomCommerce = result.title\n      ? result.title.split(' - ')[0].split(' | ')[0].trim()\n      : 'Votre \u00e9tablissement';\n\n    const emails = textToSearch.match(emailRegex) || [];\n    for (const email of emails) {\n      if (emailsSeen.has(email)) continue;\n      if (email.includes('example.') || email.includes('test@') || email.includes('@sentry') || email.includes('@google') || email.includes('@facebook') || email.includes('@instagram') || email.includes('@wix') || email.includes('@wordpress')) continue;\n      if (email.endsWith('.png') || email.endsWith('.jpg') || email.endsWith('.gif')) continue;\n      emailsSeen.add(email);\n      results.push({\n        json: {\n          nom: nomCommerce, email, telephone: '',\n          canal: 'email', ville, categorie: category,\n          source: result.link || '', snippet: result.snippet || ''\n        }\n      });\n    }\n\n    const phones = textToSearch.match(phoneRegex) || [];\n    for (let phone of phones) {\n      phone = phone.replace(/[^0-9]/g, '');\n      if (phone.startsWith('00221')) phone = phone.slice(5);\n      else if (phone.startsWith('221')) phone = phone.slice(3);\n      else if (phone.startsWith('0')) phone = phone.slice(1);\n      const fullPhone = '221' + phone;\n      if (phonesSeen.has(fullPhone)) continue;\n      if (fullPhone.length !== 12) continue;\n      phonesSeen.add(fullPhone);\n      results.push({\n        json: {\n          nom: nomCommerce, email: '', telephone: fullPhone,\n          canal: 'whatsapp', ville, categorie: category,\n          source: result.link || '', snippet: result.snippet || ''\n        }\n      });\n    }\n  }\n\n  const kgText = JSON.stringify(knowledgeGraph);\n  const kgEmails = kgText.match(emailRegex) || [];\n  for (const email of kgEmails) {\n    if (!emailsSeen.has(email) && !email.includes('@google') && !email.includes('@facebook')) {\n      emailsSeen.add(email);\n      results.push({\n        json: {\n          nom: knowledgeGraph.title || '\u00c9tablissement', email, telephone: '', canal: 'email',\n          ville, categorie: category,\n          source: knowledgeGraph.website || '', snippet: knowledgeGraph.description || ''\n        }\n      });\n    }\n  }\n}\n\nreturn results.slice(0, 150);\n"
      },
      "id": "node-extract-search",
      "name": "Extraire emails (Search)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        980,
        280
      ]
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\nconst results = [];\nconst phonesSeen = new Set();\n\nfor (const item of items) {\n  const data = item.json;\n  const category = data.category || '';\n  const ville = data.ville || '';\n  const places = data.places || [];\n\n  for (const place of places) {\n    let phone = place.phoneNumber || '';\n    if (!phone) continue;\n\n    phone = phone.replace(/[^0-9]/g, '');\n    if (phone.startsWith('00221')) phone = phone.slice(5);\n    else if (phone.startsWith('221')) phone = phone.slice(3);\n    else if (phone.startsWith('0')) phone = phone.slice(1);\n    const fullPhone = '221' + phone;\n\n    if (phonesSeen.has(fullPhone)) continue;\n    if (fullPhone.length !== 12) continue;\n    if (!fullPhone.startsWith('2217')) continue;\n    phonesSeen.add(fullPhone);\n\n    results.push({\n      json: {\n        nom: place.title || '\u00c9tablissement',\n        email: '',\n        telephone: fullPhone,\n        canal: 'whatsapp',\n        ville,\n        categorie: category,\n        source: place.website || '',\n        snippet: place.address || '',\n        googleMaps: place.cid ? `https://maps.google.com/?cid=${place.cid}` : ''\n      }\n    });\n  }\n}\n\nreturn results.slice(0, 150);\n"
      },
      "id": "node-extract-places",
      "name": "Extraire t\u00e9l\u00e9phones (Places)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        980,
        520
      ]
    },
    {
      "parameters": {
        "jsCode": "const searchContacts = $('Extraire emails (Search)').all();\nconst placesContacts = $('Extraire t\u00e9l\u00e9phones (Places)').all();\n\nconst allContacts = [...searchContacts, ...placesContacts];\n\nconst emailsSeen = new Set();\nconst phonesSeen = new Set();\nconst merged = [];\n\nfor (const item of allContacts) {\n  const d = item.json;\n  if (d.canal === 'email') {\n    if (emailsSeen.has(d.email)) continue;\n    emailsSeen.add(d.email);\n    merged.push(item);\n  } else if (d.canal === 'whatsapp') {\n    if (phonesSeen.has(d.telephone)) continue;\n    phonesSeen.add(d.telephone);\n    merged.push(item);\n  }\n}\n\nreturn merged.slice(0, 150);\n"
      },
      "id": "node-merge",
      "name": "Fusionner contacts",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        400
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "is-email",
              "leftValue": "={{ $json.canal }}",
              "rightValue": "email",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "node-if-canal",
      "name": "Email ou WhatsApp ?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1420,
        400
      ]
    },
    {
      "parameters": {
        "jsCode": "const details = {\n  'Restaurant': { avantages: 'menu digital interactif, r\u00e9servations en ligne, galerie photos des plats, commandes \u00e0 emporter', exemple: 'BMF Restaurant', lien: 'https://bmf-6fa.pages.dev' },\n  'Salon de Coiffure': { avantages: 'prise de RDV en ligne 24h/24, galerie avant/apr\u00e8s, pr\u00e9sentation de l\\'\u00e9quipe, tarifs en ligne', exemple: 'Minka Haircut', lien: 'https://minka-haircut.pages.dev' },\n  'Agence Immobili\u00e8re': { avantages: 'catalogue de propri\u00e9t\u00e9s avec photos, formulaires de contact, estimation en ligne, cr\u00e9dibilit\u00e9 professionnelle', exemple: 'BMF Restaurant', lien: 'https://bmf-6fa.pages.dev' },\n  'Pharmacie': { avantages: 'catalogue produits, horaires et localisation, conseils sant\u00e9, contact rapide', exemple: 'Minka Haircut', lien: 'https://minka-haircut.pages.dev' },\n  'Boutique V\u00eatements': { avantages: 'boutique e-commerce, catalogue avec photos, paiement en ligne, livraison', exemple: 'BMF Restaurant', lien: 'https://bmf-6fa.pages.dev' },\n  'H\u00f4tel': { avantages: 'r\u00e9servation directe sans commission, galerie des chambres, offres sp\u00e9ciales, avis clients', exemple: 'BMF Restaurant', lien: 'https://bmf-6fa.pages.dev' },\n  'Cabinet M\u00e9dical': { avantages: 'prise de RDV en ligne, pr\u00e9sentation des m\u00e9decins, sp\u00e9cialit\u00e9s, localisation pr\u00e9cise', exemple: 'Minka Haircut', lien: 'https://minka-haircut.pages.dev' },\n  'Boulangerie': { avantages: 'menu et prix en ligne, commandes de g\u00e2teaux, horaires, promotions du jour', exemple: 'BMF Restaurant', lien: 'https://bmf-6fa.pages.dev' },\n  'Garage': { avantages: 'liste des services, devis en ligne, galerie des r\u00e9alisations, contact rapide', exemple: 'Minka Haircut', lien: 'https://minka-haircut.pages.dev' },\n  '\u00c9cole/Formation': { avantages: 'catalogue des formations, inscription en ligne, t\u00e9moignages, placement', exemple: 'BMF Restaurant', lien: 'https://bmf-6fa.pages.dev' },\n  'default': { avantages: 'pr\u00e9sence professionnelle en ligne, formulaire de contact, pr\u00e9sentation de vos services', exemple: 'BMF Restaurant', lien: 'https://bmf-6fa.pages.dev' }\n};\n\nconst sujets = {\n  'Restaurant': 'Boostez vos r\u00e9servations avec un site web professionnel',\n  'Agence Immobili\u00e8re': 'Multipliez vos mandats immobiliers en ligne',\n  'Salon de Coiffure': 'Prise de RDV en ligne 24h/24 pour votre salon',\n  'Pharmacie': 'Digitalisez votre pharmacie et gagnez en visibilit\u00e9',\n  'Boutique V\u00eatements': 'Vendez vos collections sur internet',\n  'H\u00f4tel': 'Augmentez vos r\u00e9servations sans commission',\n  'Cabinet M\u00e9dical': 'Facilitez la prise de RDV de vos patients',\n  'Boulangerie': 'Commandes en ligne et plus de visibilit\u00e9',\n  'Garage': 'Attirez plus de clients avec un site professionnel',\n  '\u00c9cole/Formation': 'Inscriptions en ligne et plus d\\'\u00e9tudiants',\n  'default': 'D\u00e9veloppez votre activit\u00e9 avec un site web professionnel'\n};\n\nconst accroches = [\n  'J\\'ai remarqu\u00e9 que',\n  'En cherchant des services \u00e0',\n  'Je me permets de contacter',\n  'En tant que d\u00e9veloppeur web s\u00e9n\u00e9galais, j\\'ai d\u00e9couvert',\n  'En visitant votre \u00e9tablissement en ligne,'\n];\nconst transitions = [\n  'Aujourd\\'hui, la majorit\u00e9 de vos clients potentiels cherchent en ligne avant de se d\u00e9placer.',\n  'De nos jours, une pr\u00e9sence en ligne est indispensable pour attirer de nouveaux clients.',\n  'Sans site web, vous passez \u00e0 c\u00f4t\u00e9 de nombreux clients qui cherchent vos services sur Google.',\n  'La plupart des S\u00e9n\u00e9galais consultent internet avant de choisir un prestataire ou un commerce.'\n];\nconst conclusions = [\n  'Je serais ravi d\\'\u00e9changer avec vous 15 minutes gratuitement pour vous montrer ce que je peux faire pour vous.',\n  'Je vous offre une consultation gratuite de 15 min pour discuter de votre projet sans engagement.',\n  'N\\'h\u00e9sitez pas \u00e0 me r\u00e9pondre ou \u00e0 m\\'appeler pour une consultation gratuite de 15 minutes.'\n];\n\nconst rand = arr => arr[Math.floor(Math.random() * arr.length)];\n\nconst results = [];\nfor (const inputItem of $input.all()) {\n  const item = inputItem.json;\n  const d = details[item.categorie] || details['default'];\n  const sujetBase = sujets[item.categorie] || sujets['default'];\n  const sujet = `${item.nom} - ${sujetBase}`;\n\n  const emailBody = `Bonjour,\n\n${rand(accroches)} ${item.nom} \u00e0 ${item.ville}, je souhaite vous proposer mes services en d\u00e9veloppement web.\n\n${rand(transitions)}\n\nUn site web professionnel pour ${item.nom} vous permettrait d'avoir ${d.avantages}. Cela vous aiderait \u00e0 attirer de nouveaux clients, \u00e0 renforcer votre cr\u00e9dibilit\u00e9 et \u00e0 vous d\u00e9marquer de la concurrence.\n\nJ'ai d\u00e9j\u00e0 r\u00e9alis\u00e9 des projets similaires au S\u00e9n\u00e9gal, comme ${d.exemple} : ${d.lien}\nVous pouvez \u00e9galement consulter mon portfolio complet : https://porfolio-idy.pages.dev\n\nJe propose des sites professionnels livr\u00e9s en 7 jours, \u00e0 des tarifs adapt\u00e9s au march\u00e9 s\u00e9n\u00e9galais.\n\n${rand(conclusions)}\n\nCordialement,\nIdrissa Kane\nD\u00e9veloppeur Web Full-Stack\n\ud83d\udce7 idykane03@gmail.com\n\ud83d\udcf1 +221 78 119 48 05\n\ud83c\udf10 https://porfolio-idy.pages.dev`;\n\n  results.push({ json: { ...item, emailBody, sujet, dateEnvoi: new Date().toISOString() } });\n}\nreturn results;\n"
      },
      "id": "node-gen-email",
      "name": "G\u00e9n\u00e9rer email (local)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1640,
        260
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": false,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "conditions": [
            {
              "id": "valid-email",
              "leftValue": "={{ $json.email }}",
              "rightValue": "^[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}$",
              "operator": {
                "type": "string",
                "operation": "regex"
              }
            }
          ],
          "combinator": "and"
        }
      },
      "id": "node-validate-email",
      "name": "Valider email",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1860,
        260
      ]
    },
    {
      "parameters": {
        "amount": 90,
        "unit": "seconds"
      },
      "id": "node-wait-email",
      "name": "Pause 90s avant email",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        2080,
        200
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $json.email }}",
        "subject": "={{ $json.sujet }}",
        "message": "={{ $json.emailBody }}",
        "options": {
          "senderName": "Idrissa Kane - D\u00e9veloppeur Web"
        }
      },
      "id": "node-gmail",
      "name": "Gmail - Envoyer email",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        2300,
        200
      ],
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "1WEExNRPftqCDQFzj3AAytKFf-JTCUTGHzDf-Sq1Wgew",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "id"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Date": "={{ $json.dateEnvoi }}",
            "Nom": "={{ $json.nom }}",
            "Categorie": "={{ $json.categorie }}",
            "Ville": "={{ $json.ville }}",
            "Telephone": "=N/A",
            "Email": "={{ $json.email }}",
            "Sujet": "={{ $json.sujet }}",
            "Statut": "=Email Envoy\u00e9 \u2705",
            "Site actuel": "={{ $json.source }}",
            "Google Maps": "=N/A"
          }
        },
        "options": {
          "useAppend": true
        }
      },
      "id": "node-sheets-email",
      "name": "Sheets - Logger email",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        2520,
        200
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const details = {\n  'Restaurant': { avantages: '\ud83d\udccb Menu digital\\n\ud83d\udcc5 R\u00e9servations en ligne\\n\ud83d\udcf8 Galerie de vos plats\\n\ud83d\udef5 Commandes \u00e0 emporter', exemple: 'https://bmf-6fa.pages.dev' },\n  'Salon de Coiffure': { avantages: '\ud83d\udcc5 RDV en ligne 24h/24\\n\ud83d\udcf8 Galerie avant/apr\u00e8s\\n\ud83d\udc65 Pr\u00e9sentation de l\\'\u00e9quipe\\n\ud83d\udcb0 Tarifs en ligne', exemple: 'https://minka-haircut.pages.dev' },\n  'Agence Immobili\u00e8re': { avantages: '\ud83c\udfe0 Catalogue de propri\u00e9t\u00e9s\\n\ud83d\udcdd Formulaires de contact\\n\ud83d\udcb0 Estimation en ligne\\n\u2b50 Cr\u00e9dibilit\u00e9 pro', exemple: 'https://bmf-6fa.pages.dev' },\n  'Pharmacie': { avantages: '\ud83d\udc8a Catalogue produits\\n\ud83d\udd50 Horaires en ligne\\n\ud83d\udccd Localisation\\n\ud83d\udcde Contact rapide', exemple: 'https://minka-haircut.pages.dev' },\n  'Boutique V\u00eatements': { avantages: '\ud83d\udecd\ufe0f Boutique en ligne\\n\ud83d\udcf8 Catalogue avec photos\\n\ud83d\udcb3 Commandes en ligne\\n\ud83d\ude9a Livraison', exemple: 'https://bmf-6fa.pages.dev' },\n  'H\u00f4tel': { avantages: '\ud83d\udecf\ufe0f R\u00e9servation directe\\n\ud83d\udcf8 Galerie des chambres\\n\ud83d\udcb0 Tarifs clairs\\n\u2b50 Avis clients', exemple: 'https://bmf-6fa.pages.dev' },\n  'Cabinet M\u00e9dical': { avantages: '\ud83d\udcc5 RDV en ligne\\n\ud83d\udc68\u200d\u2695\ufe0f Pr\u00e9sentation m\u00e9decins\\n\ud83c\udfe5 Sp\u00e9cialit\u00e9s\\n\ud83d\udccd Localisation', exemple: 'https://minka-haircut.pages.dev' },\n  'Boulangerie': { avantages: '\ud83e\udd56 Menu et prix en ligne\\n\ud83c\udf82 Commandes de g\u00e2teaux\\n\ud83d\udd50 Horaires\\n\ud83c\udf81 Promotions', exemple: 'https://bmf-6fa.pages.dev' },\n  'Garage': { avantages: '\ud83d\udd27 Liste des services\\n\ud83d\udcb0 Devis en ligne\\n\ud83d\udcf8 Galerie r\u00e9alisations\\n\ud83d\udcde Contact rapide', exemple: 'https://minka-haircut.pages.dev' },\n  '\u00c9cole/Formation': { avantages: '\ud83d\udcda Catalogue formations\\n\ud83d\udcdd Inscriptions en ligne\\n\u2b50 T\u00e9moignages\\n\ud83c\udf93 Placement', exemple: 'https://bmf-6fa.pages.dev' },\n  'default': { avantages: '\ud83c\udf10 Visibilit\u00e9 sur Google\\n\ud83d\udcde Contact facile\\n\u2b50 Cr\u00e9dibilit\u00e9 pro\\n\ud83d\udcc8 Plus de clients', exemple: 'https://bmf-6fa.pages.dev' }\n};\n\nconst accroches = [\n  'j\\'ai vu que vous n\\'aviez pas encore de site web',\n  'votre \u00e9tablissement m\u00e9rite une belle pr\u00e9sence en ligne',\n  'beaucoup de clients cherchent vos services sur Google sans vous trouver',\n  'un site web pourrait vraiment booster votre activit\u00e9'\n];\n\nconst rand = arr => arr[Math.floor(Math.random() * arr.length)];\n\nconst results = [];\nfor (const inputItem of $input.all()) {\n  const item = inputItem.json;\n  const d = details[item.categorie] || details['default'];\n\n  const waMessage = `Bonjour \ud83d\udc4b\n\nJe suis Idrissa Kane, d\u00e9veloppeur web au S\u00e9n\u00e9gal. En cherchant ${item.categorie.toLowerCase()} \u00e0 ${item.ville}, ${rand(accroches)} pour *${item.nom}*.\n\nUn site web vous permettrait d'avoir :\n${d.avantages}\n\nJ'ai d\u00e9j\u00e0 r\u00e9alis\u00e9 des projets similaires :\n\ud83d\udd17 ${d.exemple}\n\ud83d\udd17 https://porfolio-idy.pages.dev\n\nSite livr\u00e9 en 7 jours \u26a1 Tarifs adapt\u00e9s au S\u00e9n\u00e9gal \ud83c\uddf8\ud83c\uddf3\n\nJe vous offre une consultation gratuite de 15 min \ud83c\udf81\n\n- Idrissa Kane, D\u00e9veloppeur Web \ud83c\udf10\n\ud83d\udcf1 +221 78 119 48 05`;\n\n  results.push({ json: { ...item, waMessage, dateEnvoi: new Date().toISOString() } });\n}\nreturn results;\n"
      },
      "id": "node-gen-wa",
      "name": "G\u00e9n\u00e9rer message WA (local)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1640,
        540
      ]
    },
    {
      "parameters": {
        "amount": 90,
        "unit": "seconds"
      },
      "id": "node-wait-wa",
      "name": "Pause 90s avant WhatsApp",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1860,
        540
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.fonnte.com/send",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Vyd7qsXoYe2vhzPwTvdA"
            }
          ]
        },
        "sendBody": true,
        "contentType": "form-urlencoded",
        "bodyParameters": {
          "parameters": [
            {
              "name": "target",
              "value": "={{ $json.telephone }}"
            },
            {
              "name": "message",
              "value": "={{ $json.waMessage }}"
            },
            {
              "name": "countryCode",
              "value": "221"
            }
          ]
        },
        "options": {}
      },
      "id": "node-fonnte",
      "name": "Fonnte - Envoyer WhatsApp",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        2080,
        540
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "1WEExNRPftqCDQFzj3AAytKFf-JTCUTGHzDf-Sq1Wgew",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "id"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Date": "={{ $json.dateEnvoi }}",
            "Nom": "={{ $json.nom }}",
            "Categorie": "={{ $json.categorie }}",
            "Ville": "={{ $json.ville }}",
            "Telephone": "={{ $json.telephone }}",
            "Email": "=N/A",
            "Sujet": "=Message WhatsApp",
            "Statut": "=WhatsApp Envoy\u00e9 \u2705",
            "Site actuel": "={{ $json.source }}",
            "Google Maps": "={{ $json.googleMaps || 'N/A' }}"
          }
        },
        "options": {}
      },
      "id": "node-sheets-wa",
      "name": "Sheets - Logger WhatsApp",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        2300,
        540
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "D\u00e9clencheur 10h50": {
      "main": [
        [
          {
            "node": "G\u00e9n\u00e9rer recherches du jour",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "D\u00e9clencheur 13h00": {
      "main": [
        [
          {
            "node": "G\u00e9n\u00e9rer recherches du jour",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "D\u00e9clencheur 16h00": {
      "main": [
        [
          {
            "node": "G\u00e9n\u00e9rer recherches du jour",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "D\u00e9clencheur 19h00": {
      "main": [
        [
          {
            "node": "G\u00e9n\u00e9rer recherches du jour",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "G\u00e9n\u00e9rer recherches du jour": {
      "main": [
        [
          {
            "node": "Serper - Search (emails)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Serper - Places (t\u00e9l\u00e9phones)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Serper - Search (emails)": {
      "main": [
        [
          {
            "node": "Extraire emails (Search)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Serper - Places (t\u00e9l\u00e9phones)": {
      "main": [
        [
          {
            "node": "Extraire t\u00e9l\u00e9phones (Places)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extraire emails (Search)": {
      "main": [
        [
          {
            "node": "Fusionner contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extraire t\u00e9l\u00e9phones (Places)": {
      "main": [
        [
          {
            "node": "Fusionner contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fusionner contacts": {
      "main": [
        [
          {
            "node": "Email ou WhatsApp ?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email ou WhatsApp ?": {
      "main": [
        [
          {
            "node": "G\u00e9n\u00e9rer email (local)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "G\u00e9n\u00e9rer message WA (local)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "G\u00e9n\u00e9rer email (local)": {
      "main": [
        [
          {
            "node": "Valider email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Valider email": {
      "main": [
        [
          {
            "node": "Pause 90s avant email",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Pause 90s avant email": {
      "main": [
        [
          {
            "node": "Gmail - Envoyer email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - Envoyer email": {
      "main": [
        [
          {
            "node": "Sheets - Logger email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "G\u00e9n\u00e9rer message WA (local)": {
      "main": [
        [
          {
            "node": "Pause 90s avant WhatsApp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pause 90s avant WhatsApp": {
      "main": [
        [
          {
            "node": "Fonnte - Envoyer WhatsApp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fonnte - Envoyer WhatsApp": {
      "main": [
        [
          {
            "node": "Sheets - Logger WhatsApp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "staticData": null,
  "tags": [
    {
      "name": "prospection"
    },
    {
      "name": "senegal"
    }
  ],
  "triggerCount": 4,
  "updatedAt": "2026-06-01T00:00:00.000Z",
  "versionId": "5"
}

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

Prospection Sénégal - Email + WhatsApp/jour. Uses httpRequest, gmail, googleSheets. Scheduled trigger; 20 nodes.

Source: https://github.com/idy-00/prospect-site-senegal-n8n/blob/b692ad08f1698396e4976b92d5fa6440cc39f565/workflow/prospection-senegal.json — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Email & Gmail

This workflow is a powerful, two-phase system designed to automate the entire passive candidate sourcing and engagement cycle.

HTTP Request, Google Sheets, Gmail
Email & Gmail

Every weekday morning, the workflow reads your prospect list from Google Sheets and cross-checks it against a send log — anyone already emailed is automatically skipped Each new contact is assigned on

Google Sheets, Gmail
Email & Gmail

How It Works Starts with a Manual Trigger Reads lead list from Google Sheet Filter rows where email wasn’t sent Generate personalized email body (AI) Generate email subject line (AI) Merge AI outputs

Google Sheets, HTTP Request, Gmail
Email & Gmail

YOUR_ID 4. Uses gmail, googleDrive, googleSheets, httpRequest. Scheduled trigger; 53 nodes.

Gmail, Google Drive, Google Sheets +1
Email & Gmail

Automatically extract structured information from emails using AI-powered document analysis. This workflow processes emails from specified domains, classifies them by type, and extracts structured dat

Gmail, HTTP Request, AWS S3 +1