GA4 applique user_id à tous les événements de la session courante lorsqu’il est défini, mais ne l’applique pas rétroactivement aux sessions précédentes. Si un visiteur navigue sur votre site de manière anonyme pendant trois sessions avant de se connecter lors de la quatrième, les sessions une à trois restent anonymes dans les données de GA4 — même si vous savez maintenant qui est cette personne.
Cela signifie que vos données de navigation pré-connexion sont déconnectées de la personne qui a finalement converti. Pour les modèles Customer 360 et l’attribution marketing, cet écart est significatif. Le parcours complet de découverte du visiteur — les articles de blog lus, les visites de la page tarification, les comparaisons de fonctionnalités — reste attaché à un user_pseudo_id anonyme que votre CRM ne connaît pas.
La rétrocouture utilisateur corrige cela dans l’entrepôt en utilisant un principe simple : si nous avons jamais observé un user_id associé à un user_pseudo_id donné, appliquons-le à tous les événements de cet appareil.
Le pattern SQL de base
La technique nécessite deux étapes : construire un lookup des paires d’identité connues, puis le joindre à tous les événements.
WITH known_identities AS ( SELECT DISTINCT user_id, user_pseudo_id FROM {{ ref('base__ga4__events') }} WHERE user_id IS NOT NULL)
SELECT e.event_date, e.event_timestamp, e.event_name, e.user_pseudo_id, -- Préférer le user_id propre à l'événement ; revenir à la valeur rétrocousue COALESCE(e.user_id, k.user_id) AS resolved_user_idFROM {{ ref('base__ga4__events') }} eLEFT JOIN known_identities k ON k.user_pseudo_id = e.user_pseudo_idLe COALESCE garantit que si un événement a déjà un user_id défini (parce que l’utilisateur était connecté au moment), la valeur originale est préservée. La valeur rétrocousue ne remplit que les événements où user_id était null.
La colonne resolved_user_id devient le pont vers vos données CRM. Une fois que vous connaissez le user_id pour un user_pseudo_id, vous pouvez retracer l’historique complet de navigation de cet appareil — y compris les sessions anonymes qui ont précédé la connexion.
Gestion des appareils partagés
Le principal cas limite est les appareils partagés. Si deux personnes utilisent le même navigateur, le même user_pseudo_id pourrait correspondre à plusieurs valeurs user_id. Sans gestion de ce cas, la CTE known_identities produit un fan-out : une ligne user_pseudo_id se joint à plusieurs lignes d’identité, dupliquant les événements.
L’approche la plus sûre est de prendre la correspondance la plus récente :
WITH known_identities AS ( SELECT user_id, user_pseudo_id FROM {{ ref('base__ga4__events') }} WHERE user_id IS NOT NULL QUALIFY ROW_NUMBER() OVER ( PARTITION BY user_pseudo_id ORDER BY event_timestamp DESC ) = 1)Cela dit : pour chaque appareil, la dernière personne à se connecter est celle que nous associons à tous les événements. C’est une heuristique, pas une solution parfaite. Les événements de l’autre personne sont mal attribués. Mais les appareils partagés sont relativement rares en pratique (surtout sur mobile), et l’alternative — ne pas faire de rétrocouture du tout — perd beaucoup plus de données que le cas limite de l’appareil partagé ne corrompt.
Pour les équipes qui ont besoin d’une meilleure précision, une approche temporelle assigne les événements à l’utilisateur connecté le plus proche dans le temps :
WITH known_identities AS ( SELECT user_id, user_pseudo_id, event_timestamp AS identified_at, LEAD(event_timestamp) OVER ( PARTITION BY user_pseudo_id ORDER BY event_timestamp ) AS next_identification_at FROM {{ ref('base__ga4__events') }} WHERE user_id IS NOT NULL)
SELECT e.*, COALESCE( e.user_id, k.user_id ) AS resolved_user_idFROM {{ ref('base__ga4__events') }} eLEFT JOIN known_identities k ON k.user_pseudo_id = e.user_pseudo_id AND e.event_timestamp <= k.identified_at AND (k.next_identification_at IS NULL OR e.event_timestamp > COALESCE( LAG(k.identified_at) OVER ( PARTITION BY k.user_pseudo_id ORDER BY k.identified_at ), TIMESTAMP('1970-01-01') ))C’est plus complexe et plus difficile à maintenir. L’approche simple du plus récent fonctionne pour la grande majorité des cas d’usage.
Où la rétrocouture s’intègre dans le DAG dbt
La rétrocouture appartient à la couche de résolution d’identité, après les modèles de base et avant les modèles mart. Dans le DAG Customer 360, elle vit généralement dans ou alimente le modèle int__identity_resolved :
base__ga4__events ↓int__ga4__events_with_resolved_identity (la rétrocouture se produit ici) ↓int__identity_resolved (combine toutes les sources d'identité) ↓mrt__core__customer_360Le modèle d’événements rétrocousus ajoute resolved_user_id à chaque événement GA4. Les modèles en aval — événements sessionisés, timelines de points de contact, modèles d’attribution — consomment tous cette identité résolue plutôt que le champ user_id brut.
Matérialisation
Le lookup known_identities est petit (au plus une ligne par appareil qui a eu un utilisateur connecté), mais la jointure contre la table complète des événements est coûteuse. Matérialisez le modèle d’événements rétrocousus comme un modèle incrémentiel avec insert_overwrite et une fenêtre de lookback :
{{ config( materialized='incremental', incremental_strategy='insert_overwrite', partition_by={ 'field': 'event_date', 'data_type': 'date' }, partitions=['CURRENT_DATE()', 'DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)', 'DATE_SUB(CURRENT_DATE(), INTERVAL 2 DAY)']) }}Un lookback de 3 jours gère les événements GA4 arrivant en retard. Le lookup d’identité devrait toujours scanner la table complète (ou au minimum les 90 derniers jours) pour capturer les identités établies des semaines avant la fenêtre de traitement courante.
Quand la rétrocouture a de la valeur — et quand elle n’en a pas
La rétrocouture est la plus précieuse lorsque :
- Il existe un écart significatif entre le premier point de contact d’un visiteur et sa première connexion (courant en SaaS B2B avec de longs cycles d’évaluation)
- Votre modèle d’attribution a besoin de l’historique de navigation pré-connexion pour créditer les canaux de notoriété
- Vous construisez un Customer 360 qui doit inclure le parcours complet, pas seulement le comportement post-connexion
La rétrocouture apporte moins de valeur lorsque :
- Les utilisateurs se connectent dès la première visite (ex. un produit avec authentification obligatoire)
- Votre analyse se concentre sur l’utilisation du produit post-connexion, pas sur l’attribution marketing
- Les durées de vie des cookies sont très courtes en raison des restrictions ITP/navigateur, donc les valeurs
user_pseudo_idne persistent pas assez longtemps pour valoir la peine d’être rétrocousues
La technique est également limitée par le problème inter-appareils. La rétrocouture connecte les sessions anonymes à un utilisateur connu sur le même appareil. Elle ne peut pas lier les sessions entre appareils — cela nécessite que l’utilisateur se connecte sur chaque appareil indépendamment. Pour l’identité inter-appareils, vous avez besoin de la couche complète de résolution d’identité combinant les soumissions de formulaires, les connexions et potentiellement les identifiants de transaction.