S
Retour au blogComment tracker l'origine de vos prospects de l'email au formulaire sans perdre le fil
Email Marketing & Newsletters7 août 202614 min de lecture

Comment tracker l'origine de vos prospects de l'email au formulaire sans perdre le fil

Les UTM disparaissent entre la landing page et le formulaire. Voici comment maintenir la continuité du tracking pour que chaque lead arrive avec son contexte d'origine.

Vous lancez une campagne, les clics arrivent, les formulaires se remplissent. Pourtant, au moment de qualifier les prospects, impossible de dire quelle action a déclenché quelle demande. Les paramètres UTM présents sur la page d'arrivée s'évaporent dès la seconde page visitée. Le formulaire envoie nom, email, message, mais reste muet sur le parcours qui a mené là. Résultat : votre outil d'analyse affiche une conversion, votre équipe commerciale reçoit un contact sans contexte. Pour combler ce trou noir, il faut un repère commun qui survive à la navigation, du premier clic jusqu'à l'envoi du formulaire. Ce repère, ce n'est pas l'URL. C'est une donnée stockée côté navigateur, récupérée au moment précis où le visiteur devient prospect. La solution tient en trois étapes : capturer les paramètres à l'arrivée, les conserver dans le navigateur, les injecter dans le formulaire avant l'envoi. Rien de magique, juste une discipline technique que la plupart des sites oublient d'appliquer.

Pourquoi les UTM seuls ne suffisent pas

Les paramètres UTM décrivent l'origine d'un clic. Google Analytics recommande utm_source, utm_medium, utm_campaign pour identifier la source, le canal, la campagne. Matomo propose le même principe. Ils sont utiles, indispensables même. Mais leur présence sur la page d'arrivée ne garantit pas qu'ils suivront le visiteur jusqu'au formulaire.

Prenez un parcours réel. Quelqu'un clique dans votre newsletter sur une URL balisée. Il arrive sur un article de blog. Il clique vers une page offre. Il ouvre la page contact. Il envoie le formulaire. Au moment de l'envoi, l'URL du formulaire ne contient plus les paramètres de la newsletter. Si rien ne les a conservés, la demande arrive sans source exploitable. Votre tableau de bord voit une conversion. Votre commercial voit un email anonyme. Le lien est rompu.

Google Ads ajoute une difficulté. Avec le marquage automatique, un clic publicitaire transmet un identifiant gclid dans l'URL. Cet identifiant relie le clic à la campagne. Il peut aussi intervenir dans le suivi des conversions hors ligne. Mais comme les UTM, il disparaît dès que l'internaute change de page. Pire : certains navigateurs ou extensions le suppriment dès l'arrivée. Si vous ne le capturez pas instantanément, il est perdu pour toujours.

Le point de rupture : le changement de page

Le problème technique est simple. Les paramètres de campagne vivent dans l'URL. L'URL change à chaque navigation. Le navigateur ne conserve pas l'historique des paramètres d'une page à l'autre. Chaque chargement est une page blanche pour les paramètres de l'URL courante.

Votre visiteur arrive sur monsite.com/article?utm_source=newsletter&utm_campaign=rentree. La page s'affiche. Les paramètres sont là. Il clique sur un lien interne vers monsite.com/offre. La nouvelle URL ne contient plus rien. Le serveur n'a aucune raison de les reporter. Le JavaScript de la nouvelle page ne les voit pas. Ils ont existé le temps d'un chargement, puis ils ont cessé d'exister.

C'est là que se joue tout le suivi. La majorité des sites n'ont aucun mécanisme pour faire traverser ces données d'une page à l'autre. Le formulaire, souvent sur une URL distincte, reçoit une requête propre, sans mémoire du parcours. C'est le trou noir dont parle votre source d'inspiration : deux vérités séparées, l'analyse d'un côté, le commercial de l'autre, aucune passerelle entre les deux.

La solution : stocker côté navigateur dès la première page

