A/B test WhatsApp — deux messages, un gagnant — le workflow n8n – AutomationBoost
Workflow n8n · gratuit

A/B test WhatsApp : deux messages, un gagnant

16 nœuds · import en 2 minutes · Google Sheets + Evolution API

Tu envoies le même message WhatsApp à toute ta base, et personne ne répond. Le problème n'est pas le canal : c'est que tu n'as aucun moyen de savoir quelle formulation marche.

Ce workflow coupe ta liste en deux, envoie deux messages différents en même temps, et écrit dans ta feuille de calcul qui a reçu quoi et qui a cliqué. Seize nœuds. Il tourne sur n8n, y compris l'offre gratuite.

Avant tout le reste

Envoyer des messages WhatsApp à des gens qui ne te l'ont pas demandé, c'est le meilleur moyen de te faire bannir ton numéro — et selon l'endroit où tu es, ce n'est pas seulement une question de plateforme. Utilise ce workflow sur une base qui a accepté d'être contactée. Le Wait 3s entre deux envois et la limite à 20 destinataires par exécution sont là pour la même raison : ils ralentissent volontairement.

Ce qu'il fait, nœud par nœud

Ce ne sont pas des étapes idéales : c'est le contenu réel du fichier que tu vas copier plus bas.

  1. Démarrer — un déclencheur manuel. Tu lances toi-même chaque vague, tu ne subis pas une programmation.
  2. Lire Google Sheet — il lit ta feuille de contacts.
  3. Filtre Leads avec Tel — deux conditions cumulées : la colonne Telephone n'est pas vide, et la colonne Message_Envoye ne vaut pas true. C'est ça qui t'empêche de recontacter deux fois la même personne.
  4. Limit 20 — vingt destinataires au maximum par exécution.
  5. Logique A/B + Format Tel — un nœud de code qui fait deux choses. Il attribue le groupe A aux dix premiers et B aux dix suivants. Puis il nettoie le numéro : suppression des espaces, retrait du +, conversion du 0262 en 262, et ajout de l'indicatif quand le numéro commence par un simple 0.
  6. Switch A/B — deux sorties nommées Groupe A et Groupe B. Rien ne sort si le groupe est absent.
  7. WhatsApp Groupe A et WhatsApp Groupe B — deux appels POST vers ton instance Evolution API, avec ta clé en en-tête. Chacun porte sa propre version du message.
  8. Wait 3s — trois secondes entre deux envois, sur chaque branche.
  9. Set Statut — prépare les valeurs à réécrire : Message_Envoye = true, la date du jour, et la variante A ou B.
  10. Update Sheet — réécrit ces trois colonnes sur la bonne ligne, en se calant sur row_number.
  11. Webhook Tracking Clic — une branche séparée, avec son propre webhook. Quand quelqu'un ouvre le lien qu'on lui a envoyé, il passe par là.
  12. Marquer Clic dans Sheet — écrit A_Clique = true et la date du clic sur la ligne correspondante.

L'indicatif : le détail qui casse tout

C'est le piège classique et il vaut le détour, parce qu'il ne produit aucune erreur visible — l'API accepte le numéro, et le message n'arrive nulle part.

Une feuille de contacts remplie à la main contient toujours quatre écritures du même numéro : avec des espaces, avec un +, avec un 0 devant, ou déjà à l'international. Le nœud de code les ramène toutes à la même forme avant l'envoi. L'indicatif utilisé ici est 262, celui de La Réunion : si tu es ailleurs, c'est la seule ligne à changer.

Les deux versions du message

Ce qui change entre A et B n'est pas cosmétique : c'est l'angle d'entrée. La version A se présente et pose une question sur la situation. La version B entre par le métier et pose une question sur une douleur précise. Les deux finissent sur le même lien, avec un paramètre variant différent — c'est ce paramètre qui permet, plus tard, de savoir laquelle a fait cliquer.

Version AVersion B
Se présente, dit à qui il s'adresse, puis demande : « Vous gérez tout ça manuellement en ce moment ? » Entre directement par le secteur et le gain de temps, puis demande : « Vous avez déjà eu des no-shows qui auraient pu être évités ? »
Question ouverte, sur l'organisation. Question fermée, sur un incident déjà vécu.

Les deux textes complets sont dans le fichier, tu les remplaces par les tiens.

Ce que le workflow ne fait pas

