Cookie-samtycke för Next.js, Gatsby och statiska webbplatser: en utvecklarguide för integration
Problemet med samtycke på statiska webbplatser
Moderna JavaScript-ramverk som Next.js, Gatsby och Nuxt.js har inneburit ett paradigmskifte i hur webbsidor byggs och levereras. Sidor förgenereras vid byggtid eller på servern och hydras sedan på klienten. Detta skapar en unik utmaning för cookie-samtycke: samtyckesbannern måste vara redo innan några spårningsskript körs, men själva sidan kan redan vara renderad och cachad vid edge.
Traditionella CMP:er designades för serverrenderad PHP eller enkla HTML-sidor där dokumentet laddas linjärt uppifrån och ned. I en ramverksvärld med code splitting, lazy loading och streaming server-side rendering håller inte dessa antaganden. För att få samtycke rätt i dessa miljöer krävs förståelse för renderingskedjan.
Varför timing är viktigare än du tror
I en vanlig HTML-sida är det enkelt att placera ett CMP-skript i <head> före andra skript. I Next.js App Router eller Gatsby är situationen mer komplex:
- Förgenererad HTML anländer först: Webbläsaren tar emot komplett HTML från CDN eller server. Om några inline-skript eller tredjepartstaggar är inbäddade i den HTML:en kan de köras innan din samtyckeslogik laddas.
- Hydreringsgap: React-hydrering sker efter att HTML:en har målats upp. Om din samtyckeskomponent är en React-komponent existerar den inte i ett funktionellt tillstånd förrän hydreringen är klar. Under detta gap kan Google-taggar eller analys-skript köras utan samtycke.
- Komplikationer med edge-cache: Om du använder ISR (Incremental Static Regeneration) eller edge-funktioner cachas HTML:en. Du kan inte dynamiskt injicera samtyckesberoende logik i cachad HTML utan en klient-sidig mekanism.
Kärnprincipen är denna: samtycke måste etableras på skriptnivå, inte komponentnivå. En React-komponent som renderar en samtyckesbanner är för sen om den bara blir interaktiv efter hydrering.
Integration med Next.js App Router
Next.js 13+ med App Router introducerade ett nytt sätt att hantera skript. Här är det rekommenderade tillvägagångssättet för samtyckesintegration:
Steg 1: Ladda CMP-skriptet i root-layouten
Använd Next.js Script-komponent med strategin beforeInteractive i din root-layout.tsx. Detta talar om för Next.js att injicera skriptet i det initiala HTML-dokumentet, innan hydreringen börjar:
Strategin beforeInteractive är avgörande. Standardstrategin afterInteractive laddar skript efter hydrering, vilket är för sent för samtycke. Med beforeInteractive inkluderas CMP-skriptet i den serverrenderade HTML:en och körs medan sidan laddas.
Steg 2: Sätt standardsamtycke före Google-taggar
Före ditt Google Tag Manager- eller gtag.js-snippet lägger du in ett inline-skript som sätter standardtillstånd för samtycke. Detta säkerställer att även om GTM laddas innan CMP-bannern visas respekterar den nekade standardvärden:
Detta inline-skript ska placeras i <head> i din root-layout, före CMP- och GTM-skripten. I Next.js kan du använda en vanlig <script>-tagg inuti <head>-elementet i din layout för detta ändamål.
Steg 3: Hantera ruttbyten
Vid single-page application-navigering laddas CMP-skriptet en gång, men ruttbyten triggar inte en fullständig sidomladdning. Din CMP måste bestå över klient-sidiga navigeringar. FlexyConsent hanterar detta automatiskt – när det väl är laddat förblir det aktivt över alla ruttbyten utan ominitialisering.
Integration med Next.js Pages Router
För projekt som fortfarande använder Pages Router är tillvägagångssättet liknande men använder _document.tsx i stället för root-layouten. Placera CMP-skriptet i <Head>-komponenten i din anpassade Document-klass. Strategin beforeInteractive fungerar på samma sätt i Pages Router.
Den viktiga skillnaden är att _document.tsx bara renderas på servern, så all samtyckeslogik här är garanterat med i den initiala HTML-payloaden.
Gatsby-integration för statiska webbplatser
Gatsby genererar helt statisk HTML vid byggtid. Det finns ingen server-side rendering vid förfrågan, vilket förenklar vissa aspekter men komplicerar andra:
- Använd
gatsby-ssr.tsxför att injicera CMP-skriptet i<head>på varje sida. API:etonRenderBodylåter dig lägga till skript i head som kommer att finnas i varje statisk HTML-fil. - Undvik Gatsby-plugins som lazy-loadar samtycke: Vissa community-plugins kapslar in samtycke i React-komponenter som bara mountas efter hydrering. Detta skapar timing-gapet som diskuterades tidigare.
- Placera samtyckesstandarder inline: Använd
setHeadComponentsigatsby-ssr.tsxför att lägga till ett inline-skript som sätter standardtillstånd för samtycke. Detta skript kommer att finnas i den statiska HTML:en och köras omedelbart.
Gatsbys byggtidsstrategi innebär att varje HTML-fil på ditt CDN kommer att inkludera samtyckesskriptet. Detta är faktiskt idealiskt – det finns ingen serverlogik som kan fallera eller cacheas felaktigt.
Överväganden för Nuxt.js
Nuxt.js (Vue-baserat) har sina egna mönster. I Nuxt 3 använder du useHead-composable eller appens head-konfiguration i nuxt.config.ts för att lägga till CMP-skriptet globalt. Nuxt stöder ett alternativ body: false (som placerar skript i head) och attributet async för icke-blockerande laddning.
För Nuxts server-side rendering-läge gäller samma princip: CMP-skriptet måste finnas i det initiala HTML-svaret, inte injiceras dynamiskt av en Vue-komponent efter mount.
Att undvika layoutskift
Samtyckesbanners är ökända för att orsaka Cumulative Layout Shift (CLS), en Core Web Vital som påverkar SEO-ranking. När en banner dyker upp efter att sidan har renderats skjuter den ned innehåll eller lägger sig oväntat ovanpå.
Strategier för att minimera CLS från samtyckesbanners:
- Använd en banner l��ngst ned: Bannrar längst ned i vyn flyttar inte sidans innehåll. Detta är det mest CLS-vänliga tillvägagångssättet.
- Reservera utrymme: Om du måste använda en toppbanner, reservera det vertikala utrymmet i din CSS så att sidlayouten tar höjd för bannern innan den renderas.
- Undvik modal-overlays vid laddning: Helskärms-samtyckesväggar som visas efter att sidan har renderats orsakar upplevd layoutinstabilitet. Om du behöver en vägg, rendera den som en del av sidans initiala tillstånd.
- Ladda CMP synkront i head: När CMP laddas som ett render-blockerande skript i head kan bannern visas som en del av den initiala målningen i stället för att poppa in senare.
FlexyConsents ramverksagnostiska angreppssätt
FlexyConsent är designat för att fungera med vilket ramverk som helst – eller utan ramverk – genom att verka på skriptnivå i stället för komponentnivå. Här är varför det spelar roll:
- En enda asynkron script-tagg: En
<script>-tagg i<head>är allt som behövs. Inga npm-paket att installera, inga ramverksspecifika wrappers, ingen byggkonfiguration. - Samtyckesstandarder körs omedelbart: Skriptet sätter Consent Mode V2-standarder som sin första åtgärd, före någon callback eller DOM-manipulation. Detta innebär att Google-taggar respekterar samtycke från första millisekunden.
- Ingen DOM-beroende: Samtyckeslogiken väntar inte på att React, Vue eller Svelte ska hydra. Den fungerar oberoende av ramverkets livscykel.
- Fungerar med SSG, SSR, ISR och CSR: Eftersom det är ett vanligt skript fungerar det identiskt oavsett om sidan genererades statiskt, serverrenderades, regenererades inkrementellt eller renderades på klientsidan.
Utvecklartips: Det enklaste testet för korrekt CMP-integration är att öppna webbläsarens Network-flik, filtrera på Google-domäner och ladda om sidan. Inga Google-förfrågningar ska ske innan kommandot för samtyckesstandard visas i konsolen. Om de gör det laddas din CMP för sent.
FlexyConsents gratisplan stöder obegränsade sidvisningar och fungerar med Next.js, Gatsby, Nuxt, Astro, SvelteKit, Remix och ren HTML. Integrationen är densamma i alla: en script-tagg, rätt placerad.