16 min de lectureTutoriels
Pilier

Comment suivre les campagnes UTM de bout en bout sans CDP

Un manuel pratique pour les marketeurs : modèles UTM d'espace de travail, import en masse depuis Sheets, transmission de conversion côté serveur, et le dry-run QA qui attrape la dérive avant le lancement

Ana Kowalska
Marketing solutions engineering
Pipeline UTM en cinq étapes : modèle d'espace de travail, remplacement de campagne, import en masse, transmission côté serveur, vérification GA4 DebugView

J'ai déployé le suivi UTM de bout en bout dans trois entreprises. Chaque fois, les cinq mêmes choses se sont cassées dans le même ordre, et chaque fois la correction était la même : remonter le templating au niveau de la campagne, pousser la transmission de conversion vers le serveur, et intercaler un dry-run entre les deux. C'est l'essentiel de cet article. Le reste, c'est la checklist QA qui attrape ce que vous n'aviez pas pensé à casser.

Si vous n'êtes pas encore sûr de ce que fait chacun des cinq tags, les paramètres UTM expliqués est l'amorce sur laquelle ce pipeline se construit.

Vous n'avez pas besoin d'une plateforme de données client (CDP) pour ceci. Vous en aurez besoin d'une un jour si votre problème d'attribution devient « recoller quatre touches anonymes sur trois appareils en un seul parcours client », mais pour le cas que je vois le plus souvent - « taguer chaque lien sortant de manière cohérente, capturer le clic, transmettre la conversion à Meta et GA4 côté serveur, et survivre à Safari » - un raccourcisseur d'URL avec modèles plus une API de conversions fait le travail. Voici la version qui fonctionne, avec les modes de défaillance que j'ai observés soulignés.

Ce qui ne va pas avec le suivi UTM

Les marketeurs avec qui je travaille ne sont pas mauvais avec les UTM. Le problème, c'est que les outils rendent par défaut facile de taper un UTM une fois, difficile de l'imposer dans toute une organisation, et impossible de le corriger après le lancement. Quatre modes de défaillance reviennent sans cesse.

La dérive. Une personne tape utm_source=newsletter, une autre tape utm_source=Newsletter, une troisième tape utm_source=email. Six mois plus tard, votre canal « newsletter » est éclaté en neuf variantes de chaîne dans GA4. Le nettoyer après coup est un exercice de regex et de prière. Le script urchinTracker() d'origine qui a introduit cette convention - le produit d'analyse web Urchin pré-Analytics de Google, brièvement en open source en 2003 avant d'être absorbé - n'avait pas non plus de couche de modèle. La convention a toujours été « le taper de manière cohérente » ; l'outillage ne l'a jamais imposé.

Le tagage manuel à grande échelle. Une campagne de flyers avec 80 liens courts sur quatre magasins régionaux, ce sont 320 URL que vous devez taper, coller dans un tableur, copier dans votre raccourcisseur, et espérer. La moitié reçoit le mauvais utm_content. Personne ne le remarque avant que la campagne ne soit déjà lancée depuis deux semaines.

Les écarts de conversion côté serveur. Le pixel se déclenche sur la page de remerciement, GA4 le capte, Meta le capte, et vous rentrez chez vous. Puis Safari livre une nouvelle version d'ITP, les installations de bloqueurs de publicité augmentent, et vos conversions rapportées chutent d'un tiers. Les notes de version d'ITP 2.3 d'Apple détaillent exactement le mécanisme : la décoration de lien est limitée, document.referrer est retiré, et tout flux d'analyse qui dépend de l'exécution de JS tiers par le navigateur se dégrade silencieusement. Les conversions se produisent toujours sur votre serveur. Elles n'atteignent simplement plus les surfaces publicitaires.

Aucun dry-run. La première conversion qui traverse le nouveau pipeline est le premier vrai acheteur. Si quelque chose est mal configuré, vous le découvrez trois jours plus tard quand l'algorithme d'optimisation a déjà retiré du budget d'une campagne qui fonctionnait en réalité.

Cet article traite les trois premiers avec des modèles + import en masse + transmission côté serveur, et le quatrième avec une étape de vérification facile à sauter et coûteuse à sauter.

Modèles UTM d'espace de travail et de campagne

Les modèles remontent le problème de cohérence dans la pile. Vous définissez votre convention de tagage une fois au niveau de l'espace de travail, superposez des remplacements par campagne là où ils sont justifiés, et laissez chaque lien hériter. Il ne reste plus de place pour qu'une faute de frappe s'installe.

