Next.js SDK
Drop-in analytics for App Router and Pages Router — one component, React hooks, and an optional API proxy.
The Next.js SDK wraps the Web SDK and adds a FlashAnalyticsComponent for layout setup, a useFlashAnalytics() hook for client components, and an optional route-handler proxy so events stay on your domain.
Installation
Install the package
npm install @flash-analytics/nextjs@2.2.4pnpm add @flash-analytics/nextjs@2.2.4Add environment variables
NEXT_PUBLIC_FLASH_ANALYTICS_APP_ID=00000000-0000-4000-8000-000000000000
NEXT_PUBLIC_FLASH_ANALYTICS_ENDPOINT=https://api.flashanalytics.appKeep secrets server-side
NEXT_PUBLIC_* variables in the browser. Never set FLASH_ANALYTICS_SECRET_KEY as a public env var.Add the component to your root layout
Place FlashAnalyticsComponent inside <body> so it loads on every page.
import { FlashAnalyticsComponent } from '@flash-analytics/nextjs';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<FlashAnalyticsComponent
appId={process.env.NEXT_PUBLIC_FLASH_ANALYTICS_APP_ID!}
capturePageViews
captureErrors
captureVariants
/>
{children}
</body>
</html>
);
}Track events in client components
'use client';
import { useFlashAnalytics } from '@flash-analytics/nextjs';
export function UpgradeButton() {
const analytics = useFlashAnalytics();
return (
<button
onClick={() => analytics.track('upgrade_clicked', { placement: 'settings' })}
>
Upgrade
</button>
);
}Pages Router setup
For Pages Router, add the component in _app.tsx.
import type { AppProps } from 'next/app';
import { FlashAnalyticsComponent } from '@flash-analytics/nextjs';
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<FlashAnalyticsComponent
appId={process.env.NEXT_PUBLIC_FLASH_ANALYTICS_APP_ID!}
capturePageViews
/>
<Component {...pageProps} />
</>
);
}Identify users
Call identify after login. Pass userId directly to the component to identify immediately at bootstrap.
// Via hook (client component)
const analytics = useFlashAnalytics();
await analytics.identify({ profileId: session.user.id, email: session.user.email });
// Via component prop (identifies at script boot)
<FlashAnalyticsComponent
appId={process.env.NEXT_PUBLIC_FLASH_ANALYTICS_APP_ID!}
userId={session?.user?.id}
defaultProperties={{ plan: session?.user?.plan }}
/>Experiments
Enable captureVariants to keep a local cache in sync automatically. New session → all experiments fetched. After identify() → profile-mode assignments refreshed.
'use client';
import { useFlashAnalytics } from '@flash-analytics/nextjs';
export function PricingBanner() {
const analytics = useFlashAnalytics();
// No API call — reads from cache
const all = analytics.getAllExperiments();
// Cache first, API fallback
const assignment = await analytics.getExperimentById('checkout-cta');
console.log(assignment?.variantName); // 'control' | 'variant_a'
}Dashboard settings and batching
Because the Next.js SDK wraps the Web SDK, it supports the same dashboard-managed collection rules, session timeout override, batching, remote config, and experiment cache behavior.
<FlashAnalyticsComponent
appId={process.env.NEXT_PUBLIC_FLASH_ANALYTICS_APP_ID!}
collectionConfig
maxSessionTimeoutInMin={15}
deliveryStrategy={{
strategy: 'batching',
config: {
size: 10,
timeout: 5000,
fallbackToIndividual: true,
},
}}
/>From the dashboard, you can allow or block event patterns, allow or block properties for a single event, define project-wide blocked properties, and create client-level overrides for one Next.js app without affecting other clients in the same project.
Error boundaries
import { FlashAnalyticsComponent, FlashErrorBoundary } from '@flash-analytics/nextjs';
export default function RootLayout({ children }: { children: React.ReactNode }) {
const appId = process.env.NEXT_PUBLIC_FLASH_ANALYTICS_APP_ID!;
const endpoint = process.env.NEXT_PUBLIC_FLASH_ANALYTICS_ENDPOINT
?? 'https://api.flashanalytics.app';
return (
<html lang="en">
<body>
<FlashAnalyticsComponent appId={appId} endpoint={endpoint} captureErrors />
<FlashErrorBoundary
clientId={appId}
apiUrl={`${endpoint}/track`}
fallback={<h1>Something went wrong.</h1>}
>
{children}
</FlashErrorBoundary>
</body>
</html>
);
}API proxy (optional)
Route events through your own domain to avoid ad-blockers. Create a route handler and point the component at it with endpoint.
import { createRouteHandler } from '@flash-analytics/nextjs/server';
export const { GET, POST } = createRouteHandler({
endpoint: 'https://api.flashanalytics.app',
});<FlashAnalyticsComponent
appId={process.env.NEXT_PUBLIC_FLASH_ANALYTICS_APP_ID!}
endpoint="/api/flash-analytics"
/>Available hook methods
useFlashAnalytics() returns all core SDK methods:
track()identify()setGlobalProperties()revenue()increment()decrement()getSession()fetchRemoteConfig()assignExperiment()autoAssignExperiments()getAllExperiments()getExperimentById()