Retour au blog

L'INP Pénalise l'Analytics Lourde : Pourquoi Votre Traqueur Est sur le Thread Principal

Interaction to Next Paint est le Core Web Vital que la plupart des sites échouent, et les données de terrain montrent que les scripts de suivi comportemental en sont une cause majeure. La solution : envoyer moins de travail au thread principal.

Interaction to Next Paint (INP) est le Core Web Vital que les développeurs échouent le plus souvent, et la cause se trouve dans votre <head>. L'INP est devenu un Core Web Vital stable en 2024, remplaçant le First Input Delay, et il mesure ce que le FID n'a jamais pu : à quel point une page reste réactive à chaque clic, tap et frappe de touche, pendant toute sa durée de vie.

La métrique est impitoyable envers le type de JavaScript que l'analytics de surveillance embarque. Si votre traqueur effectue un travail conséquent sur le thread principal, chaque interaction de vos utilisateurs hérite de ce coût.

Ce que l'INP Mesure Réellement

L'INP rapporte la latence des interactions au 75e percentile de tous les clics, taps et frappes de touche sur une page. Un score de 200 ms ou moins est « bon » ; de 200 à 500 ms « à améliorer » ; au-delà de 500 ms « mauvais ».

Chaque interaction se décompose en trois phases :

  • Délai d'entrée (input delay) — le temps avant que vos event handlers puissent même démarrer, parce que le thread principal est occupé.
  • Durée de traitement — le temps que mettent les callbacks de vos event handlers à s'exécuter.
  • Délai de présentation (presentation delay) — le temps entre la fin du callback et le moment où le navigateur peint l'image suivante.

L'analytics lourde nuit aux trois phases. Un traqueur qui parse un gros bundle, évalue une logique de consentement, regroupe une file de tag manager ou lit le layout pour construire une empreinte occupe le thread principal exactement quand l'utilisateur tente d'interagir.

Les Tâches Longues Sont le Mécanisme

Le navigateur ne peut pas traiter une interaction pendant qu'une tâche s'exécute. Toute tâche durant plus de 50 ms est une tâche longue, et la portion au-delà de 50 ms est du temps mort pendant lequel les clics s'accumulent dans la file.

Un tag manager qui charge et exécute de façon synchrone une douzaine de scripts de fournisseurs produit une cascade de tâches longues. L'utilisateur clique, rien ne se passe, il reclique — et quand le thread principal se libère enfin, les entrées en file se déclenchent toutes d'un coup.

Ce n'est pas théorique. Le Web Almanac 2024 du HTTP Archive a constaté que les pages embarquant des scripts de comportement utilisateur — session replay, cartes de chaleur, analytics comportementale — n'atteignaient un bon INP que 37 % du temps sur mobile, contre 60 % sur desktop. Les scripts de gestion du consentement, les bannières qu'exigent ces outils, ne passaient l'INP que sur 53 % des pages mobiles. L'instrumentation censée « comprendre les utilisateurs » dégrade activement leur expérience.

L'Architecture Qui l'Évite

La solution est structurelle, pas un interrupteur à activer. Envoyez moins de code et gardez-le hors du chemin critique.

Un traqueur privacy-first peut être assez petit pour que son parsing et son exécution ne comptent jamais comme une tâche longue. Le traqueur de Monoid pèse environ 2 Ko, n'a aucune dépendance, ne pose aucun cookie et ne lit aucun layout — il n'y a donc rien à empreinter ni rien de lourd à exécuter. Il enregistre une page vue avec une seule requête keepalive puis reste inactif :

fetch('/collect', {
  method: 'POST',
  keepalive: true,
  body: JSON.stringify({ site_id, path: location.pathname })
})

keepalive: true permet à la requête de survivre à la page sans retenir le thread principal, de sorte que la navigation et le unload ne sont jamais bloqués en attente d'une balise.

Quand vous exécutez vos propres scripts, cédez le thread principal entre les blocs de travail pour que les interactions en file puissent s'exécuter :

async function processQueue(items) {
  for (const item of items) {
    handle(item)
    if (navigator.scheduling?.isInputPending?.()) {
      await scheduler.yield()
    }
  }
}

scheduler.yield() découpe une tâche longue en morceaux et reprend en priorité, de sorte qu'un script tiers ne puisse pas passer devant votre continuation dans la file.

Mesurez-le sur le Terrain, Pas en Laboratoire

Lighthouse ne peut pas rapporter l'INP, car l'INP n'existe qu'une fois qu'une vraie personne interagit. Les outils de laboratoire estiment ; ils ne mesurent pas la réactivité.

Utilisez les données de terrain. Le Chrome User Experience Report (CrUX) agrège les interactions réelles des utilisateurs Chrome consentants, et le rapport Core Web Vitals de la Search Console expose les mêmes données par groupe d'URL. Si votre INP CrUX est bon mais votre Total Blocking Time de laboratoire élevé, vous avez de la marge ; si l'INP CrUX est mauvais, vos utilisateurs le ressentent déjà.

L'argument de confidentialité et l'argument de performance convergent ici. Un traqueur qui ne lit aucun stockage, ne construit aucune empreinte et n'embarque aucune cascade de fournisseurs n'a presque rien à faire sur le thread principal — et c'est précisément pourquoi il n'apparaît jamais dans votre INP. La surveillance coûte cher en millisecondes, pas seulement en confiance.

Sources

Comments

Loading comments…