← Retour au blog

Ajouter des Analytics Respectueux de la Vie Privée à une App SvelteKit

SvelteKit 2 intercepte la navigation côté client différemment des autres frameworks. Voici le bon pattern pour suivre les changements de route sans cookies ni bannière de consentement.

SvelteKit 2 casse les intégrations d'analytics qui rattachent la mesure au cycle de vie de la page. Une balise <script> simple se déclenche une seule fois, au premier chargement du document, et jamais plus — toute navigation côté client ultérieure reste donc invisible. Le tracker Monoid évite cela en observant la History API plutôt que le cycle de vie de la page.

Pourquoi une simple balise script ne suffit pas

Une balise <script> dans <svelte:head> s'exécute une fois par chargement de document. Le routeur de SvelteKit 2 remplace le contenu sur place sans décharger le document : rien ne la réexécute. Tout tracker dont le seul déclencheur est DOMContentLoaded ou load signale la route d'entrée puis se tait.

C'est la cause profonde du problème largement signalé où Google Analytics GA4 n'enregistre que le premier pageview au chargement initial dans les applications SvelteKit 2.

Détecter la navigation elle-même est la réponse, et cela ne nécessite aucune intégration spécifique à SvelteKit. Le routeur côté client de SvelteKit met à jour l'URL en appelant history.pushState ; un tracker qui patche history.pushState observe donc chaque changement de route côté client sans s'abonner à $app/navigation ni à aucun hook du framework.

L'approche correcte

Ajoutez le script du tracker Monoid une seule fois dans votre +layout.svelte racine via <svelte:head> :

<svelte:head>
  <script
    async
    src="https://api.monoid.website/tracker.min.js"
    data-site-id="VOTRE_SITE_ID"
  ></script>
</svelte:head>

Le listener DOMContentLoaded du tracker couvre le chargement initial de la page. Pour les navigations côté client suivantes, son patch de history.pushState s'exécute immédiatement après que SvelteKit a mis à jour l'URL : il lit donc le nouveau location.pathname et envoie un pageview par changement de route.

Une réserve à connaître : le patch couvre pushState, pas popstate. Les boutons Précédent et Suivant changent la route sans appeler pushState, et ne produisent donc pas de nouveau pageview actuellement.

Pour vérifier, ouvrez l'onglet Réseau dans DevTools et surveillez les requêtes POST vers /collect. Vous devriez en voir une par changement de route.

Séparer le trafic de staging

Les projets SvelteKit tournent généralement sur localhost en développement. Enregistrez un site séparé et associez son site_id à une variable d'environnement pour que le trafic de développement ne pollue jamais les métriques de production :

<script>
  const siteId = import.meta.env.VITE_MONOID_SITE_ID
</script>

<svelte:head>
  {#if siteId}
    <script
      async
      src="https://api.monoid.website/tracker.min.js"
      data-site-id={siteId}
    ></script>
  {/if}
</svelte:head>

Définissez VITE_MONOID_SITE_ID dans .env.local pour le développement (ou laissez-le non défini pour supprimer le tracking) et dans votre environnement de déploiement pour la production. Le bloc {#if siteId} garantit que le tracker n'est jamais injecté lorsque la variable n'est pas définie.

Ce dont vous n'avez pas besoin

Pas de bannière de consentement aux cookies. Pas de mise à jour de la politique de cookies. Pas de vérification navigator.cookieEnabled. Le point de collecte dérive un hash de visiteur quotidien à partir de l'adresse IP, du User-Agent, d'un secret côté serveur et de la date du jour :

visitor_hash = SHA-256(IP + UA + SALT_SECRET + YYYY-MM-DD)

Le hash se réinitialise toutes les 24 heures et ne peut pas être inversé pour récupérer l'IP ou le User-Agent. Rien n'est stocké sur l'appareil du visiteur. Cela signifie que l'intégration ne déclenche pas les exigences de consentement ePrivacy ou PECR — il n'y a rien à consentir.

Vérification dans le tableau de bord

Après le déploiement, ouvrez votre tableau de bord d'analytics et naviguez entre plusieurs routes sur votre site en production. Chaque navigation devrait produire une nouvelle entrée de pageview avec le chemin correct. Si vous ne voyez qu'une seule entrée quelle que soit la navigation, vérifiez que le script est chargé dans le layout racine et que VITE_MONOID_SITE_ID est défini dans l'environnement de production.

L'adaptateur SvelteKit que vous utilisez (Cloudflare, Vercel, Node, statique) n'affecte pas la collecte d'analytics, car le tracking se produit entièrement dans le navigateur après l'hydratation.

Sources

Comments

Loading comments…