optimisation core web vitals 7 min

Scripts Sarbacane et Core Web Vitals : l'impact caché des trackers

Tu suis tes campagnes email avec Sarbacane, mais sais-tu ce que son script de tracking fait à ton LCP ? On a mesuré l'impact, la réponse fait mal.

Par Julien Morel
Partager

On a vu un site e-commerce perdre 8 points de Performance Score Lighthouse du jour au lendemain. Le seul changement déployé la veille : l’équipe marketing avait branché le script de tracking Sarbacane en placement head, sans attribut async ni defer.

Le pire, c’est que personne ne l’avait vu venir. Le script faisait 43 Ko, rien de monstrueux. Mais chargé en synchrone avant le moindre élément visible de la page, il retardait le First Contentful Paint de 620ms sur une connexion 4G throttlée. Le LCP, lui, prenait 1,1 seconde dans les dents. La PLP passait de “vert” à “orange” dans la Search Console. Et le trafic organique a commencé à s’éroder deux semaines plus tard.

Le sujet n’est pas Sarbacane en particulier. C’est la famille entière des scripts de tracking marketing qu’on branche sur un site sans audit de performance, comme si un kilo-octet de plus ou de moins n’avait jamais changé un classement Google. L’angle mort est massif parce que les équipes marketing et les équipes dev ne parlent pas la même langue sur ce dossier. Les premières veulent des données de campagne fiables. Les secondes veulent un LCP sous 2,5 secondes. Les deux ont raison. Mais quelqu’un doit poser la question du compromis acceptable.

Un script Sarbacane pèse quoi, concrètement ?

On a fait le test sur une fiche produit type, Next.js 14, déployée sur Vercel, avec le script Sarbacane intégré de trois manières différentes : en head bloquant, en head avec async, et en fin de body avec defer. Les mesures sont prises en throttled 4G via WebPageTest, médiane sur 5 runs.

Le script de base pèse 47 Ko transférés (148 Ko décompressés). Il initialise une session de tracking, pose un cookie visiteur, et enregistre un événement de page vue. Temps d’exécution JS médian : 38ms. Jusque-là, rien qui fasse trembler un rapport Lighthouse.

Ce qui change tout, c’est la cascade réseau. En head bloquant, le navigateur télécharge et exécute ce script avant de parser le moindre <h1> ou <img> de la page. Résultat : un délai de 510ms avant le premier octet de contenu visible, mesuré sur une connexion avec 150ms de RTT. Le LCP passe de 1,8s à 2,7s. La note Lighthouse chute de 92 à 78.

Avec async, le script ne bloque pas le parser HTML. Le LCP reste à 1,9s. Mais l’événement de page vue est parfois déclenché après que l’utilisateur a déjà commencé à scroller, ce qui fausse les métriques de temps passé. Les marketeurs détestent ça.

La vraie solution, c’est defer placé en fin de document. Le script s’exécute après le DOM complet mais avant DOMContentLoaded. Le LCP tient à 1,85s. Les données de tracking sont fiables. Il faut juste accepter que la mesure d’impression arrive 200ms plus tard que la vérité terrain. Sur un site e-commerce, c’est négligeable.

Pourquoi les audits Lighthouse ne voient pas le problème

Lighthouse simule un chargement isolé. Une page, un cache vide, une connexion throttlée. Mais Lighthouse ne simule pas les dizaines de scripts tiers qui s’empilent dans la vraie vie : le pixel Meta, le tag LinkedIn, le script Sarbacane, le widget de chat Intercom ou Crisp, le GTM qui en injecte trois autres.

Chaque script pris isolément est inoffensif. Ensemble, ils créent une congestion du thread principal que Lighthouse ne modélise pas. L’outil te donne un score à 95, tu te félicites, et tes utilisateurs réels subissent un LCP à 3,4 secondes parce que six scripts se battent pour parser 12 Ko de JSON-LD.

La Search Console le voit, elle. Le rapport Core Web Vitals s’appuie sur les données du Chrome User Experience Report, donc sur de vraies sessions utilisateur avec tous les scripts actifs. Si ta régie pub ou ton outil emailing injecte un script qui retarde le LCP de 400ms, la Search Console te le renverra dans les dents sous forme d’URLs en “amélioration nécessaire”. Mais elle ne te dira pas quel script est responsable.