Définissez d'abord les valeurs par défaut de l'espace de travail. Les valeurs littérales fixent les variables qui ne changent jamais pour votre organisation (utm_medium = email pour les campagnes de newsletter) ; les placeholders se remplissent depuis la charge utile du lien à la création :

curl -X PUT \
  https://api.elido.app/v1/workspaces/1/utm-template \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "utm_source":   "{{ channel }}",
    "utm_medium":   "{{ medium }}",
    "utm_campaign": "{{ campaign }}",
    "utm_content":  "{{ creative }}",
    "utm_term":     "{{ audience.segment }}"
  }'

Quelques détails qui comptent ici :

  • Les placeholders sont remplis à la création du lien, pas au moment du clic. Ce qui atterrit dans votre outil d'analyse est ce qui était prévu au moment où le lien a été généré - pas ce que la destination du lien a calculé au moment du clic. Cela rend la reconstruction du journal d'audit bien plus facile quand quelque chose paraît faux six mois plus tard.
  • Les placeholders inconnus échouent rapidement. Si votre import en masse manque une colonne creative et que le modèle d'espace de travail référence {{ creative }}, l'API renvoie une erreur 422 avec le nom de la variable non résolue. Aucune application partielle silencieuse.
  • La référence complète du modèle, y compris les placeholders link.tag.<name> qui lisent depuis le tableau de tags du lien (utile pour les agences multi-locataires qui doivent intégrer un identifiant client dans chaque URL), est dans le guide de documentation.

Superposez ensuite un modèle de campagne. Les campagnes héritent de l'espace de travail et remplacent le sous-ensemble spécifique à la campagne :

curl -X POST \
  https://api.elido.app/v1/campaigns \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "name": "Printemps 2026 - DACH",
    "utm_template": {
      "utm_campaign": "spring_2026_dach",
      "utm_term":     "{{ audience.locale }}"
    }
  }'

Tout ce qui n'est pas défini sur la campagne retombe sur les valeurs par défaut de l'espace de travail. Le double niveau de superposition couvre la plupart des structures organisationnelles réelles : conventions partagées au niveau de l'espace de travail, remplacements spécifiques à l'équipe ou à la saison au niveau de la campagne. Si vous vous surprenez à vouloir un troisième niveau d'héritage, c'est un signe suspect - cela signifie généralement que deux campagnes devraient être une seule campagne avec des valeurs de placeholder plus intelligentes.

Page Campagnes du tableau de bord Elido, quatre campagnes avec leurs valeurs UTM par défaut renseignées : Lancement printemps 2026 (newsletter / email), Newsletter hebdomadaire, Influenceur DACH T2 (créateur / partenaire), Social payant retargeting Meta

Ce que les remplacements par lien abandonnent : un remplacement se déclenche quel que soit le modèle. Ce qu'ils conservent : le remplacement est enregistré dans le journal d'audit avec l'acteur + l'horodatage + le diff résolu-versus-final. Dans six mois, quand quelqu'un demande pourquoi un lien dans une campagne de 200 liens a utm_term=manual_override, vous pourrez répondre.

Import en masse depuis Sheets - le workflow que la plupart des marketeurs utilisent réellement

Les marketeurs ne passent pas leur journée dans curl. Le brief de campagne arrive sous forme de tableur avec des URL de destination et des métadonnées de campagne, la date limite de lancement est vendredi, et la question est de savoir comment ce tableur devient 200 liens courts sans que personne ne tape la même chaîne UTM 200 fois.

Les noms de colonnes CSV correspondent aux noms de placeholder de votre modèle (insensible à la casse). Les colonnes qu'Elido ne reconnaît pas sont abandonnées avec un avertissement plutôt que copiées silencieusement - c'est délibéré. La copie silencieuse est la façon dont vous vous retrouvez avec utm_brand_color apparaissant dans GA4 parce que quelqu'un a ajouté une colonne pour une note interne.

destination_url,channel,medium,creative
https://shop.example.com/de,newsletter,email,hero_a
https://shop.example.com/fr,newsletter,email,hero_a
https://shop.example.com/de,paid_social,meta,carousel_v2
https://shop.example.com/fr,paid_social,meta,carousel_v2

Envoyez-le en POST en multipart :

curl -X POST \
  https://api.elido.app/v1/links/bulk \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -F "csv=@launch_q2.csv" \
  -F "campaign_id=cmp_8a2f"

