Next.js & React SPA integration
Install the FlowConsent banner in a Next.js app (App Router or Pages Router) and enable SPA Mode so consent is re-checked on every client-side navigation.
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)
import Script from 'next/script'
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
{/* FlowConsent CMP */}
<Script
src="https://YOUR-WORKSPACE.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)
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-WORKSPACE.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.pushStateandhistory.replaceState - Listen for
popstateevents - Re-block uncovered tracking scripts on each navigation
- Emit a
flowconsent:navigationevent 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.
// 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 → ServicesOptional — React to consent in your app
FlowConsent dispatches events you can subscribe to:
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) orpages/_document.tsx(Pages Router) - App Router uses
strategy="beforeInteractive" - SPA Mode is enabled in the Builder and the banner is redeployed
- No
next/scriptfor 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