ServicesÀ proposNotesContact Me contacter →
EN FR
Note

Rétrocouture utilisateur GA4

Comment appliquer rétroactivement user_id de GA4 aux sessions anonymes dans l'entrepôt — le pattern SQL, la gestion des appareils partagés, et quand la rétrocouture vaut sa complexité.

Planté
ga4bigquerydbtdata modelinganalytics

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_id
FROM {{ ref('base__ga4__events') }} e
LEFT JOIN known_identities k
ON k.user_pseudo_id = e.user_pseudo_id

Le 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_id
FROM {{ ref('base__ga4__events') }} e
LEFT 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_360

Le 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_id ne 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.