Deux choses que ce flux de validation vous apporte et que l'interface un-lien-à-la-fois n'apporte pas :

  • Validation tout-ou-rien. Une seule mauvaise ligne annule tout l'envoi et renvoie les numéros de ligne fautifs plus la raison - row 47: unresolved variable {{ creative }} est une bien meilleure erreur que de découvrir à 16 h un vendredi que 47 de vos 200 liens se sont résolus en une chaîne de placeholder.
  • Aperçu avant lancement. La ligne d'aperçu d'import en masse du tableau de bord montre l'URL résolue, y compris la chaîne de requête utm_* rendue, avant validation. Regardez le second lien pour vous assurer que votre modèle a fait ce que vous attendiez, puis regardez le dernier lien pour vous assurer que les lignes en bas du fichier n'ont pas dérivé. Deux coups d'œil, une minute.

Si votre tableur n'a pas une forme stable - l'ordre des colonnes change, les en-têtes sont renommés - le point d'entrée d'import en masse va être désagréable. La correction n'est pas dans notre outillage ; la correction, c'est de s'engager sur un schéma CSV pour vos briefs de campagne et de traiter la dérive de schéma comme un bug de processus. Nous discutons du schéma plus large dans la page solutions marketeurs.

Transmission de conversion côté serveur vers Meta CAPI et GA4

L'attribution par pixel seul perd 20 à 40 % des conversions à cause de Safari ITP, des bloqueurs de publicité et des bannières de consentement. Le chiffre varie selon le secteur - l'ecommerce DTC voit le haut de la fourchette, le SaaS B2B le bas - mais chaque mesure que j'ai vue depuis iOS 14 place la fiabilité du pixel bien en dessous de la barre des 95 % que les plateformes publicitaires supposent. L'algorithme d'optimisation reçoit des entrées plus bruyantes et votre CPA paraît pire qu'il ne l'est.

La documentation de l'API Conversions de Meta est explicite là-dessus : les événements serveur sont ce que vous voulez, le pixel côté navigateur est le complément. Le Measurement Protocol de GA4 fait le même constat. Les deux protocoles acceptent la même forme : un événement côté serveur avec les détails de conversion, un event_id pour la déduplication, et idéalement des identifiants utilisateur hachés pour que les plateformes puissent recoller la conversion à un visiteur connu.

La plomberie qui comble l'écart est mécanique. Trois étapes.

Étape un - capturer le click_id. Chaque réponse de redirection Elido porte un en-tête X-Elido-Click-Id. Les SDK TS / Python / Go l'exposent sur l'objet réponse de redirection ; le HTTP brut fonctionne aussi :

curl -sI https://elido.me/launch | grep -i click-id
# X-Elido-Click-Id: clk_01HYZ7T8WV6KQX3M

Rangez-le dans un cookie propriétaire sur la page de destination (elido_click_id, TTL de 90 jours - assez long pour couvrir une évaluation SaaS typique, assez court pour satisfaire les recommandations ePrivacy). Relisez-le au paiement.

Étape deux - câbler les destinations. Envoyez en PUT les identifiants pour les surfaces vers lesquelles vous voulez transmettre. Tout sous-ensemble fonctionne ; les surfaces manquantes sont ignorées silencieusement :

curl -X PUT \
  https://api.elido.app/v1/workspaces/1/conversion-forwarding \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "meta_capi": {
      "pixel_id": "1234567890",
      "access_token": "EAA…",
      "test_event_code": null
    },
    "ga4_mp": {
      "measurement_id": "G-ABC123",
      "api_secret": "abc_def_ghi"
    }
  }'

Mixpanel n'est pas une destination de conversion. L'intégration Mixpanel d'Elido transmet chaque clic sur lien court comme un événement link_click, et vous la connectez séparément sous Intégrations.

Étape trois - envoyer la conversion en POST. Quand la commande se déclenche, envoyez l'événement avec le click_id et les détails de commande. event_id est votre clé d'idempotence :

curl -X POST \
  https://api.elido.app/v1/conversions \
  -H "Authorization: Bearer $ELIDO_TOKEN" \
  -d '{
    "click_id":   "clk_01HYZ7T8WV6KQX3M",
    "event_name": "purchase",
    "event_id":   "ord_98231",
    "value":      89.00,
    "currency":   "EUR",
    "user": {
      "email":  "[email protected]",
      "phone":  "+4915123456789",
      "external_id": "cust_5128"
    }
  }'

Les champs d'identité utilisateur sont hachés en SHA-256 avant transmission à Meta et GA4 - c'est ce que les deux plateformes exigent. Le contexte UTM est extrait de la ligne de clic correspondant à click_id, donc l'événement transmis porte l'attribution de campagne d'origine même si l'utilisateur a erré sur le site pendant une heure avant de payer. La mécanique complète, y compris la gestion des remboursements et le bascule de modèle d'attribution multi-touch, est dans le guide de transmission de conversion.