Puisque l'URL ne conserve pas l'information, il faut la sortir de l'URL. Le navigateur offre deux stockages persistants : les cookies et le localStorage. Les deux survivent aux changements de page. Les deux sont accessibles en JavaScript sur n'importe quelle page du même domaine. Le choix entre les deux dépend de vos contraintes techniques, mais le principe reste identique.

À l'arrivée sur la première page — celle qui reçoit le clic balisé — un script lit l'URL, extrait les paramètres qui vous intéressent (utm_source, utm_medium, utm_campaign, utm_content, utm_term, gclid, fbclid, msclkid et vos paramètres maison), puis les écrit dans le stockage choisi. À partir de cet instant, ces données voyagent avec le visiteur, page après page, sans effort supplémentaire.

Ce script doit s'exécuter le plus tôt possible, idéalement dans le <head> ou au tout début du <body>, avant tout autre JavaScript. S'il s'exécute après un clic interne, c'est trop tard : l'URL d'origine a déjà disparu. La capture doit être immédiate, sur la toute première page de la session.

Quels paramètres capturer et pourquoi

Ne capturez pas tout aveuglément. Concentrez-vous sur ce qui alimente vos décisions marketing et commerciales. La liste minimale recommandée :

  • utm_source — d'où vient le clic (newsletter, google, linkedin, partner)
  • utm_medium — le canal (email, cpc, social, referral, affiliate)
  • utm_campaign — le nom de votre campagne (rentree-2024, black-friday, webinar-sept)
  • utm_content — la variante créative (bouton-rouge, lien-texte, image-banniere)
  • utm_term — le mot-clé payant (utile pour Google Ads sans gclid)
  • gclid — l'identifiant Google Ads (marquage automatique)
  • fbclid — l'identifiant Facebook/Meta Ads
  • msclkid — l'identifiant Microsoft Ads
  • ttclid — l'identifiant TikTok Ads
  • li_fat_id — l'identifiant LinkedIn Ads

Ajoutez vos paramètres internes si vous en utilisez : ref, affiliate_id, partner_code. Chaque paramètre capturé est une dimension d'analyse future. Mais attention : le localStorage a une limite (généralement 5 Mo). Restez raisonnable. Une cinquantaine de caractères par paramètre, une douzaine de paramètres, vous êtes large.

Cookies ou localStorage : comment choisir

Les cookies sont envoyés automatiquement avec chaque requête HTTP vers votre domaine. Si votre formulaire est soumis en POST classique vers votre serveur, le serveur reçoit les cookies sans effort côté client. C'est pratique pour une architecture traditionnelle. Mais les cookies ont des inconvénients : limite de 4 Ko par domaine, transmis à chaque requête (images, CSS, JS), soumis aux politiques de consentement strictes (RGPD, ePrivacy).

Le localStorage n'est jamais envoyé au serveur automatiquement. Il reste côté navigateur. Il faut du JavaScript pour le lire et l'injecter dans le formulaire avant l'envoi. En contrepartie : 5 Mo disponibles, pas de transmission parasite, pas de gestion de domaine/chemin/expiration complexe, et surtout : il n'est pas un "cookie" au sens légal. Beaucoup de bannières de consentement ne le bloquent pas, ou le classent différemment. Vérifiez votre CMP.

Mon conseil pratique : utilisez le localStorage pour la persistance, et un cookie de session minimal (un simple identifiant de session) si votre serveur a besoin de corrélater côté backend. Le localStorage est plus robuste, plus simple à débuguer (onglet Application dans les outils développeur), et évite les fuites sur les sous-domaines non désirés.

Implémentation concrète : le script de capture

Voici la logique exacte à placer sur toutes vos pages, ou au moins sur toutes les pages d'entrée potentielles (articles, landing pages, homepage, pages produits) :

  1. Lire window.location.search
  2. Parser les paramètres avec URLSearchParams
  3. Filtrer sur votre liste blanche de paramètres autorisés
  4. Construire un objet propre
  5. Sérialiser en JSON
  6. Écrire dans localStorage.setItem('attribution_data', json)
  7. Ajouter un horodatage pour gérer l'expiration

