Why Cookie Consent Works Differently in Next.js
Next.js renders pages on the server before sending them to the browser. That single architectural decision changes how cookies behave. During server-side rendering (SSR), there is no document object, so client-side cookie libraries fail silently or throw errors. Static site generation (SSG) builds pages at compile time with no user context at all.
The result: tracking scripts that drop cookies like _ga, _fbp, or _gid must not execute during the server render phase. They belong on the client, and only after a visitor has given valid consent under Article 5(3) of the ePrivacy Directive or equivalent local law.
This applies whether you use the App Router or the Pages Router, and regardless of your deployment target.
Common Cookies in a Next.js Application
Before configuring consent, you need to know what your site actually sets. A typical Next.js project deployed on Vercel may include several cookie types beyond your own application logic.
| Cookie | Source | Category | Consent Required? |
|---|---|---|---|
__next_preview_data | Next.js Preview Mode | Strictly necessary | No |
NEXT_LOCALE | Next.js i18n routing | Functional | Depends on jurisdiction |
_ga, _gid | Google Analytics 4 | Analytics | Yes |
_fbp | Meta Pixel | Marketing | Yes |
_vercel_speed_insights | Vercel Speed Insights | Analytics | Yes |
__session | Custom auth (e.g. NextAuth) | Strictly necessary | No |
Vercel Analytics, in its default configuration, does not use cookies and collects no personally identifiable information. Vercel Speed Insights, however, can set cookies depending on implementation. Always run a cookie scan to confirm exactly what your production deployment sets - assumptions based on documentation alone are unreliable.
App Router vs Pages Router: Where to Place the Consent Script
The two routing architectures in Next.js require different integration points for a cookie consent banner.
App Router (Next.js 13+)
The App Router uses React Server Components by default. Server Components cannot access browser APIs, so your consent banner must be a Client Component marked with 'use client'. Place it in your root layout.tsx to ensure it loads on every page.
The cookies() function from next/headers reads incoming HTTP cookies in Server Components and Route Handlers. You can use this to check consent status server-side and decide whether to include analytics scripts in the initial HTML. This avoids a flash of unconsented tracking.
Pages Router
In the Pages Router, _app.tsx wraps every page. Add your consent component here. The getServerSideProps function can read cookies from the request object (req.cookies) if you need server-side consent checks.
Both approaches work. The key principle is identical: no non-essential cookies may be set before the visitor opts in.
Using the Next.js Script Component for Conditional Loading
The built-in <Script> component from next/script gives you control over when third-party scripts execute. Two strategies are worth knowing.
The strategy="lazyOnload" option defers loading until the browser is idle. The strategy="afterInteractive" option loads the script after hydration. Neither strategy, on its own, blocks scripts until consent is granted. You still need consent logic that conditionally renders the <Script> tag.
A straightforward pattern: store consent status in a cookie (e.g. cookie_consent), read it in your layout or page component, and only render the <Script> element when consent has been granted for that cookie category.
Google Consent Mode v2
Google Consent Mode v2 adds another layer. Rather than blocking the Google tag entirely, Consent Mode lets you load the tag with consent signals set to denied by default. When a visitor accepts cookies, your consent banner updates the signals to granted. Google then uses conversion modelling to fill data gaps from visitors who declined.
If you run Google Ads or rely on GA4 audiences, Consent Mode v2 is now mandatory for serving personalised ads to EEA and UK users. Your Next.js implementation must fire the default command before any Google tag loads, which means placing it early in your <head> via the <Script> component with strategy="beforeInteractive".
Script Blocking: Preventing Cookies Before Consent
Conditional rendering of <Script> tags works for scripts you control. Third-party embeds - YouTube iframes, social widgets, chat tools - are harder. They often set cookies the moment they load in the DOM.
A cookie consent platform handles this by scanning your site, identifying every script and its cookies, and blocking non-essential scripts until consent is granted. This is more reliable than maintaining a manual list of scripts, especially as your site grows.
For a detailed walkthrough of adding a consent banner to your Next.js project, see the Next.js installation guide in the Help Centre.
Server-Side Rendering and Consent State
SSR introduces a timing problem. The server renders HTML before the browser executes any JavaScript, including your consent banner. If your server-rendered page includes an analytics script tag, that script will be present in the initial HTML - potentially setting cookies before the visitor has a chance to respond to the banner.
The solution is to read the consent cookie server-side. In the App Router, the cookies() async function provides access to incoming cookies. If no consent cookie exists (first-time visitor), the server should render the page without any analytics or marketing script tags. Only after the visitor interacts with the banner and sets a consent cookie will subsequent page loads include those scripts.
This approach does disable static rendering for pages that need consent-aware script injection. If performance matters more (and it usually does for marketing pages), keep the script logic client-side and accept that the first paint will not include tracking.
GDPR, ePrivacy, and CCPA: What Next.js Developers Must Know
Privacy law does not care which framework you use. The obligations are the same.
Under GDPR and the ePrivacy Directive, you must obtain informed, freely given consent before setting any non-essential cookie. Pre-ticked boxes and implied consent through continued browsing do not count. The EDPB has confirmed this repeatedly in enforcement guidance.
CCPA/CPRA takes a different approach. California law requires an opt-out mechanism rather than opt-in consent for most cookie uses. You must honour Global Privacy Control (GPC) signals sent by the browser, and your site needs a visible "Do Not Sell or Share My Personal Information" link.
For sites that serve visitors across multiple jurisdictions, geo-detection determines which consent model to show. An EU visitor sees an opt-in banner; a Californian visitor sees an opt-out notice.
Obligations at a Glance
| Regulation | Consent Model | Cookie Blocking Required? | GPC Signal |
|---|---|---|---|
| GDPR / ePrivacy | Opt-in (prior consent) | Yes - before consent | Recommended |
| UK GDPR / PECR | Opt-in (prior consent) | Yes - before consent | Recommended |
| CCPA / CPRA | Opt-out | After opt-out request | Legally required |
| LGPD (Brazil) | Opt-in for sensitive data | Depends on legal basis | Not specified |
| PIPEDA (Canada) | Meaningful consent | Best practice | Not specified |
Vercel Analytics and Speed Insights: Do They Need Consent?
Vercel Analytics, the built-in analytics product, is designed to be privacy-friendly. It does not use cookies and collects no personally identifiable information. In most interpretations, this means it does not require consent under the ePrivacy Directive, because Article 5(3) specifically targets the storage of information on a user's device.
Vercel Speed Insights operates similarly but can behave differently depending on configuration. Always verify with a cookie audit.
Keep in mind: even if Vercel's own tools are cookie-free, most Next.js projects add Google Analytics, Meta Pixel, Hotjar, or other third-party tools that absolutely do require consent. A single unconsented _ga cookie is enough to trigger a DPA investigation.
Frequently Asked Questions
Does Next.js set cookies by default?
A bare Next.js installation does not set cookies. Cookies appear when you add features like Preview Mode (__next_preview_data), i18n routing (NEXT_LOCALE), authentication, or third-party analytics scripts.
Can I read consent status in a Server Component?
Yes. The cookies() function from next/headers reads HTTP cookies during server rendering. Check your consent cookie's value to decide whether to include analytics script tags in the rendered HTML.
Is Vercel Analytics GDPR-compliant without a cookie banner?
Vercel Analytics does not use cookies or collect personal data, so it generally falls outside the scope of the ePrivacy Directive's consent requirement. GDPR compliance depends on whether any personal data is processed, which you should verify against Vercel's current privacy documentation.
Do I need separate consent logic for the App Router and Pages Router?
The consent logic itself is the same. The difference is where you place the component: layout.tsx for the App Router, _app.tsx for the Pages Router. A shared Client Component can serve both architectures.
How do I block Google Analytics until consent in Next.js?
Conditionally render the <Script> component based on consent state. Alternatively, load Google's tag with Consent Mode v2 set to denied by default, then update the consent signal when the visitor accepts.
Does static site generation (SSG) in Next.js affect cookie compliance?
SSG pages are built at compile time with no user context, so they cannot read consent cookies server-side. All consent logic and script blocking must happen client-side after hydration.
Take Control of Your Cookie Compliance
If you are not sure which cookies your Next.js site sets, start with a free scan. Kukie.io detects, categorises, and helps you manage every cookie - so your visitors get a clear choice, and you stay on the right side of the law.