Onglet admin du pixel de suivi de conversion dans le tableau de bord Elido, avec des champs pour l'ID Pixel Meta, l'ID Google Ads / GA4, le tag Insight LinkedIn, et le code Pixel TikTok

C'est l'essentiel de l'écart comblé. Il reste un trou résiduel - les visiteurs qui bloquent le cookie click_id, ou qui arrivent par une voie non-Elido - mais pour les campagnes vers lesquelles vous dirigez réellement du trafic, vous êtes passé d'une « fiabilité pixel de 60 à 80 % » à une « fiabilité serveur de 95 % et plus ».

Trois cas limites que le journal d'audit vous sauvera

Les modèles et la transmission gèrent le chemin heureux. Les cas ci-dessous apparaissent en semaine trois de toute campagne non triviale, et la bonne réponse à tous vit dans le journal d'audit + le panneau des conversions - pas dans la tentative de concevoir un modèle plus élaboré.

Un cas qui n'est pas sur cette liste parce que vous ne pouvez pas vous en sortir par le templating : un clic qui arrive sans referrer et avec un paramètre de campagne que vous n'avez pas défini. C'est ce qu'envoient les assistants IA, et suivre le trafic depuis ChatGPT explique quoi en faire.

Remboursements. Une conversion d'achat s'est déclenchée, le client a retourné l'article une semaine plus tard, et votre revenu rapporté est désormais 8 % trop élevé. La correction consiste à envoyer en POST le même event_id avec event_name: "refund". Meta et GA4 traitent cela comme une conversion négative contre l'originale. La raison pour laquelle event_id est conçu ainsi : l'idempotence au niveau de l'id d'événement signifie que vous ne pouvez pas non plus compter le remboursement en double. Le schéma complet est documenté dans la section cas limites du guide de transmission de conversion - remboursements, remboursements partiels, et avoirs ont chacun une forme légèrement différente.

Click_id manqués. Une conversion se déclenche avec un click_id qui ne correspond à aucun clic connu - faute de frappe, expiré au-delà de la rétention, mauvais espace de travail. La conversion est quand même enregistrée contre l'espace de travail mais transmise avec un contexte UTM vide. C'est intentionnel : une attribution fourre-tout est plus utile que de laisser tomber la conversion, et le drapeau click_id_unknown dans le journal d'audit vous permet de filtrer la tranche non attribuée pour le reporting. Si la tranche dépasse 5 % des conversions, quelque chose ne va pas dans la manière dont vous persistez le click_id sur la page de destination - généralement l'attribut SameSite du cookie ou la portée du chemin.

Conversions arrivant tardivement. Une vente SaaS B2B se conclut 47 jours après le clic d'origine. La rétention de clic par défaut d'Elido est de 30 jours, donc au moment où la conversion se déclenche, le clic a expiré et vous êtes dans le cas de click_id manqué ci-dessus. Deux corrections, selon votre cycle de vente : porter la rétention à 90 jours sur l'espace de travail (plan Pro et supérieur), ou capturer le click_id sur un identifiant propriétaire à longue durée de vie (la colonne original_click_id de votre enregistrement client) pour pouvoir le recoller au moment de la conversion même si le cookie a disparu. Nous avons vu les deux schémas en production.

Le journal d'audit montre le diff UTM résolu-versus-final par lien, le code de réponse de transmission par destination par conversion, et l'état de jointure click_id-vers-conversion. Quand l'algorithme d'optimisation retire du budget d'une campagne qui paraît sous-performante, le journal d'audit est ce qui vous permet de dire « non, la campagne va bien ; nous avons perdu trois jours de transmission à cause d'un api_secret GA4 tourné ». Regardez-le.

Le QA avant lancement - dry-run tout le pipeline

Ne laissez pas la première conversion qui traverse ceci être un vrai acheteur. Le coût d'un dry-run de 30 minutes est entièrement porté par vous ; le coût d'un pipeline mal configuré est porté par l'algorithme d'optimisation retirant du budget de votre campagne la plus performante pendant deux jours avant que vous ne le remarquiez. L'asymétrie est mauvaise.

Trois étapes, dans l'ordre.

Dry-run d'import en masse. Le point d'entrée d'import en masse accepte dry_run=true comme paramètre de requête. Il exécute la validation, résout les modèles, et renvoie les liens qui auraient été créés sans valider. Ouvrez la réponse dans n'importe quel visualiseur JSON ; l'URL résolue de chaque ligne est visible. Vérifiez ponctuellement 3 à 5 lignes : le second lien, le dernier lien, et toute ligne qui a remplacé les valeurs par défaut de l'espace de travail. Vérifiez que la chaîne de requête utm_* correspond exactement à ce que dit votre brief de campagne.

