1. Qu’est-ce qu’un tunnel de conversion ? #
La notion et son vocabulaire.
Le principe #
Un tunnel de conversion (funnel) suit les étapes d'un parcours attendu, par exemple fiche produit, panier, paiement, commande, et compte combien de sessions atteignent chacune. Il répond à une question simple : où les utilisateurs abandonnent-ils ?
Le RUM (Real User Monitoring) est une source idéale : il voit les vraies sessions, dans le vrai navigateur, avec leurs erreurs et leurs lenteurs. Un tunnel RUM ne dit pas seulement combien abandonnent, il aide à comprendre pourquoi.
Le vocabulaire #
| Terme | Définition |
|---|---|
| Étape | Un événement observable : une page vue, un clic, un événement métier |
| Taux d’étape | Sessions de l’étape ÷ sessions de l’étape précédente |
| Conversion globale | Sessions de la dernière étape ÷ sessions de la première |
| Abandon | 1 − taux d’étape : la part perdue entre deux étapes |
| Unité | Ce que l’on compte : session (le plus courant en RUM) ou utilisateur |
| Fenêtre | La période dans laquelle les étapes doivent avoir lieu |
2. Bien construire son tunnel #
Les choix qui changent les chiffres.
L’ordre des étapes #
Beaucoup d'outils ne vérifient pas l'ordre : une session qui a réalisé toutes les étapes, dans n'importe quel ordre, est comptée. La documentation de Dynatrace le dit pour USQL FUNNEL, celle de New Relic pour funnel(). Nous l'avons vérifié sur Loki avec la requête de la partie 3 : une session qui paie avant de voir le produit est comptée jusqu'au bout.
Pour un parcours linéaire (panier puis paiement), l'écart est faible. Pour des étapes qui peuvent se répéter ou s'inverser, préférez un outil qui impose l'ordre, comme les funnels de Datadog.
Les bonnes pratiques #
- 3 à 6 étapes, chacune liée à une décision de l'utilisateur. Au-delà, le tunnel devient illisible.
- Des noms d'événements stables :
ajout_panierpartout, jamaisaddToCartsur une page etpanier_ajoutailleurs. - Compter des sessions distinctes, pas des événements : un utilisateur qui recharge la page ne doit pas gonfler une étape.
- Segmenter : navigateur, appareil, pays, version de l'application. Une chute concentrée sur Safari mobile pointe vers un bug, pas vers le prix.
- Croiser avec la technique : erreurs JavaScript, temps de chargement et Core Web Vitals des pages où l'on abandonne.
- Protéger les données : jamais d'e-mail, de nom ou de montant précis par client dans les attributs d'événements.
3. Grafana Faro #
Événements Faro et requêtes LogQL.
Instrumenter les étapes #
Faro n'a pas d'écran de tunnel : on le construit avec des événements, envoyés par pushEvent et stockés dans Loki avec le label kind=event.
// Une étape = un événement nommé, toujours avec les mêmes noms
faro.api.pushEvent('vue_produit', { produit: 'casque-x' });
faro.api.pushEvent('ajout_panier', { produit: 'casque-x', quantite: '1' });
faro.api.pushEvent('paiement', { moyen: 'carte' });
// Deux événements identiques à la suite sont dédupliqués par Faro :
faro.api.pushEvent('ajout_panier', { produit: 'casque-x' }, undefined, { skipDedupe: true });Compter chaque étape en LogQL #
Sessions distinctes ayant vu un produit :
count(
sum by (session_id) (count_over_time({app_name="boutique", kind="event"} | logfmt | event_name="vue_produit" [24h]))
)Sessions ayant vu un produit et ajouté au panier : l'opérateur and ne garde que les sessions présentes dans les deux résultats.
count(
sum by (session_id) (count_over_time({app_name="boutique", kind="event"} | logfmt | event_name="vue_produit" [24h]))
and
sum by (session_id) (count_over_time({app_name="boutique", kind="event"} | logfmt | event_name="ajout_panier" [24h]))
)Troisième étape :
count(
sum by (session_id) (count_over_time({app_name="boutique", kind="event"} | logfmt | event_name="vue_produit" [24h]))
and
sum by (session_id) (count_over_time({app_name="boutique", kind="event"} | logfmt | event_name="ajout_panier" [24h]))
and
sum by (session_id) (count_over_time({app_name="boutique", kind="event"} | logfmt | event_name="paiement" [24h]))
)| Requête | Résultat du test |
|---|---|
| Produit | 4 |
| Produit et panier | 3 |
| Produit, panier et paiement | 2 (dont une session qui a payé en premier) |
Le piège du simple comptage. sum by (event_name) (count_over_time(...)) donnait 4 ajouts au panier pour 4 fiches produit : une session avait ajouté au panier sans passer par la fiche. Comptez des sessions qui ont franchi les étapes précédentes, pas des événements.Dans Grafana, placez chaque requête dans un panneau Bar gauge ou Stat, une requête par étape, pour obtenir un tunnel lisible. Ces requêtes ont été testées sur Loki 3.7.9.
4. Dynatrace #
Objectifs de conversion, USQL et DQL.
RUM Classic : USQL FUNNEL #
Avec le RUM Classic, déclarez d'abord des objectifs de conversion (conversion goals) sur l'application, puis utilisez la fonction FUNNEL du langage USQL :
SELECT FUNNEL(
useraction.name = "AppStart (easyTravel)" AS "Ouverture",
useraction.name = "searchJourney" AS "Recherche",
useraction.name = "bookJourney" AS "Réservation",
useraction.matchingConversionGoals = "Payment" AS "Payé")
FROM usersession
WHERE stringProperties.memberstatus = "GOLD"- 10 conditions au maximum.
- Pas de
GROUP BY,ORDER BYniLIMIT. - L'ordre n'est pas garanti : la documentation précise que rien n'assure que la première action précède la seconde.
Couplé à Session Replay, le tunnel permet de revoir les sessions qui abandonnent à une étape.
Nouvelle expérience RUM : DQL #
Sur la plateforme Grail, les données RUM sont dans la table user.events, interrogée en DQL. La documentation montre comment compter les sessions par page :
fetch user.events
| filter characteristics.has_navigation
| summarize sessions = countDistinct(dt.rum.session.id), by: {view = view.url.path}
| sort sessions descSur ce modèle, un tunnel se construit en deux agrégations : d'abord une ligne par session avec le nombre de passages par étape, puis le décompte des sessions qui ont franchi chaque étape et les précédentes.
fetch user.events, from: now() - 7d
| filter characteristics.has_navigation
| summarize {
produit = countIf(view.url.path == "/produit"),
panier = countIf(view.url.path == "/panier"),
paiement = countIf(view.url.path == "/paiement")
}, by: {dt.rum.session.id}
| summarize {
`1. Produit` = countIf(produit > 0),
`2. Panier` = countIf(produit > 0 and panier > 0),
`3. Paiement` = countIf(produit > 0 and panier > 0 and paiement > 0)
}À valider sur votre environnement. Les champs viennent de la documentation de la nouvelle expérience RUM, encore en évolution ; nous n'avons pas pu exécuter cette requête. Adaptez les chemins de pages à votre application.
5. Datadog et New Relic #
Deux autres approches.
Datadog #
Datadog propose un écran dédié, Digital Experience > Product Analytics > Funnels : on choisit une vue ou une action de départ, puis on ajoute des étapes avec le bouton +. Les actions qui ont lieu entre deux étapes n'influencent pas les taux. Les requêtes d'un tunnel peuvent être reprises dans un moniteur RUM pour alerter sur une chute du taux de conversion.
New Relic #
FROM PageView
SELECT funnel(session,
WHERE pageUrl LIKE '%browse%' AS 'Browse',
WHERE pageUrl LIKE '%cart%' AS 'Cart',
WHERE pageUrl LIKE '%checkout%' AS 'Checkout')
SINCE 1 week AGO- Un seul attribut de regroupement par requête (
sessionici). - 10 étapes au maximum ; résultats approximatifs au-delà de 256 valeurs distinctes.
- L'ordre n'est pas imposé : la première étape vaut toujours 100 %.
En résumé #
| Outil | Construction | Ordre des étapes |
|---|---|---|
| Grafana Faro | pushEvent + LogQL dans Grafana | Non vérifié |
| Dynatrace (Classic) | Objectifs de conversion + USQL FUNNEL | Non garanti |
| Dynatrace (nouveau RUM) | DQL sur user.events | À construire dans la requête |
| Datadog | Écran Funnels, alertes | Étapes successives |
| New Relic | NRQL funnel() | Non imposé |
