Next.js
Content analytics for Next.js App Router and Pages Router
The Next.js adapter wraps your app in a ContentProvider and exposes a useTrackView hook that's SSR-safe. It detects build-time and skips emission automatically.
Install
npm install @better-i18n/contentbun add @better-i18n/contentpnpm add @better-i18n/contentyarn add @better-i18n/contentConfigure
Add your Project ID and API key to .env.local. Find both in the dashboard under Settings → General and Settings → API Keys.
NEXT_PUBLIC_BETTER_I18N_PROJECT_ID=your-org/your-project
NEXT_PUBLIC_BETTER_I18N_KEY=bi_pub_xxxxxSetup
Wrap your app with ContentProvider in a client component:
'use client'
import { ContentProvider } from '@better-i18n/content/adapters/nextjs'
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ContentProvider
config={{
projectId: process.env.NEXT_PUBLIC_BETTER_I18N_PROJECT_ID!,
apiKey: process.env.NEXT_PUBLIC_BETTER_I18N_KEY!,
}}
>
{children}
</ContentProvider>
)
}Mount it in your root layout:
import { Providers } from './providers'
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}Track a view
'use client'
import { useTrackView } from '@better-i18n/content/adapters/nextjs'
export default function BlogPost({ post }: { post: Post }) {
useTrackView('content.view', {
entryId: post.id,
contentModel: 'blog',
entrySlug: post.slug,
language: post.locale,
})
return <article>{post.body}</article>
}SSR safety
ContentProvider creates the tracker synchronously, but track() is inherently SSR-safe — it checks isBrowser() internally and becomes a no-op on the server. useTrackView is also a no-op during SSR and during the Next.js build phase (NEXT_PHASE=phase-production-build).
If useTrackView or useContent is used outside of a ContentProvider, the SDK logs a one-time warning and disables tracking — it never throws or crashes your app.