Mode test de transmission de conversion. Meta CAPI accepte un paramètre test_event_code, qui achemine l'événement vers l'onglet Test Events dans Events Manager au lieu de la production. Définissez-le sur la configuration de transmission de l'espace de travail, envoyez 10 à 20 conversions d'échantillon, et confirmez qu'elles atterrissent. Même idée pour GA4 : définissez debug_mode: true sur les événements et vérifiez dans DebugView. Les deux sont en temps réel. Le but n'est pas de vérifier ponctuellement que l'API fonctionne ; le but est d'attraper un pixel_id mal configuré ou un api_secret qui a été tourné et jamais mis à jour.

Test de bout en bout. Cliquez sur l'un de vos vrais liens courts depuis une session de navigateur propre. Observez le clic dans le panneau de clics récents du tableau de bord Elido. Faites comme si vous aviez acheté quelque chose - envoyez en POST une conversion purchase avec ce click_id depuis votre terminal. Confirmez que la conversion apparaît dans Meta Test Events et GA4 DebugView avec le bon contexte UTM attaché. La boucle entière prend moins de 10 minutes une fois que vous l'avez faite une fois.

Une fois les trois passés, retirez le test_event_code, définissez debug_mode: false, et lancez. Le premier vrai acheteur aura un pipeline propre qui l'attend.

Panneau des conversions dans le tableau de bord Elido montrant le total des conversions et du revenu, les meilleurs liens par revenu, un graphique du revenu quotidien sur les 30 derniers jours, et une ventilation du revenu par plateforme

Quand vous voudriez réellement une CDP

Modèles plus import en masse plus transmission côté serveur vous mène la majeure partie du chemin. Il existe une classe de problèmes où ce n'est pas le cas, et se tourner vers une CDP est le bon choix.

Recollage d'identité inter-appareils. Un visiteur clique sur un lien sur mobile, ne convertit pas, revient sur ordinateur, s'inscrit. Vous voulez que les deux touches soient attribuées à la même personne. Le suivi UTM + click_id est au niveau de la touche ; la couche d'identité utilisateur qui fait des deux touches un seul parcours est ce pour quoi une CDP (Segment, mParticle, RudderStack) est construite. Elido stocke jusqu'à 30 jours de clics par visiteur et prend en charge l'attribution dernière-touche / première-touche / basée-sur-la-position dans cette fenêtre, mais la jointure inter-appareils a besoin d'un graphe d'identité que nous n'exploitons délibérément pas.

Personnalisation sous 100 ms. Si vous rendez la page de destination selon les touches précédentes du visiteur en temps réel - en extrayant la cohorte d'un feature store et en faisant varier le titre principal - vous avez besoin de la résolution d'identité proche du rendu. C'est le territoire de la CDP ou, plus souvent, une plateforme d'expérimentation comme PostHog ou LaunchDarkly superposée par-dessus.

Attribution multi-touch à grande échelle. La dernière touche convient pour la plupart des campagnes. Si votre cycle de vente a six touches sur quatre mois et que vous devez vraiment créditer chacune, vous êtes dans le territoire où l'attribution par chaîne de Markov ou par valeur de Shapley commence à compter. Elido fait dernière-touche / première-touche / basée-sur-la-position ; tout ce qui est plus sophistiqué veut un outil avec un vrai graphe d'identité et une couche de modèle.

Pour tout le reste - et « tout le reste » est la plupart des équipes marketing avec qui j'ai travaillé - le schéma modèles + import en masse + transmission côté serveur suffit. Configurez le modèle d'espace de travail une fois, le modèle de campagne par lancement, la configuration de transmission une fois par intégration de plateforme, et exécutez le dry-run avant chaque lancement. Si vous faites les quatre, vous aurez un pipeline UTM plus serré que 80 % des équipes marketing que j'ai auditées.

Construisez-le une fois, testez-le en dry-run avant chaque lancement, et passez à la campagne suivante.

À lire aussi sur le blog

Essayer Elido

Collez une URL, obtenez un lien court

Sans inscription. Lien actif 30 jours. Inscrivez-vous pour le garder pour toujours.

Gratuit, sans inscription · 2 par jour

Essayer Elido

Raccourcisseur d'URL hébergé en UE : domaines personnalisés, analyses approfondies et API ouverte. Forfait gratuit - sans carte bancaire.

Tags
utm tracking
utm template
utm builder
utm attribution
conversion forwarding
ga4
meta capi

Lire la suite