Les modèles d’attribution déterminent quels canaux marketing reçoivent du crédit pour les conversions. Les modèles courants — first-touch, last-touch, linéaire, décroissance temporelle — utilisent tous des fonctions de fenêtrage pour identifier le point de contact pertinent. Chaque modèle nécessite des scénarios de test spécifiques pour vérifier que la logique de fenêtrage est correcte.
Tester le first-touch et le last-touch
-- models/marts/marketing/mrt__marketing__customer_attribution.sqlselect customer_id, first_value(utm_source) over ( partition by customer_id order by session_start ) as first_touch_source, first_value(utm_medium) over ( partition by customer_id order by session_start ) as first_touch_medium, last_value(utm_source) over ( partition by customer_id order by session_start rows between unbounded preceding and unbounded following ) as last_touch_source, max(case when converted then session_start end) as conversion_timestampfrom {{ ref('int__customers_sessions') }}unit_tests: - name: test_mrt_marketing_customer_attribution_first_last_touch model: mrt__marketing__customer_attribution description: "Le first-touch capture la source initiale, le last-touch capture la source de conversion" given: - input: ref('int__customers_sessions') rows: # Parcours client : Facebook → Google → Direct (conversion) - {customer_id: 100, session_start: "2024-06-01 10:00:00", utm_source: "facebook", utm_medium: "paid", converted: false} - {customer_id: 100, session_start: "2024-06-05 14:00:00", utm_source: "google", utm_medium: "organic", converted: false} - {customer_id: 100, session_start: "2024-06-10 09:00:00", utm_source: "direct", utm_medium: "none", converted: true} # Conversion en un seul contact - {customer_id: 101, session_start: "2024-06-02 11:00:00", utm_source: "email", utm_medium: "newsletter", converted: true} expect: rows: - {customer_id: 100, first_touch_source: "facebook", first_touch_medium: "paid", last_touch_source: "direct"} - {customer_id: 101, first_touch_source: "email", first_touch_medium: "newsletter", last_touch_source: "email"}Ce test vérifie deux scénarios :
Le parcours multi-touch du client 100 : premier contact via des publicités payantes Facebook (1er juin), retour via Google organique (5 juin), conversion via une visite directe (10 juin). Le crédit first-touch va à Facebook (où le parcours a commencé). Le crédit last-touch va au Direct (le dernier point de contact). Si vos fonctions de fenêtrage FIRST_VALUE ou LAST_VALUE ont un ordonnancement ou un cadrage incorrect, ce test le détecte.
La conversion en un seul contact du client 101 : quand il n’y a qu’une seule session avant la conversion, le first-touch et le last-touch devraient être le même canal. Ce cas limite échoue souvent quand les implémentations supposent au moins deux points de contact.
Tester l’exclusion sans conversion
L’attribution n’a de sens que pour les clients qui ont réellement converti. Les visiteurs qui n’ont pas converti devraient être entièrement exclus du modèle d’attribution.
unit_tests: - name: test_mrt_marketing_customer_attribution_no_conversion model: mrt__marketing__customer_attribution description: "Les clients sans conversion ne devraient pas apparaître" given: - input: ref('int__customers_sessions') rows: - {customer_id: 200, session_start: "2024-06-01 10:00:00", utm_source: "facebook", utm_medium: "paid", converted: false} - {customer_id: 200, session_start: "2024-06-05 14:00:00", utm_source: "google", utm_medium: "organic", converted: false} expect: rows: []Le bloc expect vide avec rows: [] vérifie que le client 200, qui a eu des sessions mais n’a jamais acheté, est exclu de la sortie d’attribution. Ce test est tout aussi important que les cas positifs — sans lui, les visiteurs non convertis pourraient apparaître dans les rapports d’attribution et fausser les métriques de performance des canaux.
Trois scénarios de test pour tout modèle d’attribution
Quel que soit le modèle d’attribution que vous implémentez, ces trois scénarios devraient toujours être testés :
-
Parcours multi-touch : le client typique qui interagit avec plusieurs canaux avant de convertir. Vérifie que le bon point de contact reçoit du crédit selon les règles du modèle d’attribution.
-
Conversion en un seul contact : un client qui convertit lors de sa première visite. Le first-touch et le last-touch devraient être d’accord. L’attribution linéaire devrait donner 100 % au canal unique. Ce cas limite casse les modèles qui supposent plusieurs points de contact.
-
Pas de conversion : les visiteurs qui ne convertissent jamais devraient être exclus (ou traités distinctement). Vérifie que le filtre de conversion fonctionne correctement.
Pièges spécifiques aux tests d’attribution
Spécification du cadre LAST_VALUE : le cadre de fenêtrage par défaut pour LAST_VALUE est ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, qui retourne la ligne actuelle — pas la dernière ligne réelle de la partition. Si votre modèle utilise LAST_VALUE, assurez-vous qu’il spécifie ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING. Votre test le détectera immédiatement si la source last-touch revient incorrectement.
Ordonnancement des points de contact : si deux sessions ont le même horodatage (possible avec des données en granularité journalière), l’attribution devient non déterministe. Incluez un critère de départage dans votre ORDER BY, ou ajoutez un cas de test avec des horodatages identiques pour documenter le comportement attendu.
Sources UTM nulles : le trafic direct a souvent des paramètres UTM nuls. Testez si votre modèle traite la source UTM null comme “direct” ou la laisse nulle. Le test documente la convention que vous avez choisie.
Pour des approches d’attribution plus complexes comme les modèles linéaires ou à décroissance temporelle, les données de test deviennent plus élaborées mais le principe reste le même : concevez des parcours de test qui produiraient une distribution de crédit incorrecte si la logique de pondération était erronée.