D’où viennent les données marketing ?
Un service marketing travaille avec trois grandes familles de données :
- les sessions (ou visites) : une ligne par visite du site, avec son origine (source, support, campagne), l’appareil et le fait qu’elle ait abouti ou non à une conversion ;
- les points de contact : une ligne par interaction d’une personne avec une campagne avant de convertir (clic sur une annonce, ouverture d’un e-mail, visite depuis un réseau social) ;
- les conversions : une ligne par objectif atteint (achat, demande de devis, inscription), avec sa valeur.
Ces données sont produites par un outil de mesure d’audience (comme Google Analytics 4), par les plateformes publicitaires et par votre propre base de commandes. Elles ne racontent jamais exactement la même histoire : chaque outil a ses règles de comptage. Votre premier travail d’analyste est donc de savoir quel est le grain de la table que vous manipulez : une ligne correspond-elle à une session, à une personne, à un clic, à une commande ?
Les paramètres UTM
Pour savoir d’où vient une visite, on ajoute aux liens des campagnes des paramètres UTM :
https://boutique.example/soldes?utm_source=newsletter&utm_medium=email&utm_campaign=soldes_hiver
utm_source: l’émetteur précis (newsletter, google, facebook) ;utm_medium: le type de support (email, cpc pour le clic payant, social, referral) ;utm_campaign: le nom de la campagne ;utm_contentetutm_term(facultatifs) : la variante de l’annonce et le mot-clé.
Python lit ces paramètres avec le module standard urllib.parse :
from urllib.parse import urlparse, parse_qs
url = "https://boutique.example/?utm_source=Newsletter&utm_medium=Email&utm_campaign=Soldes_Hiver"
params = parse_qs(urlparse(url).query)
print(params) # {'utm_source': ['Newsletter'], 'utm_medium': ['Email'], ...}
parse_qs renvoie une liste de valeurs par paramètre, car un paramètre peut apparaître plusieurs fois. On prend en général la première.
Normaliser avant de compter
Les outils de mesure distinguent Facebook, facebook et facebook : sans normalisation, une même source se retrouve éclatée sur trois lignes et chacune paraît petite. Deux règles simples :
- mettre toutes les valeurs en minuscules et retirer les espaces superflus ;
- publier une convention de nommage (par exemple : minuscules, mots séparés par
_, liste fermée de supports autorisés) et la faire respecter par tous ceux qui créent des liens.
Quand une visite n’a ni UTM ni site référent identifiable, elle est classée en accès direct : source (direct), support (none). Attention, « direct » ne veut pas dire « l’internaute a tapé l’adresse » : un lien non marqué dans un PDF, une application de messagerie ou un e-mail mal tagué arrive aussi en direct.
Regrouper en canaux
Un responsable marketing raisonne en canaux (recherche payante, e-mail, réseaux sociaux…) plutôt qu’en couples source / support. Le regroupement se fait avec des règles ordonnées : la première règle qui s’applique gagne.
def channel_group(source, medium):
if source == "(direct)":
return "Direct"
if medium == "email":
return "E-mail"
if medium in ("cpc", "ppc"):
return "Recherche payante"
if medium == "paid_social":
return "Social payant"
if medium == "organic":
return "Recherche naturelle"
if medium in ("social", "organic_social"):
return "Social naturel"
if medium == "referral":
return "Sites référents"
return "Autres"
Les outils du marché proposent leurs propres regroupements par défaut, avec des règles plus riches. Écrire les vôtres a deux avantages : vous savez exactement ce que contient chaque canal, et vous pouvez les appliquer à des données qui ne viennent pas de cet outil (CRM, export publicitaire).
Un premier tableau par canal
sessions["channel"] = [channel_group(s, m) for s, m in zip(sessions["source"], sessions["medium"])]
by_channel = sessions.groupby("channel").agg(
sessions=("converted", "size"),
conversions=("converted", "sum"),
)
by_channel["conversion_rate"] = by_channel["conversions"] / by_channel["sessions"]
Ce taux est un taux de conversion par session. Si vous le comparez à un taux calculé par utilisateur dans un autre rapport, vous comparerez deux choses différentes. Notez toujours le grain à côté du chiffre.
À retenir
- Identifiez le grain de chaque table avant de calculer.
- Normalisez les valeurs UTM et imposez une convention de nommage.
- Le regroupement en canaux est un jeu de règles ordonnées, documenté et partagé.
Exercices
Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.
Lire les UTM d'une URL
Écrivez
parse_utm(url)qui renvoie un dictionnaire{"source": ..., "medium": ..., "campaign": ...}:- valeurs en minuscules et sans espaces autour ;
- si
utm_sourceest absent ou vide, renvoyez{"source": "(direct)", "medium": "(none)", "campaign": "(not set)"}; - si seul
utm_mediumouutm_campaignmanque, mettez"(not set)"pour la valeur manquante.
Utilisez
urlparseetparse_qs.from urllib.parse import urlparse, parse_qs def parse_utm(url): ...Tableau par canal
Écrivez
channel_group(source, medium)en appliquant, dans cet ordre, les règles de la leçon (Direct, E-mail, Recherche payante, Social payant, Recherche naturelle, Social naturel, Sites référents, sinon Autres).Ajoutez ensuite à
sessionsune colonnechannel, puis construisezby_channel(index = canal) avec les colonnessessions(nombre de lignes),conversions(somme deconverted) etconversion_rate, trié parsessionsdécroissant.import pandas as pd sessions = pd.DataFrame({ "source": ["google", "google", "(direct)", "newsletter", "facebook", "google", "facebook", "blog-partenaire", "(direct)", "google"], "medium": ["cpc", "organic", "(none)", "email", "paid_social", "cpc", "social", "referral", "(none)", "organic"], "converted": [1, 0, 1, 0, 0, 1, 0, 0, 0, 1], }) def channel_group(source, medium): ... # by_channel = ...Une source éclatée
Dans un rapport, la source Facebook apparaît sur trois lignes :
Facebook,facebooketfb. Quelle est la meilleure réponse durable ?- Additionner les trois lignes à la main chaque mois
- Normaliser les valeurs (minuscules, espaces), corriger les alias connus et imposer une convention de nommage pour les futurs liens
- Supprimer les lignes les plus petites
- Passer tout le trafic Facebook en accès direct
Quiz de fin de leçon
Que signifie
utm_medium=cpc?- Une visite issue d'un e-mail
- Une visite issue d'un clic payant
- Une visite directe
Une visite classée
(direct)/(none)provient :- Toujours d'une saisie manuelle de l'adresse
- D'une origine non identifiée : saisie, favori ou lien non marqué
- D'un moteur de recherche
Pourquoi l’ordre des règles de canaux compte-t-il ?
- Parce que la première règle qui s'applique décide du canal
- Parce que pandas trie les règles
- Il ne compte pas
La suite du cours
- Attribution des campagnes : répartir le mérite d'une conversion18 min
- Tunnel de conversion : mesurer les abandons étape par étape18 min
- ROI publicitaire : seuil de rentabilité, incrémentalité et rendement marginal18 min
- Tests A/B de campagnes et tableau de bord marketing18 min