Exemple de structure stockée :

{
  "utm_source": "newsletter",
  "utm_medium": "email",
  "utm_campaign": "rentree-2024",
  "utm_content": "cta-principal",
  "gclid": null,
  "fbclid": null,
  "captured_at": "2024-09-15T10:32:14.123Z",
  "landing_page": "https://monsite.com/article/bienvenue"
}

Notez la présence de landing_page. C'est souvent le premier indicateur d'intention. Conservez-la. L'horodatage captured_at vous permet d'expirer les données après une durée définie (30 jours, 90 jours, selon votre cycle de vente). Ne laissez pas une attribution de janvier polluer un formulaire rempli en octobre.

Gérer la priorité : ne pas écraser une attribution existante

Un visiteur clique sur une publicité Google (gclid présent), arrive sur votre site, ne convertit pas. Trois jours plus tard, il clique sur votre newsletter (UTM présents), revient, remplit le formulaire. Quelle attribution gagne ? La réponse dépend de votre modèle d'attribution. Dernier clic non-direct ? Dernier clic tout court ? Premier clic ? Linéaire ?

La méthode la plus simple et la plus honnête : dernier clic non-direct. Si le localStorage contient déjà une attribution, ne l'écrasez que si la nouvelle arrivée n'est pas du trafic direct (pas de paramètres, pas de referrer identifié). Si le visiteur tape votre URL directement ou vient d'un favori, conservez l'attribution précédente. S'il arrive avec de nouveaux paramètres de campagne, mettez à jour.

Cette règle évite d'attribuer une conversion à une visite directe qui n'est que la continuation d'une session antérieure. Elle évite aussi d'écraser une campagne payante par un clic organique ultérieur. Implémentez cette logique dans votre script de capture : lire l'existant, comparer, décider, écrire.

Injecter les données dans le formulaire

Le formulaire est le point final. Au moment de l'envoi, il doit transmettre les données d'attribution alongside les champs visibles. Deux approches : champs cachés (<input type="hidden">) ou enrichissement de la payload JavaScript (fetch/AJAX).

Pour un formulaire HTML classique qui POST vers votre backend : ajoutez des champs cachés dynamiquement au chargement de la page contact. Un script lit localStorage.getItem('attribution_data'), parse le JSON, crée un <input type="hidden" name="utm_source" value="..."> pour chaque paramètre non nul, et les insère dans le <form>. Au submit, le serveur reçoit tout dans $_POST ou request.body.

Pour un formulaire géré en JavaScript (React, Vue, Alpine, vanilla fetch) : au moment du submit, lisez le localStorage, fusionnez l'objet d'attribution avec les données du formulaire, envoyez le tout en une seule requête. C'est plus propre, invisible dans le DOM, et vous contrôlez exactement ce qui part.

Dans les deux cas, ajoutez un champ attribution_captured_at et attribution_landing_page. Votre CRM ou votre fichier Excel de leads aura enfin le contexte complet.

Cas particulier : formulaires tiers (Typeform, HubSpot, Calendly, etc.)

Si votre formulaire est hébergé chez un tiers, vous ne contrôlez pas le DOM ni le submit. La plupart de ces outils acceptent des paramètres d'URL pré-remplis. Construisez l'URL du formulaire en y ajoutant vos paramètres d'attribution récupérés du localStorage.

Exemple : votre page contact contient un lien vers https://votre.typeform.com/to/xyz. Au clic, un script intercepte, lit le localStorage, ajoute ?utm_source=...&utm_medium=...&gclid=... à l'URL, puis redirige. Typeform pré-remplit ses champs cachés, et la soumission arrive avec les données.

Pour les formulaires embarqués en iframe (HubSpot forms, Pardot, Marketo) : la plupart offrent une API JavaScript pour passer des valeurs aux champs cachés de l'iframe au chargement. Lisez la doc de votre outil. La logique reste : lecture localStorage → injection via l'API du fournisseur.

Google Ads et le gclid : attention au consentement

