Consentl met Next.js
Plaats Consentl als eerste in de <head> van de root layout (App Router), laad andere tags via een kleine ConsentlScript-component, of gebruik _document (Pages Router).
- Loader als eerste in <head>
- Ja
Voor voorafgaande blokkering en de standaardwaarden van Google Consent Mode moet Consentl vóór elke andere tag worden uitgevoerd,
synchroon (geen async, defer of type="module"). In Next.js betekent dat een gewone <script>-tag,
niet next/script.
<script src="https://api.consentl.com/v1/loader.js?k=SITE_KEY&l=LANG"></script>
Sla de sitesleutel op in een omgevingsvariabele zoals NEXT_PUBLIC_CONSENTL_SITE_KEY. De sleutel is
openbaar, dus het is geen probleem dat de browser hem ziet. Consent Mode vereist het plan Pro of hoger, automatische
blokkering van bekende trackers het plan Business.
App Router (app/layout.tsx)
Getest met Next.js 16.4 en React 19.
Wat React 19 en Next met uw tags doen
- React behandelt elke
<script async src>als een resource en verplaatst die naar de bovenkant van<head>, boven een gewoon synchroon script, zelfs als u hem na Consentl hebt geschreven. De eigen scripts van Next komen ook eerst. next/scriptmetstrategy="afterInteractive"(enbeforeInteractive) schrijft een<link rel="preload">voor de tag in de pagina. De browser downloadt de tag terwijl hij de pagina leest, vóór de toestemming. Consentl voorkomt dat de tag wordt uitgevoerd, maar niet dat verzoek.
De gestreamde paginagegevens van Next (self.__next_f) worden nooit door Consentl tegengehouden, wat er ook in staat.
Aanbevolen configuratie
- Consentl als gewone
<script src>, als eerste in<head>. React verplaatst hem niet, hij staat één keer in de pagina, en bezoekers krijgen altijd uw actuele bannerinstellingen (de loader wordt 5 minuten in de cache opgeslagen). - Elke andere tag die op toestemming moet wachten (Google Analytics, Meta, TikTok…) via de kleine
component
ConsentlScripthieronder. Die schrijft de tag alstype="text/plain"met zijn Consentl-categorie: React verplaatst hem niet, de browser downloadt hem niet en Consentl voert hem na de toestemming één keer uit, bij elk plan, ook na navigatie aan de clientkant. - Of beheer die tags in Google Tag Manager (zie Google Tag Manager).
Google-tags in de geavanceerde modus van Consent Mode (plan Pro en hoger) zijn bedoeld om vóór de toestemming te laden;
als u die modus gebruikt, laad ze dan met next/script en afterInteractive.
strategy="lazyOnload" schrijft geen preload (Next 16.4) en wordt tegengehouden tot de toestemming, maar alleen voor tags
die automatische blokkering herkent (plan Business), dus geef de voorkeur aan ConsentlScript.
// app/consentl-script.tsx — works in Server and Client Components
type Category = "preferences" | "analytics" | "marketing";
/** A tag that waits for consent: inert in the page, run by Consentl once the category is accepted. */
export function ConsentlScript({ category, src, nonce, children }: { category: Category; src?: string; nonce?: string; children?: string }) {
return src ? (
// eslint-disable-next-line @next/next/no-sync-scripts -- type="text/plain": never loaded by the browser itself
<script type="text/plain" data-consentl={category} src={src} nonce={nonce} />
) : (
<script type="text/plain" data-consentl={category} nonce={nonce} dangerouslySetInnerHTML={{ __html: children ?? "" }} />
);
}
// app/layout.tsx (or app/[locale]/layout.tsx)
import { ConsentlScript } from "./consentl-script";
const SITE_KEY = process.env.NEXT_PUBLIC_CONSENTL_SITE_KEY!;
export default function RootLayout({ children }: { children: React.ReactNode }) {
const lang = "en"; // e.g. (await params).locale
const loader = `https://api.consentl.com/v1/loader.js?k=${encodeURIComponent(SITE_KEY)}&l=${encodeURIComponent(lang)}`;
return (
<html lang={lang}>
<head>
{/* eslint-disable-next-line @next/next/no-sync-scripts -- must block: consent defaults + prior blocking */}
<script src={loader} />
</head>
<body>
{children}
<ConsentlScript category="analytics" src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX" />
<ConsentlScript category="analytics">
{`window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag('js',new Date());gtag('config','G-XXXXXXX');`}
</ConsentlScript>
<footer>
<a href="#consentl" data-consentl-open="">Cookie settings</a>
</footer>
</body>
</html>
);
}
Met een Content Security Policy geeft u uw nonce door aan ConsentlScript (nonce={nonce}); Consentl
behoudt die wanneer het de tag uitvoert.
Waarom de loader niet inline afdrukken?
Een eerdere versie van deze pagina haalde de loader op de server op en drukte hem inline af. In de App
Router verstuurt dat de loader twee keer bij elke volledige paginalading, omdat React de
inhoud van het <script> van een Server Component ook naar de paginagegevens kopieert, en statisch gebouwde pagina's de
kopie die tijdens de build is opgehaald, behouden totdat ze opnieuw worden gevalideerd. Op dezelfde testpagina:
| Configuratie | HTML van de pagina | Consentl-loader |
|---|---|---|
| Gewone scripttag (aanbevolen) | 2,2 KB gzipped | 9,5 KB gzipped, één verzoek, 5 minuten in de cache en gedeeld door alle pagina's |
| Inline loader | 15,2 KB gzipped, bij elke volledige paginalading | twee keer in de pagina |
De gewone tag kost één verzoek aan api.consentl.com voordat de pagina wordt gerenderd. Met elke andere tag
in ConsentlScript (of Google Tag Manager) staat er niets in de pagina dat de browser zou kunnen
downloaden voordat Consentl wordt uitgevoerd.
Niet aanbevolen: beforeInteractive
next/script met strategy="beforeInteractive" wordt uitgegeven als een preload plus een inline wachtrij-item;
Next voegt het echte <script> vóór de hydratatie in, na inline en async scripts die al
in de server-rendered HTML staan.
Pages Router (pages/_document.tsx)
In de Pages Router wordt beforeInteractive met defer na de CSS-links gerenderd. Gebruik in plaats daarvan een gewoon
script:
import { Head, Html, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="en">
<Head>
{/* eslint-disable-next-line @next/next/no-sync-scripts */}
<script src={`https://api.consentl.com/v1/loader.js?k=${process.env.NEXT_PUBLIC_CONSENTL_SITE_KEY}&l=en`} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
Navigatie aan de clientkant
Er is niets extra's nodig: de runtime blijft geladen, de keuze staat in de first-party cookie consentl
en links "Cookie-instellingen" werken op elke route. Controleer voor uw eigen code de toestemming met
window.Consentl?.allowed("analytics") en het event consentl:change, en start dingen maar één keer
(zie Elke website).
Controleren of het werkt
Gebruik op een pagina View Source (Paginabron weergeven, niet de elementinspector): na de eigen
/_next/static/chunks/…-scripts van Next moet Consentl vóór elk ander script komen, er is geen
<link rel="preload"> voor een trackingtag en uw tags zijn type="text/plain". Open daarna de site
in een privévenster en controleer de banner en het tabblad Network (Netwerk) zoals beschreven in
Elke website: geen verzoek aan een tracker voordat u accepteert.
Beperkingen
async-tags die in de layout staan, worden door React boven Consentl geplaatst; gebruik in plaats daarvanConsentlScript.next/scriptmetafterInteractivelaat de browser de tag vóór de toestemming downloaden.- Met
beforeInteractiveworden scripts die al in de server-rendered HTML staan, vóór Consentl uitgevoerd. - Een taalwissel aan de clientkant laadt de banner niet opnieuw; de nieuwe taal geldt bij de volgende volledige paginalading.
- Als u een Content Security Policy verstuurt, sta dan
https://api.consentl.comtoe (zie Elke website).
Gerelateerde handleidingen
Vastgelopen? Schrijf naar support@consentl.com — wij antwoorden op werkdagen in het Engels.