ConsentLayer
Guides

Next.js Integration

This guide shows how to integrate ConsentLayer with Next.js 13+ App Router.

1. Install the SDK

npm install @consentlayer/sdk

2. Add the banner script

Easiest: let your agent install it

Run claude mcp add consentlayer --transport http https://api.consentlayer.com/mcp then ask: "Add the ConsentLayer banner to my Next.js app." Your agent will sign in, provision the site, and write the script tag with your real key. More on the MCP path →

Manual setup

  1. Sign in to the dashboard and copy your project key.

  2. In your root layout (app/layout.tsx), add the banner script tag — replace <your-key> with the value you copied. Don't include defer or async.

    export default function RootLayout({ children }: { children: React.ReactNode }) {
      return (
        <html lang="en">
          <head>
            <script src="https://b.consentlayer.com/<your-key>/banner.js" />
          </head>
          <body>{children}</body>
        </html>
      )
    }

3. Add the provider

Create a client component wrapper:

// components/consent-provider.tsx
'use client'

import { ConsentLayerProvider } from '@consentlayer/sdk/react'

export function ConsentProvider({ children }: { children: React.ReactNode }) {
  return <ConsentLayerProvider>{children}</ConsentLayerProvider>
}

Add it to your layout:

import { ConsentProvider } from '@/components/consent-provider'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <script src="https://b.consentlayer.com/<your-key>/banner.js" />
      </head>
      <body>
        <ConsentProvider>{children}</ConsentProvider>
      </body>
    </html>
  )
}

4. Use ConsentGate

Gate third-party scripts behind consent:

'use client'

import { ConsentGate } from '@consentlayer/sdk/react'
import Script from 'next/script'

export function Analytics() {
  return (
    <ConsentGate category="statistics">
      <Script
        src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXX"
        strategy="afterInteractive"
      />
    </ConsentGate>
  )
}

Hydration in the App Router

useConsent() and <ConsentGate> read the consent cookie on mount, so the server-rendered HTML (null cookie) won't match the first client render if the visitor has already consented. To avoid the hydration mismatch warning, gate any consent-aware UI behind a mounted flag:

'use client'

import { useEffect, useState } from 'react'
import { ConsentLayerProvider, ConsentGate } from '@consentlayer/sdk/react'

export function ConsentArea({ children }: { children: React.ReactNode }) {
  const [mounted, setMounted] = useState(false)
  useEffect(() => setMounted(true), [])
  if (!mounted) return null
  return (
    <ConsentLayerProvider>
      <ConsentGate category="statistics">{children}</ConsentGate>
    </ConsentLayerProvider>
  )
}

Why a plain <script> and not next/script?

Next.js 16 errors when <Script strategy="beforeInteractive"> is rendered inside a React component ("Scripts inside React components are never executed when rendering on the client"). A plain <script> tag in a server component renders as static HTML — the browser runs it synchronously when it parses <head>, which is exactly what the banner needs to block tracking scripts before they fire.

Add a "Manage cookies" link to your footer:

'use client'

import { useConsent } from '@consentlayer/sdk/react'

export function CookieLink() {
  const { showPreferences } = useConsent()
  return <button onClick={showPreferences}>Manage cookies</button>
}