📌 À retenir : Un script marketing n’est jamais inoffensif parce qu’il est “petit”. C’est sa position dans la cascade réseau et son interaction avec les autres scripts qui déterminent l’impact réel.

Le seul moyen fiable de le mesurer, c’est de faire un diff avant/après sur WebPageTest avec le script activé et désactivé, en simulant une latence réseau réaliste (pas “Fast 3G”, qui est une fiction de labo). On fait le test, on compare les waterfall charts, on identifie le point de blocage. C’est fastidieux mais ça ne prend pas plus de vingt minutes si on a les bons outils ouverts.

INP : le piège que personne n’anticipe

L’Interaction to Next Paint est entrée dans les Core Web Vitals en mars 2024. Depuis, beaucoup d’attention s’est portée sur les bundles JS applicatifs, les fonctions de callback lourdes, les calculs de layout intempestifs. Le tracking email, lui, est resté sous les radars.

Le problème survient quand un script marketing ne se contente pas de pousser un événement vers une API. Certaines configurations Sarbacane injectent des éléments dans le DOM : un bandeau de consentement cookie, un popup de campagne, un formulaire d’inscription newsletter. Ces injections déclenchent un recalcul de layout complet. Si l’utilisateur clique au même moment, le navigateur met 200 à 400ms à répondre parce que le thread principal est occupé à repeindre la page.

On a reproduit le scénario sur une page listing avec 48 fiches produits. Le script Sarbacane injectait un popup après 3 secondes d’inactivité. Pile au moment où l’utilisateur clique sur un filtre de catégorie. Résultat : un INP à 380ms ce jour-là, et une URL classée en “médiocre” dans la Search Console le surlendemain.

La correction n’est pas technique au sens lourd. Elle est architecturale. Il faut sortir l’injection DOM du thread critique. Soit en planifiant le popup avec requestIdleCallback pour qu’il ne s’exécute que quand le navigateur a du temps libre. Soit en déportant l’affichage dans un Web Worker léger qui ne bloque pas le thread principal. La seconde option demande un peu plus de code mais elle garantit un INP stable même avec trois campagnes actives simultanément.

Comment garder Sarbacane sans plomber tes scores

La tentation, c’est de supprimer le script. Le marketing hurle, le trafic organique remonte, tout le monde est malheureux sauf le dev qui a gagné son combat. Ce n’est pas une stratégie, c’est une impasse politique.

La méthode qu’on applique chez nos clients, c’est un processus en trois étapes. D’abord, auditer la position et l’attribut de chargement de chaque script tiers. Un script de tracking email n’a rien à faire en <head> bloquant. Il doit être en defer en fin de body, ou poussé via un tag manager avec un déclenchement sur window.loaded.

Ensuite, négocier la priorité réseau. L’attribut fetchpriority="low" sur la balise <script> indique au navigateur que ce fichier peut attendre que les images LCP et les fonts critiques soient chargées. Sarbacane le supporte sans broncher parce que son endpoint de tracking est insensible à une latence de 300ms supplémentaires.

Enfin, isoler les injections DOM dans des microtâches non bloquantes. Si le script doit afficher un élément visuel, on le fait dans un container réservé, en dehors du flux principal, avec un position: fixed qui ne déclenche pas de recalcul de layout global. L’utilisateur voit le popup. L’INP reste sous 200ms. Personne ne crie.

Le coût de mise en place est d’environ une demi-journée de dev front. Le gain, c’est un LCP stabilisé sous 2,5 secondes et un rapport Core Web Vitals qui ne te réveille plus à 3h du matin. Accessoirement, c’est aussi un sujet de performance web qui dépasse le seul cadre des outils d’emailing.

Pousser l’audit côté serveur avec un log forwarder

Quand on a optimisé le chargement côté client, il reste une question : est-ce que le script Sarbacane génère des erreurs réseau silencieuses qu’on ne voit jamais ? Un appel fetch vers l’endpoint de tracking qui échoue en 404, un timeout DNS sur le CDN de l’outil, une réponse 503 intermittente. Rien de visible dans le navigateur. Aucun impact direct sur le LCP. Mais des données de campagne incomplètes qui faussent les décisions marketing.

