Empêchez Coralogix RUM de voler votre réseau en début de chargement

Coralogix RUM envoie des balises pendant le chargement et vole le réseau de votre propre LCP. Mettez les événements en mémoire tampon et envoyez-les lors du masquage de la page à la place.

Arjen Karel Core Web Vitals Consultant
Arjen Karel - linkedin
Last update: 2026-06-06

Empêchez Coralogix RUM de voler votre réseau en début de chargement

Un outil de RUM a une seule mission : mesurer l'expérience que vivent réellement vos utilisateurs. Coralogix fait l'inverse pendant le chargement. Il commence à émettre des balises dès l'appel à init. Si cet appel se trouve dans votre bundle principal, le SDK envoie son premier lot dans la fenêtre de chargement et d'hydratation, volant du réseau au LCP même qu'il est censé mesurer. 

L'outil dégrade d'abord la métrique, puis la remonte. C'est un non-sens. J'ai donc écrit un contournement qui met les données en mémoire tampon et les envoie à l'API Coralogix quand on quitte la page (comme le fait Core/Dash par défaut – si vous cherchez un meilleur outil RUM, pensez à changer).

Coralogix se croit plus important que votre page

Regardez avec quoi ce beacon est en concurrence. Votre image principale. Vos polices. Le script qui hydrate la page. Avec la fibre, vous ne le remarquerez peut-être jamais. Mais vos utilisateurs ne sont pas tous sur la fibre. Sur mobile, dans le train ou sur le wifi d'un hôtel, la bande passante est rare. Ce beacon dispute cette ressource à votre propre contenu. Les visiteurs ayant les pires connexions s'en apercevront. Et pour quoi ?

Et voici ce qui devrait vous déranger : ces données précoces n'ont aucune utilité. Aucune. Elles ne concernent qu'une visite en cours. Personne ne les lit en direct (et si c'était le cas, ce serait assez glauque). Elles peuvent rester en mémoire et partir à la fin de la visite, ce qui ne coûte rien et ne perd rien. Les envoyer pendant le chargement n'apporte que des inconvénients. Cela ne fait que ralentir la page, sans rien vous apporter. C'est stupide. Alors reprenez le contrôle : capturez chaque événement, n'en envoyez aucun avant la fin de la visite.

corelogix network and main thread

Bon, assez râlé. Place à la correction. Voici comment faire fonctionner Coralogix correctement !

Mettre tout en mémoire tampon, ne rien envoyer

Coralogix fournit un hook beforeSend. Renvoyez l'événement pour l'envoyer. Renvoyez null pour l'ignorer. Ajoutez donc d'abord l'événement à un tableau, puis renvoyez null. Chaque événement est capturé, rien ne passe sur le réseau.

import { CoralogixRum } from '@coralogix/browser';

const PUBLIC_KEY = '<YOUR_PUBLIC_KEY>';
const APPLICATION = 'my-app';

// Capture chaque événement, n'en envoie aucun en direct.
const buffer = [];

CoralogixRum.init({
  public_key: PUBLIC_KEY,
  application: APPLICATION,
  version: '1.0.0',
  coralogixDomain: 'EU1',
  beforeSend: (event) => {
    buffer.push({ event, t: Date.now() }); // horodatage immédiat, envoi différé
    return null;                           // supprime le beacon natif du SDK
  },
});

J'ai vérifié que cela capture tout ce qui compte, car la documentation présente beforeSend comme un filtre réservé aux erreurs. Ce n'est pas le cas. Il se déclenche pour chaque type d'événement : le snapshot d'initialisation, le resource timing, chaque web vital, les interactions utilisateur et les erreurs. Le SDK continue de faire son vrai travail, à savoir mesurer toute la page. Il reste simplement silencieux sur le réseau jusqu'à ce que vous lui demandiez de vider le tampon.

Vider le tampon au moment de partir

Envoyez maintenant le tampon lorsque la page est masquée. C'est là que la version naïve échoue. Vous pensez à utiliser navigator.sendBeacon, car c'est la méthode classique pour envoyer des données lors de l'événement unload. Mais cela ne fonctionne pas ici. L'ingress s'authentifie avec un en-tête Authorization: Bearer, et sendBeacon ne permet pas de définir des en-têtes de requête. Il renvoie true et échoue en silence avec une erreur 403. Utilisez plutôt fetch avec l'option keepalive. Il survit à l'événement unload de la même manière, tout en vous permettant de définir l'en-tête.

Autre chose que le beacon vous cachait : l'ingress n'accepte pas les événements bruts. Le SDK enveloppe chaque événement dans un span et publie { logs: [...] }. Reconstruisez donc ce format avant l'envoi.

const INGRESS = 'https://ingress.eu1.rum-ingress-coralogix.com/browser/v1beta/logs';
// remplacez eu1 par votre région (us1, us2, eu2, ap1...) pour correspondre à coralogixDomain

// L'ingress attend le format span du SDK, pas les événements bruts. Reconstruisez-le.
function toCxSpan({ event, t }) {
  const hasStack = !!(event.error_context
    && event.error_context.original_stacktrace
    && event.error_context.original_stacktrace.length);

  return {
    version_metadata: event.version_metadata,
    applicationName: APPLICATION,
    subsystemName: 'cx_rum',
    severity: (event.event_context && event.event_context.severity) || 3,
    isErrorWithStacktrace: hasStack,
    timestamp: t,
    text: { cx_rum: Object.assign({}, event, { timestamp: t }) },
  };
}

function flush() {
  if (!buffer.length) return;
  const logs = buffer.splice(0).map(toCxSpan); // vide le tampon : un second appel n'enverra rien

  fetch(INGRESS, {
    method: 'POST',
    keepalive: true, // survit à l'unload et, contrairement à sendBeacon, permet de définir des en-têtes
    headers: {
      'Authorization': 'Bearer ' + PUBLIC_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ logs, skip_enrichment_with_ip: false }),
  }).catch(function () {});
}

