Aller au contenu

Langue

Ingénierie5 min de lecture

Gérer le consentement aux cookies dans les applications monopages

Consentement aux cookies dans React, Vue et les autres SPA : état partagé, suivi des changements de route, hydratation SSR, contenus intégrés et retrait immédiat.

Équipe éditoriale CookieshPublié le

Dans une application monopage (SPA), la page n’est jamais entièrement rechargée : le consentement aux cookies doit donc faire partie de l’état de l’application, et non d’un script qui s’exécute une seule fois. Enregistrez le choix du visiteur, partagez-le avec chaque composant, activez ou bloquez les scripts lorsqu’il change, n’envoyez de pages vues lors des changements de route qu’avec un consentement, et faites en sorte que le retrait prenne effet immédiatement plutôt qu’au prochain chargement de page.

Pourquoi le consentement aux cookies est-il plus complexe dans une application monopage ?

La plupart des mécanismes de consentement partent du principe que les pages se chargent entièrement, alors qu’une SPA se charge une fois puis remplace les vues en JavaScript. Quatre hypothèses tombent alors :

  • Les scripts ne se chargent qu’une fois. Si la mesure d’audience a été bloquée au chargement et que le visiteur accepte plus tard, aucun chargement de page ne viendra l’activer. Vous devez l’activer sur place.
  • Les pages vues sont virtuelles. Les changements de route ne rechargent pas la page : votre routeur doit donc signaler les pages vues, et vérifier le consentement au préalable.
  • Les choix changent en cours de session. Un visiteur peut accepter, naviguer, puis retirer son consentement depuis un lien en pied de page alors que des scripts tournent déjà en mémoire.
  • Le rendu serveur ajoute l’hydratation. Avec des frameworks comme Next.js ou Nuxt, le HTML du serveur doit correspondre au premier rendu côté client, mais le serveur ne connaît pas forcément le choix du visiteur.

Comment modéliser l’état du consentement dans une SPA ?

Traitez le consentement comme un petit store que chaque partie de l’application lit, doté d’une méthode d’abonnement pour que les composants et les scripts réagissent aux changements. Réglez par défaut chaque catégorie non essentielle sur refusé, pour que le code exécuté avant le chargement du choix enregistré ne puisse jamais laisser fuiter de données.

// consent-store.ts
export type Category = 'necessary' | 'preferences' | 'analytics' | 'marketing';
export type Consent = Record<Category, boolean>;

export const DENIED: Consent = {
  necessary: true, preferences: false, analytics: false, marketing: false,
};

let state: Consent = DENIED;
const listeners = new Set<() => void>();

export const consentStore = {
  get: (): Consent => state,
  set(next: Partial<Consent>) {
    state = { ...state, ...next, necessary: true };
    listeners.forEach((notify) => notify());
  },
  subscribe(listener: () => void) {
    listeners.add(listener);
    return () => { listeners.delete(listener); };
  },
};

Dans une application réelle, set enregistrerait aussi le choix dans un cookie propriétaire (first-party), le consignerait dans votre journal de consentement et mettrait à jour Google Consent Mode avec gtag('consent', 'update', …). Dans React, useSyncExternalStore relie le store aux composants, et le même hook peut conditionner les contenus intégrés qui déposent des cookies :

// consent.tsx
import { useSyncExternalStore } from 'react';
import { consentStore, DENIED } from './consent-store';

export function useConsent() {
  return useSyncExternalStore(consentStore.subscribe, consentStore.get, () => DENIED);
}

export function VideoEmbed({ videoId }: { videoId: string }) {
  const { marketing } = useConsent();

  if (!marketing) {
    return (
      <div className="embed-placeholder">
        <p>Cette vidéo est hébergée par YouTube, qui peut déposer des cookies marketing.</p>
        <button type="button" onClick={() => consentStore.set({ marketing: true })}>
          Autoriser les cookies marketing et lire la vidéo
        </button>
      </div>
    );
  }

  return (
    <iframe
      src={`https://www.youtube-nocookie.com/embed/${videoId}`}
      title="Vidéo de présentation du produit"
      allowFullScreen
    />
  );
}

Le troisième argument de useSyncExternalStore est l’instantané utilisé pendant le rendu serveur et l’hydratation. Renvoyer DENIED à cet endroit garantit que le serveur et le premier rendu client concordent, et React refait le rendu avec l’état réel juste après l’hydratation. Dans Vue, un composable encapsulant une ref réactive joue le même rôle.

Pour les scripts qui ne sont pas des composants, abonnez-vous directement au store et chargez-les avec un import() dynamique une fois leur catégorie autorisée. Notre guide pour bloquer les scripts jusqu’au consentement présente les modes d’activation.

Comment suivre les changements de route uniquement avec consentement ?

Envoyez une page vue virtuelle depuis le routeur après chaque navigation, et vérifiez le consentement à ce moment-là. Si le visiteur accepte la mesure d’audience en cours de session, il est raisonnable d’enregistrer la page sur laquelle il se trouve, puisque c’est là que commence son opt-in.

import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { useConsent } from './consent';
import { trackPageView } from './analytics';

