Next.js cookie consent comes down to one rule: no analytics or marketing script may set cookies before the visitor agrees, whether the page is rendered on the server or in the browser. In the App Router, load the consent script in the root layout.tsx with next/script and strategy="beforeInteractive", then render each tracker only once its category is accepted, or send Google tags a denied Consent Mode default first. As of October 2026 this applies to Next.js 15 and later, where cookies() is asynchronous.
Why cookie consent works differently in Next.js
Next.js renders pages on the server before sending them to the browser, and that changes how cookies behave. During server-side rendering (SSR) there is no document object, so browser cookie libraries fail silently or throw errors. Static generation builds pages ahead of time with no visitor context at all.
The result: tracking scripts that set cookies such as _ga or _fbp must not run during the server render. They belong in the browser, and only after a visitor has given valid consent under Article 5(3) of the ePrivacy Directive or the equivalent local law.
This applies whether you use the App Router or the Pages Router, and wherever you deploy.
Common cookies in a Next.js application
Before configuring consent, find out what your site actually sets. A typical Next.js project may include several cookies beyond your own application logic.
| Cookie | Source | Category | Consent needed? |
|---|---|---|---|
__prerender_bypass, __next_preview_data | Next.js Draft Mode and Preview Mode | Strictly necessary | No |
NEXT_LOCALE | Your app, read by Next.js i18n routing | Functional | Depends on purpose |
_ga, _ga_<container-id> | Google Analytics 4 | Analytics | Yes |
_fbp | Meta Pixel | Marketing | Yes |
authjs.session-token or __session | Auth.js or Clerk sign-in | Strictly necessary | No |
Vercel's own analytics products are designed to avoid cookies, covered in their own section below. Run a cookie scan against your production deployment to confirm exactly what it sets, because packages and embeds change over time.
App Router and Pages Router: where the consent script goes
The two routing architectures need different integration points.
App Router
The App Router uses React Server Components by default, and Server Components cannot use browser APIs. Load the consent script in the root app/layout.tsx so it runs on every page, before your own client code:
import Script from 'next/script'
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<Script src="https://cdn.kukie.io/s/YOUR-SITE-KEY/c.js" strategy="beforeInteractive" />
{children}
</body>
</html>
)
}
The cookies() function from next/headers reads incoming cookies in Server Components and Route Handlers. The Next.js documentation notes that it is asynchronous since version 15 and that using it in a layout or page opts that route into dynamic rendering.
Pages Router
In the Pages Router, pages/_app.tsx wraps every page, so the same <Script> goes there. getServerSideProps can read cookies from req.cookies if you need server-side consent checks.
Both approaches work, and the principle is the same: no non-essential cookie may be set before the visitor opts in.
Using the Script component for conditional loading
The built-in <Script> component from next/script controls when third-party scripts run. strategy="afterInteractive" loads a script after hydration, and strategy="lazyOnload" waits until the browser is idle. Neither waits for consent on its own. You still need logic that renders the <Script> tag only when its cookie category has been accepted.
With Kukie.io, a Client Component can listen for the cc:consent-updated event on document, which carries the accepted category slugs, and render the analytics <Script> once analytics is among them. Register the listener early, or catch the event with a small inline script, because a returning visitor's choice is restored as soon as the banner script runs.
Google Consent Mode v2
Google Consent Mode v2 adds another option. Instead of holding back the Google tag entirely, you load it with consent signals set to denied by default, and the banner updates them to granted when the visitor accepts. Google's developer guide says the default command must run before any command that sends measurement data, so put it early in the document, ahead of the Google tag.
For EEA and UK traffic, Google has required Consent Mode v2 signals for ad personalisation and measurement since March 2024. The four parameters are ad_storage, analytics_storage, ad_user_data and ad_personalization.
Script blocking: holding cookies back before consent
Conditional rendering works for scripts you control. Third-party embeds, such as YouTube iframes, social widgets and chat tools, are harder because they often set cookies as soon as they load.
A consent platform handles this by finding the scripts on your site and blocking non-essential scripts until consent is given. Kukie.io's banner holds more than 30 known trackers on its own and lets you add the domains of others, which is easier to keep current than a manual list as the site grows.
Server rendering and consent state
Server rendering adds a timing problem. The server renders HTML before the browser runs any JavaScript, including your consent banner. If the server-rendered page includes an analytics script tag, that script is in the first HTML and can set cookies before the visitor sees the banner.
How a consent-aware App Router page renders
One answer is to read the consent cookie on the server. In the App Router, await cookies() gives you the incoming cookies. With no consent cookie (a first visit), the server renders the page without analytics or marketing script tags. Only after the visitor chooses and the consent cookie is stored do later requests include those scripts. Read the cookie in the format your consent tool documents, or set your own when the consent event fires.
This turns off static rendering for routes that read cookies. If performance matters more, as it usually does for marketing pages, keep the script logic in the browser and accept that the first paint carries no tracking.
GDPR, ePrivacy and CCPA: what Next.js developers need to know
Privacy law does not care which framework you use. The obligations are the same.
Under the GDPR and the ePrivacy Directive, you need informed, freely given consent before setting any non-essential cookie. Pre-ticked boxes and "consent" by continued browsing do not count, as the EDPB has said in its consent guidelines.
The CCPA, as amended by the CPRA, takes a different approach. California law requires an opt-out from selling or sharing personal information rather than opt-in consent, you must honour Global Privacy Control (GPC) signals, and your site needs a visible "Do Not Sell or Share My Personal Information" link.
For sites with visitors in several jurisdictions, geo-detection decides which consent model to show: an EU visitor sees an opt-in banner, a Californian visitor an opt-out notice.
Obligations at a glance
| Law | Consent model | Cookie blocking | GPC signal |
|---|---|---|---|
| GDPR and ePrivacy | Opt-in (prior consent) | Yes, before consent | Not specifically addressed |
| UK GDPR and PECR | Opt-in, with some exceptions since February 2026 | Yes, before consent | Not specifically addressed |
| CCPA and CPRA | Opt-out | After an opt-out | Must be honoured |
| LGPD (Brazil) | Consent or another legal basis | Depends on the legal basis | Not specified |
| PIPEDA (Canada) | Meaningful consent | Good practice | Not specified |
Vercel Web Analytics and Speed Insights
Vercel's two built-in tools are designed around cookie rules. Vercel's documentation for Web Analytics says it tracks traffic without third-party cookies: visitors are identified by a hash created from the incoming request, and the visitor session is discarded after 24 hours. Its Speed Insights documentation says data points are anonymous and not tied to any visitor or IP address.
Because neither tool stores an identifier on the visitor's device, Article 5(3) of the ePrivacy Directive is usually not triggered by them. The GDPR can still apply if URLs or custom events carry personal data, which Vercel lets you strip with its beforeSend option.
Even if Vercel's own tools are cookie-free, most Next.js projects add Google Analytics, the Meta Pixel, Hotjar or other third-party tools that do need consent. A cookie audit of one page shows which third-party scripts load and whether they set cookies before a choice. If part of your front end is plain React, the same rules apply there.
Questions about consent in Next.js
Does Next.js set cookies by default?
A bare Next.js app sets no cookies. They appear when you use Draft Mode or Preview Mode, set a NEXT_LOCALE cookie for i18n routing, add sign-in, or load third-party analytics scripts.
Can I read consent status in a Server Component?
Yes. The cookies() function from next/headers reads the request's cookies during server rendering, and since Next.js 15 you await it. Reading cookies makes the route render dynamically.
Do I need separate consent logic for the App Router and Pages Router?
The consent logic is the same. The difference is where the script goes: the root layout for the App Router, pages/_app.tsx for the Pages Router. A shared Client Component can serve both.
How do I block Google Analytics until consent in Next.js?
Render the analytics Script component only once analytics consent is given. Alternatively, load Google's tag with Consent Mode v2 set to denied by default and update the signals when the visitor accepts.
Does static generation in Next.js affect cookie consent?
Statically generated pages are built ahead of time with no visitor context, so they cannot read consent cookies on the server. Consent logic and script blocking for those pages happen in the browser after hydration.
Check what your Next.js app sets before consent
Server rendering makes it easy for a tracker to slip into the first HTML. The Cookie scanner loads your deployed app like a visitor and lists every cookie it finds by name and category, so you can see whether anything is set before the banner.
