Choose your setup
Before installing packages, decide on your architecture and which plugins you need. This guide helps you make those choices based on your framework, rendering requirements, and feature needs.
Choose your architecture
Your architecture determines when personalization happens, in the browser, on the server, or at the edge.
NOTE: We recommend using the hybrid approach when personalized HTML on first load matters to you. Use client-only when simplicity is your priority. Avoid server-only unless you have a specific reason as it limits analytics and experiment measurement significantly.
For hybrid and server-only implementation details, see Edge and Server Side Rendering.
Choose your packages
Start with the core packages for your framework, then add plugins based on your needs.
Core packages
For most setups, install these three packages:
If you are not using Next.js (@ninetailed/experience.js-next), replace the framework package:
NOTE:
We recommend using fixed package versions instead of a range selector. For example, 7.9.0 instead od ^7.9.0. When adding or updating packages later on, make sure all packages are at the same exact version. Mixing versions causes unexpected behaviour.
Plugin packages
Add plugins based on what you need:
NOTE:
The Insights plugin (@ninetailed/experience.js-plugin-insights) is different from the base analytics plugin (@ninetailed/experience.js-plugin-analytics). For built-in experiment measurement and component insights, use the Insights plugin.
Framework-specific guidance
Next.js Pages Router
- Place
NinetailedProviderinpages/_app.tsx. - The Pages Router integration automatically tracks page changes.
NOTE:
Do not add manual page() calls for route navigation.
- Use
getStaticPropswithrevalidate(ISR) for the best balance of performance and fresh content. - For SSR/edge, add middleware and the SSR plugin.
Example
Next.js App Router
- The provider must be in a Client Component. Create a
providers.tsxwrapper with'use client'and place it in your root layout. - The current SDKs do not auto-track App Router navigation. Add a dedicated page tracker component.
- Server Components cannot use personalization hooks. Fetch content in a Server Component and pass it to a Client Component that handles personalization.
Examples
Gatsby
- Place the provider in
gatsby-browser.js(andgatsby-ssr.js). The provider needs to be declared both in the browser and the SSR file to avoid React hydration issues, such as, the server-generated React tree not matching the client-generated one. - Personalization is client-side only — static HTML shows the baseline, and the SDK swaps variants after hydration
- Use the
GATSBY_prefix for environment variables (e.g.,GATSBY_NINETAILED_CLIENT_ID)
Example
Plain React (Vite)
- Place the provider at your app root
- Personalization is client-side only
- No SSR capabilities. Consider Next.js if you need server-side personalization.
Example
Environment variables
At minimum, for Next.js, you need:
For edge or server-side setups, you may also need NINETAILED_API_KEY and NINETAILED_ENVIRONMENT without the NEXT_PUBLIC_ prefix.
Add real values to .env.local and placeholders to .env.example. Never commit API keys or tokens to source control.