Cookie Consent pour Next.js, Gatsby et les sites statiques : guide d’intégration pour développeurs

Le problème du consentement sur les sites statiques

Les frameworks JavaScript modernes comme Next.js, Gatsby et Nuxt.js ont introduit un changement de paradigme dans la façon dont les pages web sont construites et livrées. Les pages sont pré-rendues au moment du build ou sur le serveur, puis hydratées côté client. Cela crée un défi unique pour le cookie consent : la bannière de consentement doit être prête avant l’exécution de tout script de tracking, mais la page elle-même peut déjà être rendue et mise en cache en edge.

Les CMP traditionnels ont été conçus pour des pages PHP rendues côté serveur ou de simples pages HTML où le document se charge linéairement de haut en bas. Dans un monde de frameworks avec découpage de code, chargement paresseux (lazy loading) et rendu côté serveur en streaming, ces hypothèses ne tiennent plus. Obtenir un consentement correct dans ces environnements nécessite de comprendre le pipeline de rendu.

Pourquoi le timing compte plus que vous ne le pensez

Dans une page HTML standard, placer un script de CMP dans le <head> avant les autres scripts est simple. Dans Next.js App Router ou Gatsby, la situation est plus complexe :

Le principe fondamental est le suivant : le consentement doit être établi au niveau des scripts, pas au niveau des composants. Un composant React qui rend une bannière de consentement arrive trop tard s’il ne devient interactif qu’après l’hydratation.

Intégration avec Next.js App Router

Next.js 13+ avec l’App Router a introduit une nouvelle façon de gérer les scripts. Voici l’approche recommandée pour l’intégration du consentement :

Étape 1 : charger le script de CMP dans le layout racine

Utilisez le composant Script de Next.js avec la stratégie beforeInteractive dans votre layout.tsx racine. Cela indique à Next.js d’injecter le script dans le document HTML initial, avant le début de l’hydratation :

La stratégie beforeInteractive est critique. La stratégie par défaut afterInteractive charge les scripts après l’hydratation, ce qui est trop tard pour le consentement. Avec beforeInteractive, le script de CMP est inclus dans le HTML rendu côté serveur et s’exécute au chargement de la page.

Étape 2 : définir le consentement par défaut avant les tags Google

Avant votre snippet Google Tag Manager ou gtag.js, incluez un script inline qui définit les états de consentement par défaut. Cela garantit que même si GTM se charge avant l’apparition de la bannière CMP, il respecte les refus par défaut :

Ce script inline doit être placé dans le <head> de votre layout racine, avant les scripts CMP et GTM. Dans Next.js, vous pouvez utiliser une balise <script> classique à l’intérieur de l’élément <head> de votre layout à cet effet.

Étape 3 : gérer les changements de route

Dans une navigation de type single-page application, le script de CMP se charge une fois, mais les changements de route ne déclenchent pas un rechargement complet de la page. Votre CMP doit persister à travers les navigations côté client. FlexyConsent gère cela automatiquement : une fois chargé, il reste actif sur tous les changements de route sans réinitialisation.

Intégration avec Next.js Pages Router

Pour les projets qui utilisent encore le Pages Router, l’approche est similaire mais utilise _document.tsx au lieu du layout racine. Placez le script de CMP dans le composant <Head> de votre classe Document personnalisée. La stratégie beforeInteractive fonctionne de la même manière dans le Pages Router.

La différence clé est que _document.tsx est rendu uniquement côté serveur, de sorte que toute logique de consentement ici est garantie de se trouver dans le payload HTML initial.

Intégration des sites statiques Gatsby

Gatsby génère un HTML entièrement statique au moment du build. Il n’y a pas de rendu côté serveur à la requête, ce qui simplifie certains aspects mais en complique d’autres :

L’approche de build de Gatsby signifie que chaque fichier HTML sur votre CDN inclura le script de consentement. C’est en réalité idéal : il n’y a aucune logique serveur susceptible d’échouer ou d’être mal mise en cache.

Considérations pour Nuxt.js

Nuxt.js (basé sur Vue) a ses propres patterns. Dans Nuxt 3, utilisez le composable useHead ou la configuration d’app head dans nuxt.config.ts pour ajouter globalement le script de CMP. Nuxt prend en charge une option body: false (qui place les scripts dans le head) et un attribut async pour un chargement non bloquant.

Pour le mode rendu côté serveur de Nuxt, le même principe s’applique : le script de CMP doit se trouver dans la réponse HTML initiale, et non être injecté dynamiquement par un composant Vue après le montage.

Éviter les décalages de mise en page

Les bannières de consentement sont tristement célèbres pour provoquer des Cumulative Layout Shift (CLS), un Core Web Vital qui affecte le classement SEO. Lorsqu’une bannière apparaît après le rendu de la page, elle pousse le contenu vers le bas ou le recouvre de manière inattendue.

Stratégies pour minimiser le CLS causé par les bannières de consentement :

L’approche agnostique de FlexyConsent vis-à-vis des frameworks

FlexyConsent a été conçu pour fonctionner avec n’importe quel framework — ou sans framework — en opérant au niveau des scripts plutôt qu’au niveau des composants. Voici pourquoi cela compte :

Astuce développeur : Le test le plus simple pour vérifier une intégration correcte du CMP consiste à ouvrir l’onglet Réseau de votre navigateur, filtrer par domaines Google, puis recharger la page. Aucune requête Google ne doit partir avant que la commande de consentement par défaut n’apparaisse dans la console. Si c’est le cas, votre CMP se charge trop tard.

Le plan gratuit de FlexyConsent prend en charge un nombre illimité de pages vues et fonctionne avec Next.js, Gatsby, Nuxt, Astro, SvelteKit, Remix et du simple HTML. L’intégration est la même partout : une balise script, correctement placée.

← Blog Tout lire →