1. Le besoin #
Mesurer, sans traceur ni cookie.
Contraintes #
Ce site voulait connaître ses Core Web Vitals réels sans cookie, sans identifiant et sans service tiers, pour ne pas avoir besoin de consentement pour cette mesure. Le choix : une mesure minimale, agrégée côté serveur, et exposée à Prometheus.
2. Côté navigateur #
PerformanceObserver et sendBeacon.
Le script #
Le script observe les entrées de performance du navigateur, garde la dernière valeur de chaque indicateur, et envoie une seule balise quand la page passe en arrière-plan :
var m = {};
new PerformanceObserver(function (list) {
list.getEntries().forEach(function (e) { m.lcp = Math.round(e.startTime); });
}).observe({ type: 'largest-contentful-paint', buffered: true });
// ... idem pour paint (FCP), layout-shift (CLS), event (INP), navigation (TTFB)
document.addEventListener('visibilitychange', function () {
if (document.visibilityState === 'hidden') {
navigator.sendBeacon('/rum.php', new Blob([JSON.stringify({ p: pageType(), m: m })], { type: 'application/json' }));
}
});Bonne Pratique :sendBeaconest fiable même quand l'utilisateur ferme l'onglet, contrairement à unfetchclassique. Le type de page (accueil, article, leçon...) remplace l'URL : aucune donnée de navigation individuelle.
3. Côté serveur #
Des histogrammes pour Prometheus.
Agrégation et exposition #
Le point d'entrée valide la balise (types et bornes), puis incrémente des compteurs d'histogramme dans Redis (un compteur par seau de durée, par indicateur et par type de page). /metrics les expose au format Prometheus :
rtm_rum_lcp_bucket{page="article",le="2500"} 1834
rtm_rum_lcp_bucket{page="article",le="4000"} 1977
rtm_rum_lcp_bucket{page="article",le="+Inf"} 2010
rtm_rum_lcp_count{page="article"} 2010# LCP au 75e percentile par type de page
histogram_quantile(0.75, sum by (le, page) (rate(rtm_rum_lcp_bucket[1h])))À savoir : Les seaux suivent les seuils des Core Web Vitals (par exemple 2 500 et 4 000 ms pour le LCP). Le CLS, sans unité, est multiplié par 1 000 pour être stocké en entier : un seuil de 0,1 devient 100.
Faro ou RUM minimal ? #
| Besoin | RUM minimal | Faro |
|---|---|---|
| Web Vitals agrégés | Oui | Oui |
| Erreurs JavaScript avec pile | Non | Oui |
| Sessions, événements métier | Non | Oui |
| Traces front vers back | Non | Oui |
| Aucune donnée individuelle | Oui | Configurable |
| Composants à exploiter | Aucun nouveau | Alloy, Loki, Tempo |
Pour un site de contenu, le RUM minimal suffit. Pour une application (tunnel d'achat, espace client), Faro apporte le diagnostic des erreurs et la corrélation avec le back-end.
