Getting Started With Next.js

Setup Flowgrid on your Next.js app in just a few easy steps. Follow the instructions below to get started using app router (version 13+).

Add the tracking script to app layout

Create your new website and add the following script tag preferably in the layout.jsx section:

  1. Open your project's app/layout.jsx file.
  2. Add the Flowgrid tracking script tag inside the head section:
layout.jsx
1import Script from 'next/script'; 2 3export default function RootLayout({ children }) { 4 return ( 5 <html lang="en"> 6 <head> 7 <Script 8 src="https://core.flow-grid.xyz/flowgrid.js" 9 data-site="YOUR_WEBSITE_ID" 10 data-api-key="YOUR_API_KEY" 11 strategy="afterInteractive" 12 /> 13 </head> 14 <body>{children}</body> 15 </html> 16 ); 17} 18

Use the npm SDK + drop-in helpers

Prefer typed, in-app tracking over the script tag? Install the SDK and use the built-in helpers so you never re-implement consent wiring or stable IDs by hand. Everything below is framework-agnostic — the helpers import directly fromflowgrid-sdk.

1. Install

terminal
1npm install flowgrid-sdk 2# or: pnpm add flowgrid-sdk / yarn add flowgrid-sdk

2. Create a single setup file

Initialise FlowGrid once and re-export the helpers. setupConsent creates a consent manager andkeeps FlowGrid's consent gates in sync automatically.

lib/flowgrid.ts
1// lib/flowgrid.ts 2import { 3 FlowGrid, 4 setupConsent, 5 attachConsentBanner, 6 getOrCreateAnonId, 7} from "flowgrid-sdk"; 8 9// init() touches browser globals, so guard against SSR (window is undefined on the server). 10const isClient = typeof window !== "undefined"; 11 12export const flowgrid = isClient 13 ? FlowGrid.init({ 14 webId: process.env.NEXT_PUBLIC_FLOWGRID_WEB_ID!, 15 apiKey: process.env.NEXT_PUBLIC_FLOWGRID_API_KEY!, 16 autoTrack: { performance: true, engagement: true, replay: true }, 17 }) 18 : null; 19 20export const track = flowgrid?.track.bind(flowgrid) ?? (() => undefined); 21 22// One call creates a consent manager AND keeps FlowGrid's consent gates in sync — 23// no manual FlowGridTransport.setConsent() plumbing. 24export const getConsent = () => 25 setupConsent({ cookieName: "my_app_consent", cookieDays: 180, respectDNT: true }); 26 27// Re-export the drop-in helpers so the rest of your app imports from one place. 28export { attachConsentBanner, getOrCreateAnonId };

3. Cookie consent banner

Drop this client component into your app/layout.tsx. No manual transport sync — getConsent() did that for you.

components/cookie-banner.tsx
1// components/cookie-banner.tsx 2"use client"; 3import { useEffect, useState } from "react"; 4import { getConsent } from "@/lib/flowgrid"; 5 6export function CookieBanner() { 7 const [manager, setManager] = useState<ReturnType<typeof getConsent>>(); 8 const [visible, setVisible] = useState(false); 9 10 useEffect(() => { 11 const cm = getConsent(); // already pushes stored prefs into FlowGrid 12 setManager(cm); 13 if (!cm.hasConsented()) setVisible(true); 14 }, []); 15 16 if (!visible) return null; 17 18 return ( 19 <div id="cookie-banner" className="fixed bottom-0 inset-x-0 p-4 bg-background border-t"> 20 <button onClick={() => { manager?.rejectNonEssential(); setVisible(false); }}> 21 Reject non-essential 22 </button> 23 <button onClick={() => { manager?.acceptAll(); setVisible(false); }}> 24 Accept all 25 </button> 26 </div> 27 ); 28}

Not using React for the banner?

Call attachConsentBanner() instead — it wires the#accept-btn /#reject-btn buttons inside any#cookie-banner element for you.

4. Track with stable IDs

getOrCreateAnonId() persists a stable visitor id (SSR-safe), so product and cart events from one visitor line up automatically. Revenue comes from your connected payment provider, not from browser events.

anywhere.ts
1import { track, getOrCreateAnonId } from "@/lib/flowgrid"; 2 3// Product view — stable anonymous id, no boilerplate. 4track("product_view", { 5 productId: p.id, name: p.name, price: p.price, currency: "EUR", 6 userId: getOrCreateAnonId(), 7}); 8 9// Add to cart — a named event; build the funnel from it with no extra code. 10track("add_to_cart", { 11 productId: p.id, name: p.name, price: p.price, currency: "EUR", quantity: 1, 12 userId: getOrCreateAnonId(), 13}); 14 15// Revenue is NOT tracked from the browser: connect your payment provider 16// (Website settings → Payments) and payments arrive from its webhook, already 17// matched to this visitor. See /documentation/revenue-attribution.

5. Run an A/B experiment

Read an A/B test flag where the change renders. Reading it counts the visitor; the experiment compares the variants on the results you pick in the dashboard.

components/hero-cta.tsx
1// components/hero-cta.tsx 2"use client"; 3import { useFlagVariant } from "flowgrid-sdk/react"; 4 5export function HeroCta() { 6 const variant = useFlagVariant("hero-cta"); // null while off or outside the test 7 return <Button>{variant === "trial" ? "Start Free Trial" : "Book a Demo"}</Button>; 8} 9 10// Create the experiment in Product Analytics → Experiments and pick what 11// decides it (a signup, a form, revenue). No conversion call needed.

Verify installation

After adding the script do the following to verify that the installation was successful:

  1. Open your website that you are now tracking in the browser.
  2. Go to your dashboard, click on your website and click the go to website's dashboard to see if the incoming traffic are being tracked.