Le gclid est un identifiant personnel au sens RGPD. Google l'utilise pour relier le clic à la conversion. Si vous le stockez, vous traitez une donnée personnelle. Votre bannière de consentement doit le prévoir. Deux options :

  • Ne capturer le gclid qu'après consentement "publicité" ou "mesure d'audience" validé. Simple, conforme, mais vous perdez les données des non-consentants.
  • Utiliser le mode de consentement Google (Consent Mode v2). Votre bannière signale l'état de consentement à Google via gtag('consent', 'update', ...). Google adapte son comportement : sans consentement, pas de cookies publicitaires, mais le gclid peut encore transiter en URL pour la modélisation de conversion. Côté serveur, vous ne le stockez que si le consentement est donné.

La deuxième option est la plus robuste pour les annonceurs sérieux. Elle préserve la modélisation Google Ads (estimations de conversions) tout en respectant le choix de l'utilisateur. Implémentez le Consent Mode v2 via Google Tag Manager ou directement dans votre gtag. C'est devenu le standard attendu par Google.

Tester de bout en bout : le protocole de validation

Ne déployez pas sans tester. Créez un scénario de test complet pour chaque source de trafic :

  1. Générez une URL de test avec tous les paramètres (UTM + gclid factice + fbclid factice)
  2. Ouvrez en navigation privée (pour partir d'un stockage vide)
  3. Vérifiez dans l'onglet Application > Local Storage que l'objet attribution_data est bien écrit avec les bonnes valeurs
  4. Naviguez sur 3-4 pages internes (blog, offre, à propos, contact)
  5. Vérifiez que le localStorage n'a pas changé
  6. Remplissez le formulaire (vrai ou test)
  7. Vérifiez côté serveur / CRM / email reçu : les champs d'attribution sont-ils présents et corrects ?
  8. Répétez en arrivant par une URL sans paramètres (trafic direct) : l'attribution précédente doit persister
  9. Répétez en arrivant avec de nouveaux paramètres : l'attribution doit se mettre à jour (selon votre règle de priorité)

Automatisez ce test avec Playwright ou Cypress. Intégrez-le à votre CI/CD. Une régression sur l'attribution est invisible dans Google Analytics (les sessions restent trackées) mais casse votre qualification commerciale. Le test automatisé est votre filet de sécurité.

Erreurs fréquentes qui cassent la chaîne

  • Script de capture placé après le consentement cookie : si l'utilisateur refuse, le script ne s'exécute pas, l'attribution est perdue. Placez la capture avant, ou faites-la indépendamment du consentement (données non personnelles = UTM anonymes).
  • Nettoyage du localStorage trop agressif : certains scripts de "nettoyage" ou de "logout" vident tout le localStorage. Excluez votre clé attribution_data.
  • Sous-domaines séparés : blog.monsite.com et www.monsite.com n'ont pas le même localStorage. Utilisez un cookie de domaine parent (.monsite.com) ou passez les paramètres en URL lors du passage entre sous-domaines.
  • Formulaire en AJAX sans injection : le fetch part sans les champs cachés. Ajoutez l'enrichissement dans le handler de submit, pas dans le rendu initial.
  • Paramètres UTM en majuscules : UTM_SOURCE au lieu de utm_source. Normalisez en minuscules à la capture.
  • Double encodage : l'URL contient utm_source=newsletter%20septembre. Décodez avec decodeURIComponent avant stockage, sinon vous stockerez le %20.

Intégrer côté CRM et équipe commerciale

Les données arrivent maintenant dans votre CRM (HubSpot, Pipedrive, Salesforce, Airtable, Google Sheets). Ce n'est pas fini. Il faut les rendre exploitables.

Créez des champs dédiés dans votre CRM : Source originale, Médium original, Campagne originale, Contenu original, Terme original, GCLID, FBCLID, Page d'atterrissage, Date capture attribution. Mappez les champs cachés du formulaire vers ces champs CRM. Automatisez via webhook, Zapier, Make, ou l'API native.

Ensuite, formez vos commerciaux. Un lead avec utm_source=google / utm_medium=cpc / utm_campaign=marque-concurrente n'a pas la même conversation qu'un lead utm_source=newsletter / utm_medium=email / utm_campaign=client-fidelite. Le premier découvre votre marque en cherchant un concurrent. Le second vous connaît déjà. Le script de vente, l'argumentaire, le délai de rappel : tout change.

Ajoutez ces champs dans vos vues de liste, vos rapports, vos tableaux de bord. Filtrez, segmentez, mesurez le taux de qualification par source, le cycle de vente par campagne, le panier moyen par médium. C'est là que l'attribution devient de la business intelligence, pas juste une case cochée.

Aller plus loin : l'attribution multi-touch

Le dernier clic non-direct est un bon début. Mais les parcours complexes méritent mieux. Si vous avez le volume, passez à un modèle multi-touch : stockez l'historique complet des points de contact balisés dans le localStorage (un tableau d'objets avec timestamp, source, medium, campaign, page). Au formulaire, envoyez l'historique complet. Votre CRM ou votre entrepôt de données (BigQuery, Snowflake) pourra recalculer n'importe quel modèle : premier clic, linéaire, en U, en W, data-driven.

