- COURS ANIMÉ
- MSB · UTC
- PDF AUSSI SUR MOODLE
Avant de brancher, comprendre
Trois actes pour poser le décor : le problème qu'on veut régler, les quatre outils qui vont travailler ensemble, et les quatre mots qu'on va utiliser tout l'atelier.
La boutique WooCommerce
Amira Ben Salah
Cuisine · 1 250 TND
Le commercial
Qui a commandé ?| N° | Client | Montant | |
|---|---|---|---|
| 1046 | Youssef T. | youssef@… | 480 |
| 1047 | Youssef T. | youssef@… | 480 |
| 1048 | Amira B. | amira@gmal.com | 1 250 |
| 1049 | ? | ? | ? |
WooCommerce
Elle enregistre chaque vente : qui, quoi, combien.
ta boutique WordPressn8n
Il récupère l'information et la livre au bon endroit, sans jamais se tromper d'adresse.
n8n.wescaleup.techHubSpot
Il se souvient de qui a acheté quoi, et quand. Le commercial y travaille.
le CRMGA4
Il sait d'où viennent les ventes, mais ne connaît aucun nom.
déjà branché hierWebhook
= la sonnetteWorkflow
= la recetteToujours les mêmes étapes, dans le même ordre, à chaque commande.
Clé de service
= le badge d'accèsTest / Production
= répétition et spectacleMaintenant, suivons la commande d'Amira dans les deux tuyaux
Une commande, deux tuyaux
Quand Amira passe commande sur la boutique, deux outils doivent être informés. GA4 doit savoir ce qui s'est passé. Le CRM doit savoir qui l'a fait. On ne les nourrit pas par le même chemin, et c'est tout le sujet de cet atelier.
2 produits, 1 250 TND
paiement à la livraison
montant, produits
aucun nom
→ balise GA4
quoi et combien
toute la commande
le contact par email
+ transaction associée
Ce que chaque outil reçoit
Même commande, deux fiches très différentes. GA4 reçoit l'achat sans la personne. Le CRM reçoit la personne et son achat.
GA4 : l'événement purchase
- transaction_id1048
- value1250
- currencyTND
- itemsMitigeur Inox, Hotte 60 cm
- nom, email, téléphoneinterdit
HubSpot : contact + transaction
- ClientAmira Ben Salah
- Email, téléphoneamira@… / 22 ••• •••
- TransactionCommande 1048
- Produits1 x Mitigeur Inox, 1 x Hotte 60 cm
- Montant, étape1 250 TND, commande reçue
Pourquoi pas tout par le dataLayer ?
C'est la première idée qui vient : mettre le nom et l'email dans le dataLayer, et laisser GTM les envoyer au CRM. Regarde ce qui se passe.
email : amira@…
tél : 22 ••• •••
aux données perso
aussi
Données exposées
Le dataLayer est lisible par toutes les balises de la page. Et Google interdit d'envoyer des données personnelles à GA4.
Commandes perdues
Bloqueur de pub, page merci fermée trop vite, connexion coupée : le navigateur n'est pas un tuyau fiable pour le CRM.
Pas de mise à jour
Une commande annulée ou remboursée ne repasse jamais par la page merci. Seul le serveur connaît le vrai statut.
Ce qu'il faut faire
Neuf étapes : deux pour le tuyau GA4, sept pour le tuyau HubSpot. Fais-les dans l'ordre et teste chaque tuyau séparément.
WordPress → GTM → GA4
L'achat part vers GA4, sans aucune donnée personnelle.
Pousser purchase dans le dataLayer
- Code Snippets › + Ajouter un snippet › Ajouter votre code personnalisé, type Extrait PHP, nommé « dataLayer purchase ».
- Colle ce code, choisis l'insertion Exécuter partout, active le snippet et enregistre.Extrait PHP (WPCode)
add_action( 'woocommerce_thankyou', 'sl_datalayer_purchase', 20 ); function sl_datalayer_purchase( $order_id ) { if ( ! $order_id ) return; $order = wc_get_order( $order_id ); // Une seule fois par commande : pas de doublon si la page merci est rechargée if ( ! $order || $order->get_meta( '_sl_dl_purchase_sent' ) ) return; $items = array(); foreach ( $order->get_items() as $item ) { $product = $item->get_product(); $items[] = array( 'item_id' => $product ? ( $product->get_sku() ?: (string) $product->get_id() ) : '', 'item_name' => $item->get_name(), 'price' => (float) $order->get_item_total( $item, false ), 'quantity' => (int) $item->get_quantity(), ); } $data = array( 'event' => 'purchase', 'ecommerce' => array( 'transaction_id' => (string) $order->get_order_number(), 'value' => (float) $order->get_total(), 'tax' => (float) $order->get_total_tax(), 'shipping' => (float) $order->get_shipping_total(), 'currency' => $order->get_currency(), 'items' => $items, ), ); $order->update_meta_data( '_sl_dl_purchase_sent', 'yes' ); $order->save(); echo '<script>window.dataLayer = window.dataLayer || [];' . 'window.dataLayer.push({ ecommerce: null });' . 'window.dataLayer.push(' . wp_json_encode( $data ) . ');</script>'; }Remarque : aucun nom, email ni téléphone dans ce code. Le
{ ecommerce: null }vide l'objet e-commerce précédent, comme recommandé par Google.
Créer la balise GA4 purchase
- Déclencheurs › NouveauDéclencheurÉvénement - purchaseType de déclencheurÉvénement personnaliséNom de l'événementpurchase
- Variables › Nouvelle › Variable de couche de données, nommée DLV - transaction_id, nom de la variable
ecommerce.transaction_id. Elle sert à vérifier en mode Aperçu. - Balises › Nouvelle › Google Analytics › Événement GA4BaliseGA4 - purchaseID de mesureG-XXXXXXXXXXNom de l'événementpurchasePlus de paramètres › E-commercecocher « Envoyer des données d'e-commerce », source : Couche de donnéesDéclenchementÉvénement - purchase
Pourquoi cette case : elle demande à GTM de reprendre automatiquement tout l'objet
ecommercedu dataLayer (transaction_id, value, currency, items). Pas besoin de créer une variable par paramètre.
WooCommerce → n8n → HubSpot
Le parcours ci-dessous a été réalisé et testé de bout en bout. Les captures sont celles du vrai test.
Créer la clé de service HubSpot
C'est la clé qui autorise n8n à écrire dans ton HubSpot. Sur les comptes HubSpot récents, les « applications privées » n'existent plus : on utilise une clé de service.
- Crée un compte gratuit sur hubspot.com si ce n'est pas déjà fait, puis clique sur la roue dentée ⚙️ en haut à droite.
- Dans le menu de gauche, ouvre Intégrations › Clés de service.

Le menu Intégrations : Clés de service, Applications privées, Applications héritées. Ne passe pas par « Applications privées » ni « Applications héritées » : sur un compte neuf, HubSpot affiche « Les applications héritées ne sont pas disponibles sur ce compte ».

Le message qu'on obtient en passant par les applications héritées. - Clique sur Créer une clé de service, en haut à droite.

Développement › Clés › Clés de service. - Champ Nom :
n8n atelier. Puis clique sur + Ajoutez un nouveau champ d'application. - Recherche
contactet coche crm.objects.contacts.read et crm.objects.contacts.write. Efface, recherchedealset coche crm.objects.deals.read et crm.objects.deals.write. Clique sur Mettre à jour.
Ne coche pas les lignes avec un triangle ⚠️ (données sensibles) ni les lignes schemas.
Le résultat attendu : exactement 4 domaines sélectionnés. - Clique sur Créer (bouton blanc en haut à droite), puis sur Copier à côté de la clé. Elle commence par
pat-eu1-. Garde-la dans un bloc-notes.
La clé est créée. Elle a été floutée ici : c'est un mot de passe, ne la partage jamais.
Importer le workflow dans n8n
Inutile de construire le workflow à la main : il est fourni prêt à l'emploi sous forme de texte JSON.
- Clique sur Copier sur le bloc ci-dessous.Workflow n8n (JSON)
{ "name": "Atelier - Commande WooCommerce vers HubSpot", "nodes": [ { "parameters": { "httpMethod": "POST", "path": "woocommerce-commande-nom-prenom", "options": {} }, "name": "Webhook - commande", "type": "n8n-nodes-base.webhook", "typeVersion": 2, "position": [0, 0], "webhookId": "7f3c2a10-5b8e-4d6a-9c41-2e7b1f0a8d55" }, { "parameters": { "assignments": { "assignments": [ { "id": "f1", "name": "email", "value": "={{ $json.body.billing.email }}", "type": "string" }, { "id": "f2", "name": "prenom", "value": "={{ $json.body.billing.first_name }}", "type": "string" }, { "id": "f3", "name": "nom", "value": "={{ $json.body.billing.last_name }}", "type": "string" }, { "id": "f4", "name": "telephone", "value": "={{ $json.body.billing.phone }}", "type": "string" }, { "id": "f5", "name": "numero", "value": "={{ $json.body.number }}", "type": "string" }, { "id": "f6", "name": "montant", "value": "={{ Number($json.body.total) }}", "type": "number" }, { "id": "f7", "name": "produits", "value": "={{ $json.body.line_items.map(i => i.quantity + ' x ' + i.name).join(', ') }}", "type": "string" } ] }, "options": {} }, "name": "Préparer", "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [240, 0] }, { "parameters": { "authentication": "appToken", "resource": "contact", "operation": "upsert", "email": "={{ $json.email }}", "additionalFields": { "firstName": "={{ $json.prenom }}", "lastName": "={{ $json.nom }}", "phoneNumber": "={{ $json.telephone }}" }, "options": {} }, "name": "HubSpot - Contact", "type": "n8n-nodes-base.hubspot", "typeVersion": 2, "position": [480, 0] }, { "parameters": { "authentication": "appToken", "resource": "deal", "operation": "create", "stage": "appointmentscheduled", "additionalFields": { "dealName": "=Commande {{ $('Préparer').item.json.numero }}", "amount": "={{ $('Préparer').item.json.montant }}", "description": "={{ $('Préparer').item.json.produits }}", "associatedVids": "={{ $json.vid }}" } }, "name": "HubSpot - Deal", "type": "n8n-nodes-base.hubspot", "typeVersion": 2, "position": [720, 0] } ], "connections": { "Webhook - commande": { "main": [[{ "node": "Préparer", "type": "main", "index": 0 }]] }, "Préparer": { "main": [[{ "node": "HubSpot - Contact", "type": "main", "index": 0 }]] }, "HubSpot - Contact": { "main": [[{ "node": "HubSpot - Deal", "type": "main", "index": 0 }]] } }, "settings": {} } - Dans n8n, crée un nouveau workflow, clique sur la zone vide du canevas et fais Ctrl+V (Cmd+V sur Mac). Les 4 nœuds apparaissent, déjà reliés.

Les triangles rouges sont normaux : il manque encore la connexion à HubSpot (étape 5). - Obligatoire : personnalise l'adresse de ton webhook. Double-clique sur Webhook - commande. Dans le champ Path, remplace
woocommerce-commande-nom-prenompar ton nom et ton prénom, par exemplewoocommerce-commande-bensalah-amira. Enregistre avec Cmd+S (Ctrl+S sur Windows).Pourquoi : toute la classe utilise le même serveur n8n. Si deux étudiants gardent le même chemin, leurs commandes se mélangent et n8n refuse de publier le second workflow. Règles d'écriture : minuscules, sans accents, sans espaces, avec des tirets entre les mots.
| Nœud | Ce qu'il fait |
|---|---|
| Webhook - commande | La boîte aux lettres : reçoit la commande envoyée par WooCommerce. |
| Préparer | Le tri : garde 7 informations utiles (email, prénom, nom, téléphone, numéro, montant, produits) et leur donne des noms simples. |
| HubSpot - Contact | Cherche le client par son email : le met à jour s'il existe, le crée sinon. Jamais de doublon. |
| HubSpot - Deal | Crée la transaction « Commande n° … » avec le montant et les produits, et l'accroche au contact. |
Connecter n8n à HubSpot
- Double-clique sur HubSpot - Contact, puis clique sur Connect to HubSpot Service Key.

Les champs Email, First Name, Last Name et Phone Number sont déjà remplis par l'import. - Colle ta clé
pat-eu1-…dans Service Key, laisse « Allowed HTTP Request Domains » sur All, et clique sur Save.
Le credential « HubSpot Service Key account ». - Ouvre HubSpot - Deal. Le credential est déjà sélectionné, mais le champ Deal Stage Name or ID est en rouge.

L'étape par défaut du fichier n'existe pas dans ton pipeline HubSpot. - Clique sur la flèche ⌄ du champ et choisis la première étape de ton pipeline. Si la liste s'affiche, c'est la preuve que la clé de service fonctionne.

Les étapes changent d'un compte à l'autre. Ici, on a pris « Réunion d'introduction ». - Ferme le panneau et enregistre le workflow (Cmd+S). Les triangles rouges ont disparu.
Ne clique pas sur « Execute step » dans un nœud HubSpot : n8n essaierait d'exécuter le Webhook, qui attendrait une commande. Si le bouton tourne, arrête-le avec le petit carré ⬜.
Copier l'URL de test du Webhook
- Double-clique sur Webhook - commande. Reste sur l'onglet Test URL et clique sur l'adresse pour la copier. Elle doit se terminer par ton nom et prénom, par exemple
https://n8n.wescaleup.tech/webhook-test/woocommerce-commande-bensalah-amira. La capture montre l'adresse du formateur.
L'adresse de test contient /webhook-test/. On passera à la Production URL à l'étape 9.
Créer le crochet web dans WooCommerce
Dans la version française de WooCommerce, les webhooks s'appellent Crochets Web.
- Va dans WooCommerce › Réglages › Avancé › Crochets Web et clique sur Créer un nouveau crochet web.

Onglet Avancé, lien Crochets Web. - Remplis le formulaire :Crochet webCommande vers n8nNomCommande vers n8nÉtatActiveSujetCommande crééeURL de livraisonta Test URL copiée à l'étape 6 (elle finit par ton nom-prénom)Secretne touche pasVersion de l'APIIntégration WP API REST v3

Vérifie que l'URL se termine bien par woocommerce-commande-ton-nom-ton-prenom, sans espace. - Clique sur Enregistrer le crochet web.

L'erreur 404 est normale : WooCommerce envoie un test, mais n8n n'écoute pas encore. Le crochet web est bien créé. (Secret flouté.)
Tester avec une vraie commande
n8n n'écoute que pendant 2 minutes environ, et WooCommerce n'envoie pas le crochet web immédiatement. La méthode qui marche à coup sûr : préparer 3 onglets avant de lancer quoi que ce soit.
Le workflow, sur le canevas.
Un produit dans le panier, page Checkout remplie, sans valider. En navigation privée.
WooCommerce › État › Actions planifiées
- Onglet 1 : clique sur Execute workflow, en bas du canevas. Le Webhook attend.

« Waiting for you to call the Test URL ». - Onglet 2 : valide la commande. Note son numéro.

La commande n° 1389 de notre test (email flouté). - Onglet 3 : actualise, tape
webhookdans la recherche et clique sur Rechercher…. Sur la lignewoocommerce_deliver_webhook_asyncEn attente, survole le nom et clique sur Exécuter.
Les actions planifiées : c'est ici que WooCommerce met ses envois en file d'attente. - Onglet 1 : les 4 nœuds passent au vert, avec « 1 item » entre chacun.

La commande a traversé tout le workflow. - Dans HubSpot : Contacts, ouvre la fiche du client. Le panneau Transactions, à droite, affiche la commande.

« Commande 1389 », 6,00 $US, associée au contact (données personnelles floutées).
Pourquoi tester en navigation privée : si tu es connecté à WordPress, la commande est pré-remplie avec le nom de ton compte administrateur. Dans notre test, elle est arrivée au nom du compte WordPress connecté, pas au nom saisi.
Passer en production
Jusqu'ici, le workflow ne marche que si tu cliques sur « Execute workflow ». En production, il traite chaque commande tout seul.
- Dans Webhook - commande, clique sur l'onglet Production URL et copie l'adresse :
/webhook/au lieu de/webhook-test/, toujours avec ton nom-prénom à la fin.
La Production URL. - Enregistre, puis clique sur Publish en haut à droite du canevas (sur les anciennes versions de n8n : l'interrupteur Inactive → Active).

La pastille verte « Published » : le workflow écoute en permanence. - Dans WooCommerce, ouvre ton crochet web, remplace l'URL de livraison par la Production URL et clique sur Enregistrer le crochet web. Plus d'erreur 404.

« Mis à jour le… » et l'URL sans « -test ». - Passe une nouvelle commande sans toucher à n8n, attends environ une minute, puis ouvre l'onglet Executions du workflow : une exécution réussie apparaît.
Bonus : renomme les étapes du pipeline HubSpot pour l'e-commerce (par exemple « Commande reçue », « En préparation », « Livrée », « Annulée ») dans ⚙️ › Objets › Transactions › Pipelines. HubSpot garde les mêmes identifiants internes, donc le workflow continue de fonctionner. Le montant s'affiche en USD si la boutique et HubSpot sont réglés en dollars : tu peux passer en TND dans les réglages de HubSpot.
Pannes rencontrées et solutions
Toutes ces situations sont arrivées pendant le test réel. Si tu bloques, la réponse est presque sûrement ici.
n8n refuse de publier : conflit de webhook (« conflict » ou « already registered »)
Ma commande arrive chez un autre étudiant, ou celle d'un autre arrive chez moi
woocommerce-commande-nom-prenom, et le crochet web WooCommerce doit pointer exactement vers cette adresse.« Les applications héritées ne sont pas disponibles sur ce compte »
Le champ « Deal Stage Name or ID » est en rouge
deals.WooCommerce affiche « L'url de livraison a renvoyé le code : 404 »
/webhook/ et non /webhook-test/.n8n reste sur « Waiting for you to call the Test URL », puis s'arrête
webhook, puis Exécuter). Si l'écoute de n8n a expiré entre-temps, la commande est perdue pour le test : recommence avec la méthode des 3 onglets.Le bouton « Execute step » tourne sans fin dans un nœud
Le contact arrive avec un autre nom que celui saisi
En production, rien n'arrive dans « Executions »
Avant de partir
Coche chaque point. Les deux tuyaux doivent fonctionner.
ET APRÈS ?
Ici, tu as envoyé une commande vers GA4 et vers HubSpot.
Dans la formation 90h, tu construis toute la chaîne sur un vrai projet : tracking, CRM et automatisations n8n.