document.addEventListener('visibilitychange', function () {
  if (document.visibilityState === 'hidden') flush();
});
window.addEventListener('pagehide', flush);

splice vide le tampon, ainsi un second événement de masquage n'enverra rien. visibilitychange vers la valeur hidden est le signal fiable, même sur mobile où unload ne se déclenche jamais. pagehide sert de filet de sécurité. Une mise en garde : keepalive partage un budget de 64 Ko entre toutes les requêtes en cours. Une longue session qui met en mémoire tampon des milliers d'entrées de ressources peut donc le dépasser. Si vous collectez beaucoup de données, découpez le tableau logs en plusieurs envois plus petits.

Ce que cela coûte

Vous reconstruisez maintenant le format de Coralogix à la main, soyez prudent ! Le session_context est un peu plus limité que celui du SDK. Coralogix renseigne l'identifiant de session, le user agent et l'appareil après le passage dans beforeSend. Vos spans construits à la main contiennent donc moins de détails qu'un beacon standard. Pour capturer les Core Web Vitals, cela n'a pas d'importance. Pour des analyses de session approfondies, cela peut avoir un impact. Et vérifiez bien que vous obtenez un code 200 dans votre onglet Réseau lors du premier déploiement. Une mauvaise clé ou une règle CORS durcie échouera en silence, tout comme le faisait le beacon d'origine.

Si maintenir un format d'échange que vous ne contrôlez pas vous semble pénible, l'alternative radicale consiste à différer CoralogixRum.init() après l'hydratation, puis à laisser le SDK envoyer ses données normalement. Vous perdez les métriques de chargement antérieures à l'initialisation, mais vous préservez votre santé mentale. Choisissez votre compromis.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

J'ai construit CoreDash pour mes propres audits.

Moins de 1KB. Hosting EU. Sans bannière cookies. Et maintenant MCP intégré.

Essayez CoreDash gratuitement
Empêchez Coralogix RUM de voler votre réseau en début de chargementCore Web Vitals Empêchez Coralogix RUM de voler votre réseau en début de chargement