Skill 09 · Contentful Personalization
Subchapter 9.21
references/provider-patterns.mdMarkdown5 KBView on GitHub
Use these patterns to avoid scope and hydration problems.
The lifecycle boundary is runtime-specific. Do not treat every Optimization integration as a client-only React provider:
OptimizationRoot and one router tracker around the browser tree.createNextjsAppRouterOptimization from
@contentful/optimization-nextjs/app-router; the bound OptimizationRoot owns server evaluation
and browser takeover.createNextjsPagesRouterOptimization from /pages-router and /pages-router/server.ContentfulOptimization singletons; Node calls forRequest() for
each request.OptimizationRoot or injects an explicitly owned instance.For exact provider or factory code, use the matching optimization-<runtime>.md reference together
with optimization-shared.md. Keep one root/factory, one initial page or screen owner, and one clear
manual-or-managed entry boundary.
Use the following patterns only when the repository already uses the Ninetailed SDK and the task is to diagnose, repair, or extend that deployment.
Recommended pattern:
NinetailedProvider in pages/_app.tsx.page() calls for navigation events.Typical plugin choices:
NinetailedInsightsPlugin for measurementNinetailedSsrPlugin for SSR or edge profile continuityNinetailedPreviewPlugin only for preview or development workflowsExample shape:
<NinetailedProvider
clientId={process.env.NEXT_PUBLIC_NINETAILED_CLIENT_ID ?? ''}
environment={process.env.NEXT_PUBLIC_NINETAILED_ENVIRONMENT ?? 'main'}
plugins={[
new NinetailedInsightsPlugin(),
...(preview
? [
new NinetailedPreviewPlugin({
experiences: pageProps.ninetailed?.preview?.experiences ?? [],
audiences: pageProps.ninetailed?.preview?.audiences ?? [],
}),
]
: []),
]}
>
<Component {...pageProps} />
</NinetailedProvider>Recommended pattern:
NinetailedProvider initialization in a dedicated client wrapper component.Example shape:
import { NinetailedProvider } from '@ninetailed/experience.js-next';
import { NinetailedInsightsPlugin } from '@ninetailed/experience.js-plugin-insights';
export default function RootLayout({ children }) {
return (
<html>
<body>
<NinetailedProvider
clientId={process.env.NEXT_PUBLIC_NINETAILED_API_KEY!}
environment={process.env.NEXT_PUBLIC_NINETAILED_ENVIRONMENT}
plugins={[new NinetailedInsightsPlugin()]}
>
{children}
</NinetailedProvider>
</body>
</html>
);
}Checklist:
page() call.Use a dedicated tracker component for App Router navigation rather than scattering page() calls
across many routes.
clientId prop (API key not passed or env var undefined).@contentful/optimization: destructuring methods off useOptimization() instead of using
useOptimizationActions() (loses the instance binding).@ninetailed/experience.js: empty plugins array when analytics is expected; using apiKey
instead of clientId on older SDK versions.