ServicesÀ proposNotesContact Me contacter →
EN FR
Note

Macro dbt de regroupement des canaux GA4

Une macro dbt qui encapsule la logique de regroupement des canaux par défaut de Google sous forme de SQL réutilisable, avec les patterns regex et les cas limites à connaître.

Planté
ga4dbtbigqueryanalyticsdata modeling

Le regroupement des canaux traduit les combinaisons brutes source/medium UTM en catégories lisibles par les équipes métier : Recherche organique, Social payant, Direct, Email. L’interface GA4 applique ces regroupements automatiquement en utilisant les règles par défaut de Google. Dans un projet dbt, vous devez répliquer cette logique — et une macro est la bonne abstraction.

Pourquoi une macro

Le regroupement des canaux est nécessaire à au moins deux endroits : le modèle intermédiaire d’événements sessionisés et potentiellement tout mart incluant l’attribution par canal. Répéter le CASE statement signifierait plusieurs points de maintenance. Une macro appelle la logique une seule fois et génère le SQL partout où elle est référencée.

La macro prend des références de colonnes (pas des valeurs) comme arguments, ce qui est le pattern standard dbt pour les macros génératrices de SQL :

-- macros/ga4/default_channel_grouping.sql
{% macro default_channel_grouping(source_column, medium_column) %}
CASE
-- Direct
WHEN {{ source_column }} IS NULL
OR {{ source_column }} = '(direct)'
OR {{ source_column }} = '(none)'
THEN 'Direct'
-- Recherche payante
WHEN REGEXP_CONTAINS({{ medium_column }}, r'^(cpc|ppc|paidsearch)$')
OR ({{ source_column }} = 'google' AND {{ medium_column }} = 'sem')
THEN 'Paid Search'
-- Social payant
WHEN REGEXP_CONTAINS({{ medium_column }}, r'^(paidsocial|paid-social|paid_social)$')
OR (REGEXP_CONTAINS({{ source_column }}, r'facebook|instagram|linkedin|twitter|tiktok')
AND REGEXP_CONTAINS({{ medium_column }}, r'^(cpc|ppc|paid)'))
THEN 'Paid Social'
-- Display
WHEN REGEXP_CONTAINS({{ medium_column }}, r'^(display|cpm|banner)$')
THEN 'Display'
-- Recherche organique
WHEN {{ medium_column }} = 'organic'
OR REGEXP_CONTAINS({{ source_column }}, r'google|bing|yahoo|duckduckgo|baidu')
AND {{ medium_column }} = 'organic'
THEN 'Organic Search'
-- Social organique
WHEN REGEXP_CONTAINS({{ source_column }}, r'facebook|instagram|linkedin|twitter|tiktok|pinterest|youtube')
AND ({{ medium_column }} IS NULL OR {{ medium_column }} IN ('social', 'referral', '(none)'))
THEN 'Organic Social'
-- Email
WHEN REGEXP_CONTAINS({{ medium_column }}, r'^(email|e-mail|e_mail)$')
THEN 'Email'
-- Affiliation
WHEN REGEXP_CONTAINS({{ medium_column }}, r'^(affiliate|affiliates)$')
THEN 'Affiliates'
-- Référent
WHEN {{ medium_column }} = 'referral'
THEN 'Referral'
-- Autre
ELSE 'Other'
END
{% endmacro %}

Utilisation dans le modèle sessionisé :

{{ default_channel_grouping('session__source_final', 'session__medium_final') }}
AS session__channel_grouping

L’ordre du CASE est important

Le CASE statement est évalué de haut en bas, la première correspondance gagne. L’ordre ici encode des décisions de priorité :

  1. Direct en premier — Une source nulle est toujours Direct, avant toute logique basée sur le medium
  2. Payant avant organique — Le medium cpc est classifié comme Recherche payante avant que la règle Recherche organique ne puisse attraper une source Google
  3. Medium Social payant d’abord, puis source + medium — Les équipes utilisant paidsocial comme medium sont classifiées directement ; les équipes utilisant le medium cpc avec des sources de réseaux sociaux sont attrapées par la deuxième condition
  4. Social organique vérifie source + medium non payant — Attrape facebook/instagram avec medium social/referral, mais pas s’ils ont un medium payant (déjà attrapé ci-dessus)
  5. Référent en dernier — Passe après toutes les autres classifications de canal

Changer cet ordre change le résultat. Si vous mettez Référent avant Social organique, certains trafics de référence sociale seront classifiés comme Référent plutôt que Social organique.

Où le regroupement des canaux diverge de l’interface GA4

Votre macro ne correspondra pas exactement à l’interface GA4. L’interface utilise le jeu complet de règles de regroupement des canaux de Google, plus complexe et incluant une logique spécifique aux plateformes que Google ne publie pas entièrement. Attendez-vous à des différences dans le segment « Autre ».

Les points de divergence les plus courants :

Recherche payante de marque vs hors marque. Google Ads peut taguer les campagnes avec des signaux branded ou non-branded, et l’interface peut distinguer ces derniers comme des canaux séparés. Votre macro classe les deux comme Recherche payante.

Cross-network et Performance Max. Les types de campagnes plus récents peuvent utiliser des valeurs de medium non couvertes par les patterns regex standard. Lorsque vous voyez du trafic atterrir dans « Autre » que vous savez être payant, vérifiez les valeurs brutes source/medium et ajoutez des conditions correspondantes.

YouTube. YouTube peut apparaître à la fois comme Social organique (vues organiques YouTube) et Vidéo payante (publicités YouTube payantes avec medium video). Le regex attrape YouTube dans Social organique ; assurez-vous que vos campagnes YouTube payantes utilisent un medium comme cpc ou paid pour être attrapées par les règles Social payant ou Display en premier.

Alignement avec vos conventions UTM

La macro encode des hypothèses sur votre taxonomie UTM. Si votre équipe utilise paid-social comme convention de medium pour les publicités sociales, le regex r'^(paidsocial|paid-social|paid_social)$' le couvre. Si vous utilisez quelque chose de non standard comme social_paid, il tombera dans « Autre ».

Avant de déployer, exécutez une requête de validation :

SELECT
session__source,
session__medium,
session__channel_grouping,
COUNT(*) AS sessions
FROM mrt__analytics__sessions
WHERE session__channel_grouping = 'Other'
GROUP BY 1, 2, 3
ORDER BY 4 DESC
LIMIT 50

Tout volume de sessions significatif dans « Autre » avec des sources reconnaissables mérite une investigation. Soit votre nommage UTM ne correspond pas aux patterns attendus (un problème de convention de nommage), soit la macro a besoin d’une condition supplémentaire.

Tester la sortie

Ajoutez un test accepted_values à la colonne dans votre YAML :

- name: session__channel_grouping
tests:
- accepted_values:
values:
- 'Direct'
- 'Organic Search'
- 'Paid Search'
- 'Paid Social'
- 'Organic Social'
- 'Email'
- 'Referral'
- 'Display'
- 'Affiliates'
- 'Other'

Ce test avertira (ou générera une erreur, selon la sévérité) si la macro génère un nom de canal inattendu. Utile comme garde-fou contre les futures modifications qui introduiraient une faute de frappe ou une nouvelle catégorie de canal sans mettre à jour la liste des valeurs acceptées.