export function PageViewTracker() {
  const { pathname } = useLocation();
  const { analytics } = useConsent();

  useEffect(() => {
    if (analytics) trackPageView(pathname);
  }, [pathname, analytics]);

  return null;
}

Attention au double comptage. Certains outils de mesure d’audience peuvent envoyer automatiquement des pages vues lors des changements de l’historique du navigateur ; Google Analytics 4 le propose comme option de mesure améliorée. Utilisez soit l’option automatique, soit votre propre tracker, mais pas les deux.

Comment éviter les incohérences d’hydratation et le clignotement du bandeau ?

Déterminez où le choix du visiteur est connu lors du premier rendu. Deux options solides s’offrent à vous :

  • Lire le cookie de consentement sur le serveur. Les cookies sont envoyés avec chaque requête : les pages rendues côté serveur peuvent donc afficher ou omettre correctement le bandeau dès le premier octet. Cela ne fonctionne que si le HTML n’est pas mis en cache et partagé entre visiteurs.
  • Afficher le bandeau uniquement côté client. Pour les pages générées statiquement ou mises en cache sur un CDN, n’affichez rien côté serveur et montrez le bandeau une fois l’application montée. Positionnez-le en superposition fixe pour qu’une apparition tardive ne provoque pas de décalage de mise en page ; voir bandeaux cookies et Core Web Vitals.

Dans les deux cas, le cookie ou l’entrée de stockage qui mémorise le choix est généralement considéré comme nécessaire pour respecter ce choix ; voir ce qui relève d’un cookie strictement nécessaire.

Comment gérer le retrait du consentement en cours de session ?

Rendez le retrait immédiat et aussi simple que le fait de donner son consentement, comme l’exige l’article 7(3) du RGPD. Concrètement, cela suppose un lien permanent « Paramètres des cookies », généralement en pied de page, qui rouvre les préférences sans chargement de page. Lorsqu’un visiteur retire son consentement pour une catégorie :

  1. Mettez à jour le store et enregistrez le nouveau choix.
  2. Si vous utilisez des balises Google, envoyez gtag('consent', 'update', …) avec les signaux concernés réglés sur 'denied'.
  3. Cessez d’appeler les fonctions de suivi ; le code conditionné par le store le fait automatiquement.
  4. Supprimez les cookies propriétaires déposés par la catégorie retirée, lorsque vous connaissez leurs noms et domaines. Vos scripts ne peuvent pas supprimer les cookies déposés sur d’autres domaines.
  5. Rechargez la page si un script retiré est déjà en cours d’exécution. Les bibliothèques conservent des minuteurs, des écouteurs et des identifiants en mémoire, et un rechargement est le seul moyen fiable de les effacer.

Un rechargement après un retrait est un compromis raisonnable : il est rare, et l’alternative consiste à exécuter du code que vous n’avez plus l’autorisation d’exécuter.

En résumé

Dans une SPA, le consentement est un état : refusez par défaut, partagez un store unique, conditionnez-y les scripts et les contenus intégrés, n’envoyez de pages vues qu’avec un consentement et faites prendre effet le retrait immédiatement. Des outils comme Cookiesh peuvent prendre en charge une bonne partie de cette plomberie, avec un SDK React qui fournit CookieshProvider et un hook useConsent(), ainsi qu’un événement consent:updated pour tout le reste.

Cet article est fourni à titre d’information générale et ne constitue pas un avis juridique. Pour toute décision concernant votre situation, consultez un professionnel qualifié de la protection des données.

Questions fréquentes

Faut-il réafficher le bandeau cookies après chaque changement de route ?

Non. Affichez-le jusqu'à ce que le visiteur fasse un choix, enregistrez ce choix et conservez un lien permanent vers les paramètres. Ne redemandez que si vos finalités ou vos fournisseurs changent de façon significative, ou si le choix enregistré expire.

Puis-je stocker le choix de consentement dans le localStorage plutôt que dans un cookie ?

Les deux fonctionnent dans le navigateur, mais un cookie est aussi envoyé à votre serveur avec chaque requête : les pages rendues côté serveur peuvent donc afficher le bon état dès le premier rendu. Le localStorage n'est lisible que par le code côté client, une fois l'application chargée.

Les composants de script des frameworks, comme next/script, gèrent-ils le consentement à ma place ?

Non. Des utilitaires comme le composant Script de Next.js contrôlent le moment où un script se charge par rapport à l'hydratation, pas le fait que le visiteur l'ait accepté ou non. Affichez-les de manière conditionnelle en fonction de votre état de consentement, afin qu'ils ne soient pas ajoutés à la page avant un opt-in.

Sources

  1. Directive 2002/58/EC (ePrivacy Directive), EUR-Lex
  2. Regulation (EU) 2016/679 (GDPR), EUR-Lex
  3. Google : présentation du mode Consentement

Équipe éditoriale Cookiesh

Ingénieurs vie privée et spécialistes de la conformité, nous rédigeons des guides pratiques sur le consentement, les cookies et la protection des données pour les équipes produit.

Des bandeaux cookies conformes en quelques minutes, pas en quelques sprints

Commencez gratuitement sur un domaine. Passez à l'offre supérieure quand il vous faut plus de domaines, le géociblage ou votre propre image de marque.

Sans carte bancaire · Résiliable à tout moment