Autant le dire tout de suite, parce que c'est ce qu'on croit en le lisant vite.

  • Il ne désigne pas le gagnant. Aucun nœud ne compare A et B pour basculer ensuite sur le meilleur. Il collecte la matière — variante envoyée, clic, dates — et c'est toi qui lis la feuille et qui tranches.
  • Il ne compte pas les réponses. Ce qui est mesuré, c'est le clic sur le lien, via la branche de tracking. Une personne qui te répond sans cliquer n'apparaît nulle part.
  • Il ne s'auto-déclenche pas. Le déclencheur est manuel, par choix.

Le premier point est le plus important : ce workflow est un instrument de mesure, pas un pilote automatique. C'est aussi ce qui le rend utilisable dès aujourd'hui — un test A/B qui bascule tout seul avant d'avoir assez de données prend de mauvaises décisions plus vite.

Comment l'installer

  1. Copie le bloc ci-dessous avec le bouton.
  2. Dans n8n : Workflows → Import from clipboard → colle → Import.
  3. Ouvre les nœuds Google Sheets et remplace VOTRE_GOOGLE_SHEET_ID par l'identifiant de ta feuille, puis choisis tes accès Google. Le fichier n'en contient aucun — c'est voulu.
  4. Dans les deux nœuds WhatsApp, remplace TON-INSTANCE-EVOLUTION-API par l'adresse de ton instance et TA_CLE_EVOLUTION_API par ta clé.
  5. Ta feuille doit contenir ces colonnes, écrites exactement comme ça : Telephone, Message_Envoye, Date_Envoi, Variante, A_Clique, Date_Clic.
  6. Réécris les deux messages. Ceux du fichier sont des exemples — envoyés tels quels, ils ne parleront pas de ton métier.
Le seul piège

Si la colonne Message_Envoye n'existe pas dans ta feuille, le filtre laisse passer tout le monde à chaque exécution — et tu renvoies le même message aux mêmes personnes. Crée la colonne avant le premier envoi, pas après.

Le workflow, en entier

