Chaque modèle d’attribution — premier contact, dernier contact, linéaire, basé sur la position, décroissance temporelle, algorithmique — opère sur la même entrée : une table de touchpoints qui relie les interactions marketing aux conversions dans une fenêtre de lookback. Les modèles diffèrent uniquement dans la façon dont ils distribuent le crédit. Concevez mal la table de touchpoints et chaque modèle en aval hérite des mêmes problèmes.
Cette note couvre les champs dont la table de touchpoints a besoin, les défis d’identité qui affectent la précision et le modèle dbt intermédiaire qui la construit à partir d’événements bruts.
Champs Requis
La table de touchpoints a besoin de ces champs au minimum :
| Champ | Objectif | Exemple |
|---|---|---|
user_id | Identifiant utilisateur (appareil ou authentifié) | user_pseudo_id, customer_id |
session_id | Identifiant de session | ga_session_id |
touchpoint_timestamp | Moment où le touchpoint s’est produit | event_timestamp |
channel | Classification marketing | paid search, email, organic social |
source / medium | Détail de la source de trafic | google / cpc, newsletter / email |
campaign | Identifiant de campagne | Valeur UTM campaign |
transaction_id | Relie le touchpoint à la conversion | order_id |
conversion_timestamp | Moment où la conversion s’est produite | Horodatage d’événement d’achat |
revenue | Valeur de la conversion | 149.99 |
Le champ channel est typiquement une concaténation de source et medium (google / cpc) ou une macro de regroupement de canaux qui classe les paires source/medium en catégories marketing. Les deux approches fonctionnent, mais soyez cohérent — les valeurs de canal deviennent vos dimensions de rapport d’attribution.
Le Problème d’Identité
Le champ user_id mérite une attention particulière. Si vous travaillez avec des données GA4, user_pseudo_id est basé sur l’appareil. La même personne sur son téléphone, son ordinateur portable et son ordinateur de travail apparaît comme trois utilisateurs distincts. Sans résolution d’identité, votre attribution pense que trois personnes différentes ont eu un touchpoint chacune, alors qu’en réalité une seule personne a eu trois touchpoints dans un seul parcours.
Pour une attribution précise, vous devez éventuellement rejoindre les valeurs user_id authentifiées avec les identifiants anonymes d’appareils. C’est le problème de couture d’identité. Cela ne vous empêche pas de construire l’attribution — vous pouvez commencer avec user_pseudo_id et obtenir des résultats directionnellement utiles — mais cela plafonne votre précision. Les cycles d’achat courts (où les utilisateurs convertissent généralement sur le même appareil que celui sur lequel ils vous ont découvert) sont moins affectés que les longs cycles B2B où un prospect peut interagir sur plusieurs appareils sur plusieurs semaines.
L’impact pratique : sans couture d’identité, votre attribution sur-comptera le crédit du premier contact (chaque appareil obtient son propre « premier contact ») et sous-comptera la longueur des parcours multi-touch. Si la longueur médiane de votre parcours semble suspicieusement courte, la fragmentation d’identité en est généralement la raison.
Ce qui Compte comme Touchpoint
Il s’agit d’une décision de modélisation, pas technique. Approches courantes :
Touchpoints au niveau de la session. Chaque session avec une source marketing compte comme un touchpoint. C’est l’approche la plus courante et ce que les champs de source de trafic au niveau session de GA4 supportent naturellement. Un utilisateur qui visite trois pages dans une session à partir d’un clic de recherche payante génère un touchpoint, pas trois.
Touchpoints au niveau des événements. Des événements spécifiques à forte valeur (demandes de démo, téléchargements de contenu, vues de la page de tarification) comptent chacun comme un touchpoint quelle que soit la session. Cela donne une attribution plus granulaire mais gonfle les comptages de touchpoints et peut sur-créditer les canaux qui génèrent de l’engagement sans générer de conversion.
Touchpoints au niveau des clics. Seuls les clics publicitaires explicites (gclid, fbclid) comptent. Cela exclut entièrement les touchpoints organiques et directs, limitant votre attribution aux seuls canaux payants.
Pour la plupart des implémentations, les touchpoints au niveau de la session offrent le bon équilibre. Ils capturent chaque interaction marketing sans gonfler la longueur du parcours.
Le Modèle dbt Intermédiaire
Dans un projet dbt à trois couches, la table de touchpoints vit dans la couche intermédiaire. Elle consomme les événements nettoyés de la couche base et produit les lignes que les modèles mart d’attribution consomment.
Voici le pattern pour les données GA4 dans BigQuery :
-- int__touchpoints_mapped.sqlWITH touchpoint_events AS ( SELECT user_pseudo_id, session_id, event_timestamp, COALESCE(source, '(direct)') AS source, COALESCE(medium, '(none)') AS medium, CONCAT( COALESCE(source, '(direct)'), ' / ', COALESCE(medium, '(none)') ) AS channel FROM {{ ref('base__ga4__events') }} WHERE session_id IS NOT NULL),
conversion_events AS ( SELECT user_pseudo_id, event_timestamp, transaction_id, revenue FROM {{ ref('base__ga4__events') }} WHERE event_name = 'purchase')
SELECT t.user_pseudo_id AS user_id, c.transaction_id, t.session_id, t.event_timestamp AS touchpoint_timestamp, c.event_timestamp AS conversion_timestamp, t.source, t.medium, t.channel, c.revenueFROM touchpoint_events tJOIN conversion_events c ON t.user_pseudo_id = c.user_pseudo_id AND t.event_timestamp <= c.event_timestamp AND t.event_timestamp >= TIMESTAMP_SUB( c.event_timestamp, INTERVAL 30 DAY )Quelques points à noter sur ce pattern :
Les deux CTEs tirent du même modèle base. Les événements de touchpoints et les événements de conversion proviennent de base__ga4__events. Le CTE de touchpoints extrait les sessions avec des données de source de trafic. Le CTE de conversion extrait les événements d’achat. La jointure les relie par utilisateur dans la fenêtre de lookback.
La condition de jointure est là où le périmètre d’attribution se définit. t.event_timestamp <= c.event_timestamp garantit que seuls les touchpoints avant la conversion sont qualifiés. Le filtre TIMESTAMP_SUB définit la fenêtre de lookback — 30 jours ici, mais cela devrait correspondre au cycle d’achat de votre entreprise.
La gestion des source/medium nuls est importante. Les visites directes ont des source et medium nuls dans GA4. Les COALESCE les enveloppent en (direct) / (none) pour qu’ils apparaissent comme un canal plutôt que de disparaître de l’attribution. Inclure ou non les visites directes comme touchpoints est une décision métier — certaines équipes les excluent car « direct » est souvent un fourre-tout pour le trafic non attribué.
Une ligne par paire touchpoint-conversion. Si un utilisateur a 5 sessions avant de convertir, cela produit 5 lignes pour cette conversion, chacune avec la source de trafic de la session et le revenu de la conversion. Les modèles d’attribution en aval décident ensuite comment distribuer ce revenu sur les 5 lignes.
Le Modèle Base Alimentant Ce Modèle
Le modèle base nettoie les données d’export brutes GA4 BigQuery. Pour l’attribution, les transformations clés sont le dépliage des structures imbriquées et la standardisation des noms de champs :
-- base__ga4__events.sqlSELECT user_pseudo_id, (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id') AS session_id, event_timestamp, event_name, traffic_source.source, traffic_source.medium, traffic_source.name AS campaignFROM {{ source('ga4', 'events') }}Ce modèle base est partagé entre de nombreux cas d’usage en aval — sessionisation, analyse des funnels, métriques d’engagement — pas seulement l’attribution. Les champs de source de trafic qu’il expose sont ce que le modèle de touchpoints intermédiaire consomme.
Agrégation pour le Reporting par Canal
La table de touchpoints et les modèles d’attribution en aval produisent des lignes au niveau des touchpoints. Pour le reporting de performance des canaux, vous agrégez :
SELECT channel, COUNT(DISTINCT transaction_id) AS conversions_touched, SUM(attributed_revenue) AS total_attributed_revenue, SUM(attributed_revenue) / COUNT(DISTINCT transaction_id) AS avg_attributed_valueFROM attribution_resultsGROUP BY channelORDER BY total_attributed_revenue DESCPour les modèles à contact unique (premier contact, dernier contact), conversions_touched est égal au nombre réel de conversions — chaque conversion correspond à exactement un canal. Pour les modèles multi-touch (linéaire, basé sur la position), conversions_touched compte combien de conversions un canal a participé, ce qui est utile pour comprendre les conversions assistées.
Cette agrégation vit typiquement dans le modèle de résumé de comparaison plutôt que comme mart séparé, car vous voulez la même agrégation appliquée de manière cohérente à tous les modèles.
Erreurs Courantes
Oublier la fenêtre de lookback. Sans le filtre TIMESTAMP_SUB, vous joindrez des touchpoints d’il y a des mois aux conversions d’aujourd’hui. Un utilisateur qui a d’abord visité via le référencement naturel il y a 6 mois obtient ce crédit de visite aux côtés du clic de reciblage d’hier, même si la visite organique n’a aucune relation plausible avec la conversion.
Inclure des touchpoints post-conversion. Si la condition de jointure n’applique pas touchpoint_timestamp <= conversion_timestamp, une session qui se produit après l’achat obtient du crédit d’attribution pour celui-ci. Cela semble évident mais est facile à manquer quand la logique de jointure devient complexe.
Ne pas dédupliquer les sessions. Si votre modèle base produit plusieurs lignes par session (une par événement), le CTE de touchpoints doit dédupliquer en une ligne par session. Sinon, une session avec 15 pages vues devient 15 touchpoints, gonflant massivement la part de revenus attribués à cette session.
Ignorer les achats répétés. Un utilisateur avec 3 achats a 3 chemins de conversion séparés. Chaque achat devrait avoir son propre ensemble de touchpoints qualifiants, partitionné par transaction_id. Si vous partitionnez uniquement par user_id, tous les touchpoints sont crédités pour tous les achats.