# Next.js & React SPA integration

Install the FlowConsent banner in a Next.js app (App Router or Pages Router) and enable SPA Mode to re-check consent on every client-side navigation.

> Canonical: https://www.flowconsent.com/en/doc/nextjs-integration
> Last updated: 2026-05-31
The FlowConsent banner is a single self-contained `<script>`, the same snippet works on Next.js, Nuxt, SvelteKit, and any custom-code app, exactly like it does on Webflow, Framer, or WordPress. There is **one extra step** for single-page apps: enable **SPA Mode** so consent is re-checked when the user navigates client-side.

## Why a SPA needs one extra step

On a classic multi-page site, every navigation is a full page reload, so the banner re-runs and re-blocks tracking scripts on each page. A Single Page Application (Next.js, React, Vue…) navigates with `history.pushState`, **no page reload**, so without SPA Mode, scripts injected after the first page would not be re-blocked on subsequent routes.

SPA Mode hooks `pushState`, `replaceState`, and `popstate` to re-verify consent on every client-side navigation.

## Step 1: Add the script

The banner already ships Google Consent Mode v2 defaults inside the bundle, so the snippet stays minimal: just load the script as early as possible.

### App Router (`app/layout.tsx`)

```tsx
import Script from 'next/script'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        {/* FlowConsent CMP */}
        <Script
          src="https://YOUR-LICENSE-CODE.consent.flowconsent.com/cookie-manager.js?code=YOUR_LICENSE_CODE"
          strategy="beforeInteractive"
        />
      </body>
    </html>
  )
}
```

`strategy="beforeInteractive"` makes Next.js load the script before hydration, so prior blocking is in place before any tracking fires.

### Pages Router (`pages/_document.tsx`)

```tsx
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head>
        {/* FlowConsent CMP: keep it first in <Head> */}
        <script src="https://YOUR-LICENSE-CODE.consent.flowconsent.com/cookie-manager.js?code=YOUR_LICENSE_CODE" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}
```

You'll find your exact snippet (with your deployment URL and license code) in **Builder → Deployment → Integration**, where a **Next.js** tab generates this code for you.

## Step 2: Enable SPA Mode

In the Builder, open the **Settings** tab and turn on **SPA Mode**. Redeploy your banner so the change ships.

With SPA Mode on, FlowConsent will:

- Intercept `history.pushState` and `history.replaceState`
- Listen for `popstate` events
- Re-block uncovered tracking scripts on each navigation
- Emit a `flowconsent:navigation` event you can listen to

## Step 3: Let FlowConsent manage tracking scripts

Do **not** load tracking scripts (Google Analytics, Meta Pixel…) with `next/script`. Instead, declare them in **Builder → Services** and let FlowConsent inject them once consent is given.

```tsx
// Avoid: tracking script outside FlowConsent's control
<Script src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX" strategy="afterInteractive" />

// Prefer: configure Google Analytics in Builder → Services
```

## Optional: React to consent in your app

FlowConsent dispatches events you can subscribe to:

```tsx
import { useEffect } from 'react'

export function useConsentListener() {
  useEffect(() => {
    const onConsent = (event) => {
      const { preferences } = event.detail
      if (preferences?.analytics) {
        // analytics consent granted: initialise your own analytics
      }
    }
    window.addEventListener('flowconsent:consent', onConsent)
    return () => window.removeEventListener('flowconsent:consent', onConsent)
  }, [])
}
```

## Verification checklist

- [ ] Script is in `app/layout.tsx` (App Router) or `pages/_document.tsx` (Pages Router)
- [ ] App Router uses `strategy="beforeInteractive"`
- [ ] **SPA Mode** is enabled in the Builder and the banner is redeployed
- [ ] No `next/script` for tracking scripts: they're configured in Services
- [ ] Banner appears on first load
- [ ] No tracking requests in the Network tab before clicking **Accept**
- [ ] Consent persists across client-side navigations

## Do it from your AI agent (MCP)

FlowConsent has an official MCP server, `https://mcp.flowconsent.com`, usable from Claude, ChatGPT or any MCP client. You connect with OAuth 2.0 using your FlowConsent account, no API key needed. Your agent fetches the snippet and placement instructions (`get_banner_snippet` and `get_setup_instructions` tools), verifies the installation with a real scan (`verify_consent_compliance`) and can set up recurring monitoring (`monitor_compliance`). It does not edit your Next.js site for you: pasting the snippet stays on your side.

Example request: "Give me my banner snippet for my Next.js site and check that it is installed correctly on https://mysite.com".

See the [MCP server guide](/en/doc/mcp-server) and the [FlowConsent MCP](/en/mcp) page.