Cela demande plus de rigueur : déduplication des clics rapprochés, gestion de la fenêtre d'attribution (30j, 90j), enrichissement avec les données post-clic (pages vues, temps, scroll, vidéos). Mais ça transforme votre formulaire en point de collecte d'un parcours complet, pas juste une photo du dernier instant.

Commencez simple. Le dernier clic non-direct bien implémenté vaut mieux qu'un multi-touch mal fichu qui perd des données. Montez en sophistication quand le volume et les questions business le justifient.

Checklist de mise en production

  • Script de capture déployé sur toutes les pages d'entrée (vérifiez via Search Console : pages avec trafic organique + pages de destination Ads + pages lien newsletter + pages lien partenaires)
  • Liste blanche de paramètres documentée et partagée avec l'équipe marketing (pour qu'ils balisent correctement leurs URLs)
  • Règle de priorité (dernier clic non-direct) codée, testée, validée
  • Injection dans le formulaire testée sur tous les types de formulaires du site (natif, Typeform, HubSpot, Calendly, iframe)
  • Champs CRM créés, mapping configuré, webhook testé
  • Consent Mode v2 actif si Google Ads
  • Test de bout en bout automatisé dans la CI/CD
  • Documentation interne : comment baliser une URL, comment lire les champs dans le CRM, qui contacter si ça casse
  • Formation commerciale : 30 min pour expliquer les champs, leur signification, comment adapter l'approche
  • Rapport mensuel : volume de leads par source/medium/campagne, taux de qualification, CA attribué

Ce que vous gagnez vraiment

Plus de "d'où vient ce lead ?" dans Slack. Plus de "je crois que c'est la newsletter" au feeling. Chaque prospect arrive avec son pedigree complet. Votre équipe marketing voit enfin quelles campagnes génèrent des leads qui signent, pas juste des leads qui remplissent. Votre équipe commerciale arrive en rendez-vous avec le contexte : "je vois que vous avez cliqué sur notre comparatif vs Concurrent X". Votre direction alloue le budget sur les canaux qui produisent du chiffre, pas du trafic.

Le dispositif est invisible pour le visiteur. Aucun formulaire alourdi, aucune question en plus, aucun consentement supplémentaire pour les UTM (données non personnelles). Juste une ligne de code qui dit : "souviens-toi d'où il vient". Et une autre qui dit : "transmets-le quand il s'engage".

C'est tout. Mais c'est la différence entre piloter à l'aveugle et piloter aux instruments. Commencez cette semaine. Choisissez une page d'entrée, ajoutez le script, testez un formulaire. Étendez page par page. Dans un mois, vous ne comprendrez plus comment vous faisiez sans.

#email marketing#tracking UTM#attribution marketing#lead generation#analytics
Partager WhatsApp LinkedIn