Cookie Consent per Next.js, Gatsby e siti statici: guida all’integrazione per sviluppatori
Il problema del consenso sui siti statici
I framework JavaScript moderni come Next.js, Gatsby e Nuxt.js hanno introdotto un cambio di paradigma nel modo in cui le pagine web vengono costruite e distribuite. Le pagine vengono pre-renderizzate in fase di build o sul server, quindi idratate sul client. Questo crea una sfida particolare per il cookie consent: il banner di consenso deve essere pronto prima che qualsiasi script di tracciamento venga eseguito, ma la pagina stessa può essere già renderizzata e messa in cache all’edge.
I CMP tradizionali sono stati progettati per pagine PHP renderizzate lato server o per semplici pagine HTML in cui il documento viene caricato linearmente dall’alto verso il basso. Nel mondo dei framework, con code splitting, lazy loading e streaming server-side rendering, queste assunzioni non reggono più. Gestire correttamente il consenso in questi ambienti richiede di comprendere la pipeline di rendering.
Perché il timing conta più di quanto pensi
In una normale pagina HTML, inserire uno script CMP nel <head> prima degli altri script è semplice. In Next.js App Router o Gatsby, la situazione è più complessa:
- L’HTML pre-renderizzato arriva per primo: Il browser riceve HTML completo dal CDN o dal server. Se in quell’HTML sono presenti script inline o tag di terze parti, potrebbero essere eseguiti prima che la tua logica di consenso venga caricata.
- Gap di hydration: L’hydration di React avviene dopo che l’HTML è stato disegnato. Se il tuo componente di consenso è un componente React, non esiste in stato funzionale finché l’hydration non è completata. Durante questo intervallo, i tag Google o gli script di analytics potrebbero attivarsi senza consenso.
- Complicazioni con la cache all’edge: Se utilizzi ISR (Incremental Static Regeneration) o edge functions, l’HTML viene messo in cache. Non puoi iniettare dinamicamente logica dipendente dal consenso in HTML già in cache senza un meccanismo lato client.
Il principio fondamentale è questo: il consenso deve essere gestito a livello di script, non a livello di componente. Un componente React che renderizza un banner di consenso arriva troppo tardi se diventa interattivo solo dopo l’hydration.
Integrazione con Next.js App Router
Next.js 13+ con l’App Router ha introdotto un nuovo modo di gestire gli script. Ecco l’approccio consigliato per integrare il consenso:
Passaggio 1: carica lo script del CMP nel layout root
Usa il componente Script di Next.js con la strategia beforeInteractive nel tuo layout.tsx root. Questo indica a Next.js di iniettare lo script nel documento HTML iniziale, prima che inizi l’hydration:
La strategia beforeInteractive è fondamentale. La strategia predefinita afterInteractive carica gli script dopo l’hydration, che è troppo tardi per il consenso. Con beforeInteractive, lo script del CMP è incluso nell’HTML renderizzato lato server ed eseguito mentre la pagina viene caricata.
Passaggio 2: imposta il consenso predefinito prima dei tag Google
Prima del tuo snippet Google Tag Manager o gtag.js, includi uno script inline che imposta gli stati di consenso predefiniti. Questo garantisce che, anche se GTM viene caricato prima che il banner del CMP appaia, rispetti i valori predefiniti di diniego:
Questo script inline dovrebbe essere inserito nel <head> del tuo layout root, prima degli script CMP e GTM. In Next.js puoi usare un normale tag <script> all’interno dell’elemento <head> del tuo layout per questo scopo.
Passaggio 3: gestisci i cambi di rotta
Nella navigazione single-page, lo script del CMP viene caricato una sola volta, ma i cambi di rotta non innescano un reload completo della pagina. Il tuo CMP deve persistere attraverso le navigazioni lato client. FlexyConsent gestisce questo automaticamente: una volta caricato, rimane attivo su tutti i cambi di rotta senza bisogno di re-inizializzazione.
Integrazione con Next.js Pages Router
Per i progetti che usano ancora il Pages Router, l’approccio è simile ma utilizza _document.tsx invece del layout root. Inserisci lo script del CMP nel componente <Head> della tua classe Document personalizzata. La strategia beforeInteractive funziona allo stesso modo nel Pages Router.
La differenza chiave è che _document.tsx viene renderizzato solo sul server, quindi qualsiasi logica di consenso presente qui è garantita nell’HTML iniziale inviato al client.
Integrazione con siti statici Gatsby
Gatsby genera HTML completamente statico in fase di build. Non c’è rendering lato server al momento della richiesta, il che semplifica alcuni aspetti ma ne complica altri:
- Usa
gatsby-ssr.tsxper iniettare lo script del CMP nel<head>di ogni pagina. L’APIonRenderBodyti permette di aggiungere script all’head che saranno presenti in ogni file HTML statico. - Evita i plugin Gatsby che caricano il consenso in lazy loading: Alcuni plugin della community incapsulano il consenso in componenti React che vengono montati solo dopo l’hydration. Questo crea il gap di timing descritto in precedenza.
- Imposta i valori di consenso inline: Usa
setHeadComponentsingatsby-ssr.tsxper aggiungere uno script inline che imposta gli stati di consenso predefiniti. Questo script sarà presente nell’HTML statico ed eseguito immediatamente.
L’approccio di Gatsby basato sulla build fa sì che ogni file HTML sul tuo CDN includa lo script di consenso. Questo è in realtà ideale: non c’è logica lato server che possa fallire o essere messa in cache in modo errato.
Considerazioni per Nuxt.js
Nuxt.js (basato su Vue) ha i suoi pattern specifici. In Nuxt 3, utilizza la composable useHead o la configurazione dell’head dell’app in nuxt.config.ts per aggiungere globalmente lo script del CMP. Nuxt supporta l’opzione body: false (che posiziona gli script nell’head) e l���attributo async per un caricamento non bloccante.
Per la modalità server-side rendering di Nuxt, vale lo stesso principio: lo script del CMP deve essere presente nella risposta HTML iniziale, non iniettato dinamicamente da un componente Vue dopo il mount.
Evitare il layout shift
I banner di consenso sono famigerati per causare Cumulative Layout Shift (CLS), una Core Web Vital che influisce sul posizionamento SEO. Quando un banner compare dopo il rendering della pagina, spinge il contenuto verso il basso o lo sovrappone in modo inatteso.
Strategie per ridurre al minimo il CLS causato dai banner di consenso:
- Usa un banner posizionato in basso: I banner in fondo alla viewport non spostano il contenuto della pagina. È l’approccio più compatibile con il CLS.
- Riserva spazio: Se devi usare un banner in alto, riserva lo spazio verticale nel tuo CSS in modo che il layout della pagina tenga conto del banner prima che venga renderizzato.
- Evita overlay modali al caricamento: I wall di consenso a schermo intero che compaiono dopo il rendering della pagina causano una forte percezione di instabilità del layout. Se hai bisogno di un wall, renderizzalo come parte dello stato iniziale della pagina.
- Carica il CMP in modo sincrono nell’head: Quando il CMP viene caricato come script bloccante nel head, il banner può apparire come parte del paint iniziale invece di comparire in un secondo momento.
L’approccio framework-agnostico di FlexyConsent
FlexyConsent è stato progettato per funzionare con qualsiasi framework — o senza framework — operando a livello di script anziché a livello di componente. Ecco perché questo è importante:
- Un singolo tag script async: È sufficiente un solo tag
<script>nel<head>. Nessun pacchetto npm da installare, nessun wrapper specifico per framework, nessuna configurazione di build. - I valori di consenso predefiniti vengono impostati immediatamente: Lo script imposta i default di Consent Mode V2 come prima azione, prima di qualsiasi callback o manipolazione del DOM. Questo significa che i tag Google rispettano il consenso fin dal primo millisecondo.
- Nessuna dipendenza dal DOM: La logica di consenso non aspetta che React, Vue o Svelte completino l’hydration. Funziona in modo indipendente dal ciclo di vita del framework.
- Funziona con SSG, SSR, ISR e CSR: Poiché è un semplice script, si comporta allo stesso modo indipendentemente dal fatto che la pagina sia stata generata staticamente, renderizzata lato server, rigenerata in modo incrementale o renderizzata lato client.
Consiglio per sviluppatori: Il test più semplice per verificare una corretta integrazione del CMP è aprire il pannello Network del browser, filtrare per domini Google e ricaricare la pagina. Nessuna richiesta verso Google dovrebbe partire prima che il comando di default del consenso compaia nella console. Se succede, il tuo CMP viene caricato troppo tardi.
Il piano gratuito di FlexyConsent supporta pageview illimitate e funziona con Next.js, Gatsby, Nuxt, Astro, SvelteKit, Remix e semplice HTML. L’integrazione è la stessa per tutti: un solo tag script, posizionato correttamente.