[WHATSAPP] A/B test WhatsApp — deux messages, un gagnant
{
  "name": "[WHATSAPP] A/B test WhatsApp — deux messages, un gagnant",
  "nodes": [
    {
      "id": "c1db45d3-9131-49dd-9eb1-135ba56f5f43",
      "name": "Démarrer",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        -2032,
        656
      ],
      "parameters": {}
    },
    {
      "id": "15e4d6ff-b1b8-4bf2-984e-bb161f77dba5",
      "name": "Lire Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        -1824,
        656
      ],
      "parameters": {
        "documentId": {
          "__rl": true,
          "value": "VOTRE_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Feuille 1",
          "mode": "name"
        },
        "options": {}
      }
    },
    {
      "id": "21b151c8-7f7e-49db-88f8-476e30e43b3b",
      "name": "Filtre Leads avec Tel",
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.2,
      "position": [
        -1632,
        656
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "tel_check",
              "leftValue": "={{ $json.Telephone }}",
              "operator": {
                "operation": "notEmpty",
                "type": "string"
              }
            },
            {
              "id": "envoye_check",
              "leftValue": "={{ $json.Message_Envoye }}",
              "rightValue": "true",
              "operator": {
                "operation": "notEquals",
                "type": "string"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "8922f824-473e-4772-b6cf-d93d1c41aab3",
      "name": "Limit 20",
      "type": "n8n-nodes-base.limit",
      "typeVersion": 1,
      "position": [
        -1424,
        656
      ],
      "parameters": {
        "maxItems": 20
      }
    },
    {
      "id": "093002a9-d64a-4ba1-a731-fc053498c588",
      "name": "Logique A/B + Format Tel",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1232,
        656
      ],
      "parameters": {
        "jsCode": "const leads = $input.all();\n\nreturn leads.map((item, index) => {\n  // Groupe A premiers 10, Groupe B suivants 10\n  item.json.ab_group = (index < 10) ? 'A' : 'B';\n  \n  // Nettoyage numéro : supprimer espaces, +, 0 initial, gérer +262 et 0262\n  let tel = item.json.Telephone || '';\n  tel = tel.replace(/\\s+/g, '');\n  \n  // Si commence par +262, enlever le +\n  if (tel.startsWith('+')) tel = tel.substring(1);\n  \n  // Si commence par 0262, remplacer par 262\n  if (tel.startsWith('0262')) tel = '262' + tel.substring(4);\n  \n  // Si commence par 0 seul (numéro local), ajouter 262\n  else if (tel.startsWith('0') && !tel.startsWith('262')) {\n    tel = '262' + tel.substring(1);\n  }\n  \n  item.json.Tel_Formate = tel;\n  item.json.row_index = index;\n  return item;\n});"
      }
    },
    {
      "id": "1b647bcc-1503-46f2-b00c-5b584aa0bec6",
      "name": "Switch A/B",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        -1024,
        656
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.ab_group }}",
                    "rightValue": "A",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Groupe A"
            },
            {
              "conditions": {
                "conditions": [
                  {
                    "leftValue": "={{ $json.ab_group }}",
                    "rightValue": "B",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "renameOutput": true,
              "outputKey": "Groupe B"
            }
          ]
        },
        "options": {
          "fallbackOutput": "none"
        }
      }
    },
    {
      "id": "858d45aa-e431-4eec-81d6-8b7bb6efac8b",
      "name": "WhatsApp Groupe A",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        -784,
        528
      ],
      "parameters": {
        "method": "POST",
        "url": "https://TON-INSTANCE-EVOLUTION-API/message/sendText/TON-INSTANCE",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "TA_CLE_EVOLUTION_API"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"number\": \"{{ $json.Tel_Formate }}\",\n  \"text\": \"Bonjour 👋 Je suis Tony, je travaille avec des restaurants à La Réunion pour automatiser les tâches qui font perdre du temps (réservations, relances clients, avis Google…).\\n\\nVous gérez tout ça manuellement en ce moment ?\\n\\nJe vous ai préparé une démo personnalisée : {{ $json.deploymentUrl || 'https://TA-PAGE-DEMO.exemple.com' }}\\n\\nFormulaire de contact : https://TON-N8N/form/ton-formulaire?id={{ $json.row_number }}&variant=A\"\n}",
        "options": {}
      }
    },
    {
      "id": "48ee02d1-9281-464e-aa2d-5e0c287da1d9",
      "name": "WhatsApp Groupe B",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        -784,
        800
      ],
      "parameters": {
        "method": "POST",
        "url": "https://TON-INSTANCE-EVOLUTION-API/message/sendText/TON-INSTANCE",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apikey",
              "value": "TA_CLE_EVOLUTION_API"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"number\": \"{{ $json.Tel_Formate }}\",\n  \"text\": \"Hello ! 🍴 Spécial restaurant : j'aide les restos réunionnais à gagner 5-10h/semaine sur les réservations, avis Google et suivi clients.\\n\\nVous avez déjà eu des no-shows qui auraient pu être évités ?\\n\\nDémo ici : {{ $json.deploymentUrl || 'https://TA-PAGE-DEMO.exemple.com' }}\\n\\nContactez-moi : https://TON-N8N/form/ton-formulaire?id={{ $json.row_number }}&variant=B\"\n}",
        "options": {}
      }
    },
    {
      "id": "8ce201f2-68d8-44d5-86f5-3c515353f873",
      "name": "Wait 3s A",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        -560,
        528
      ],
      "parameters": {
        "amount": 3
      }
    },
    {
      "id": "fd805f74-10fa-4b74-86b4-c1910000adad",
      "name": "Wait 3s B",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        -560,
        800
      ],
      "parameters": {
        "amount": 3
      }
    },
    {
      "id": "25c3981e-ffc3-4d80-8384-e0bb7f4c6654",
      "name": "Set Statut A",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -352,
        528
      ],
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "Message_Envoye",
              "value": "true",
              "type": "string"
            },
            {
              "name": "Date_Envoi",
              "value": "={{ new Date().toISOString().slice(0,10) }}",
              "type": "string"
            },
            {
              "name": "Variante",
              "value": "A",
              "type": "string"
            },
            {
              "name": "Telephone",
              "value": "={{ $('Logique A/B + Format Tel').item.json.Telephone }}",
              "type": "string"
            },
            {
              "name": "row_number",
              "value": "={{ $('Logique A/B + Format Tel').item.json.row_number }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "8ca06f42-6b1d-4617-8714-0abebeb76c3c",
      "name": "Set Statut B",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -352,
        800
      ],
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "name": "Message_Envoye",
              "value": "true",
              "type": "string"
            },
            {
              "name": "Date_Envoi",
              "value": "={{ new Date().toISOString().slice(0,10) }}",
              "type": "string"
            },
            {
              "name": "Variante",
              "value": "B",
              "type": "string"
            },
            {
              "name": "Telephone",
              "value": "={{ $('Logique A/B + Format Tel').item.json.Telephone }}",
              "type": "string"
            },
            {
              "name": "row_number",
              "value": "={{ $('Logique A/B + Format Tel').item.json.row_number }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "2c657d78-de87-4bc2-9afa-ea96d1d319f6",
      "name": "Update Sheet A",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        -128,
        528
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "VOTRE_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Feuille 1",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Message_Envoye": "={{ $json.Message_Envoye }}",
            "Date_Envoi": "={{ $json.Date_Envoi }}",
            "Variante": "={{ $json.Variante }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": [
            {
              "id": "row_number",
              "displayName": "row_number",
              "canBeUsedToMatch": true,
              "required": false,
              "defaultMatch": true
            },
            {
              "id": "Message_Envoye",
              "displayName": "Message_Envoye",
              "canBeUsedToMatch": false
            },
            {
              "id": "Date_Envoi",
              "displayName": "Date_Envoi",
              "canBeUsedToMatch": false
            },
            {
              "id": "Variante",
              "displayName": "Variante",
              "canBeUsedToMatch": false
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "892aaed3-d521-4f07-90f9-b6d934dc0601",
      "name": "Update Sheet B",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        -128,
        800
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "VOTRE_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Feuille 1",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Message_Envoye": "={{ $json.Message_Envoye }}",
            "Date_Envoi": "={{ $json.Date_Envoi }}",
            "Variante": "={{ $json.Variante }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": [
            {
              "id": "row_number",
              "displayName": "row_number",
              "canBeUsedToMatch": true,
              "required": false,
              "defaultMatch": true
            },
            {
              "id": "Message_Envoye",
              "displayName": "Message_Envoye",
              "canBeUsedToMatch": false
            },
            {
              "id": "Date_Envoi",
              "displayName": "Date_Envoi",
              "canBeUsedToMatch": false
            },
            {
              "id": "Variante",
              "displayName": "Variante",
              "canBeUsedToMatch": false
            }
          ]
        },
        "options": {}
      }
    },
    {
      "id": "02e92b01-325d-43a7-a3b4-a91c346368cf",
      "name": "Webhook Tracking Clic",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        288,
        1056
      ],
      "parameters": {
        "path": "automationboost-click-tracker",
        "options": {}
      }
    },
    {
      "id": "410e3e80-73fd-4490-876c-17187bc22d86",
      "name": "Marquer Clic dans Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        528,
        1056
      ],
      "parameters": {
        "operation": "update",
        "documentId": {
          "__rl": true,
          "value": "VOTRE_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "Feuille 1",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "A_Clique": "true",
            "Date_Clic": "={{ new Date().toISOString().slice(0,10) }}"
          },
          "matchingColumns": [
            "row_number"
          ],
          "schema": [
            {
              "id": "row_number",
              "displayName": "row_number",
              "canBeUsedToMatch": true,
              "defaultMatch": true
            },
            {
              "id": "A_Clique",
              "displayName": "A_Clique",
              "canBeUsedToMatch": false
            },
            {
              "id": "Date_Clic",
              "displayName": "Date_Clic",
              "canBeUsedToMatch": false
            }
          ]
        },
        "options": {}
      }
    }
  ],
  "connections": {
    "Démarrer": {
      "main": [
        [
          {
            "node": "Lire Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lire Google Sheet": {
      "main": [
        [
          {
            "node": "Filtre Leads avec Tel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filtre Leads avec Tel": {
      "main": [
        [
          {
            "node": "Limit 20",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Limit 20": {
      "main": [
        [
          {
            "node": "Logique A/B + Format Tel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Logique A/B + Format Tel": {
      "main": [
        [
          {
            "node": "Switch A/B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch A/B": {
      "main": [
        [
          {
            "node": "WhatsApp Groupe A",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "WhatsApp Groupe B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WhatsApp Groupe A": {
      "main": [
        [
          {
            "node": "Wait 3s A",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WhatsApp Groupe B": {
      "main": [
        [
          {
            "node": "Wait 3s B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3s A": {
      "main": [
        [
          {
            "node": "Set Statut A",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3s B": {
      "main": [
        [
          {
            "node": "Set Statut B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Statut A": {
      "main": [
        [
          {
            "node": "Update Sheet A",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Statut B": {
      "main": [
        [
          {
            "node": "Update Sheet B",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Tracking Clic": {
      "main": [
        [
          {
            "node": "Marquer Clic dans Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}

WHATSAPP | TONY PAYET / AUTOMATION BOOST | 2026

← Toutes les ressources