La parade, c’est un log forwarder côté serveur qui capture les appels sortants vers les domaines de tracking. Un middleware Express ou un edge handler qui loggue chaque requête vers *.sarbacane.com, son code de statut, sa latence. En quinze lignes de configuration, on obtient un dashboard Grafana qui montre la santé réelle des intégrations tierces.

On a mis ça en place sur un projet récent après avoir découvert que 12% des événements de page vue Sarbacane étaient perdus à cause d’un CDN régional qui plantait entre 10h et 14h. Le support Sarbacane n’avait rien détecté. Sans ce log forwarder, on serait restés aveugles pendant des semaines. La démarche s’apparente à ce qu’on ferait pour auditer les accès API d’un IDE comme Cursor : si tu ne loggues pas, tu ne sais pas ce que tu perds.

La couche consentement complique tout

Le tracking email est soumis au consentement RGPD. Si le visiteur refuse les cookies, le script Sarbacane ne doit pas se charger du tout. Pas de defer, pas de fetchpriority, pas de chargement conditionnel. Juste rien.

Beaucoup de CMP (plateformes de gestion du consentement) implémentent ça en chargeant le script puis en le désactivant après coup via un flag JavaScript. C’est la pire approche possible : le fichier est téléchargé, le parser l’exécute, le thread principal trinque, et les données sont quand même jetées. Un chargement inutile et coûteux.

La bonne pratique, c’est de conditionner l’injection même de la balise <script> au statut de consentement. Si le visiteur n’a pas encore fait son choix, on ne charge rien. S’il refuse, on ne charge rien. S’il accepte, on injecte dynamiquement le script avec defer et fetchpriority="low". Le gain est double : pas de chargement superflu pour les utilisateurs opt-out, et un LCP préservé pour tout le monde.

Le code est trivial. Un petit écouteur sur l’événement de consentement de ta CMP, une fonction qui crée l’élément script et l’ajoute au DOM, et basta. Moins de quinze lignes, zéro impact sur le bundle applicatif.

⚠️ Attention : Si ta CMP elle-même charge un script lourd en bloquant avant le LCP, tu as déplacé le problème sans le résoudre. Audite ta CMP avec la même rigueur que le reste.

Cette logique de chargement conditionnel rejoint ce qu’on préconise pour les librairies de state management comme Zustand : ne charge que ce dont l’utilisateur a besoin, quand il en a besoin. Le code mort coûte plus cher en performance qu’en kilo-octets.

Questions fréquentes

Est-ce que Sarbacane propose un mode de chargement optimisé pour la performance web ?

Sarbacane fournit un script standard qui n’est pas spécifiquement profilé pour les Core Web Vitals. L’équipe support confirme que les attributs defer et async sont supportés sans perte de données de tracking, à condition que l’événement de page vue soit appelé après le chargement complet du DOM. C’est au développeur de le configurer.

Un script de tracking email peut-il vraiment faire la différence entre un LCP “vert” et “orange” dans la Search Console ?

Oui, si le script est en head bloquant et que le site est déjà proche du seuil de 2,5 secondes. 400ms de délai supplémentaire peuvent faire basculer une URL de “bonne” à “amélioration nécessaire” dans le rapport Core Web Vitals. La Search Console ne pardonne rien sur les seuils.

Comment surveiller l’impact des scripts Sarbacane dans la durée sans refaire un audit manuel chaque mois ?

La meilleure approche combine deux outils : un monitoring synthétique (WebPageTest en API, programmé en cron toutes les semaines) avec deux configurations (script activé / script désactivé), et un suivi du rapport Core Web Vitals dans la Search Console filtré par segment d’URLs. Si le LCP médian dérive de plus de 200ms d’une semaine à l’autre, il faut chercher quel script tiers a changé.

Articles similaires

Julien Morel

Julien Morel

Ancien dev front React passé SEO technique après une migration e-commerce qui a fait perdre 60% du trafic organique à son employeur en une nuit (fichier robots.txt oublié en staging). Depuis, il écrit pour que ça n'arrive à personne d'autre et teste sur ses propres side-projects avant de publier quoi que ce soit.

Cet article est publie a titre informatif. Faites vos propres recherches avant toute decision.