Quick Start for Developers (Next.js)

This guide describes the steps you need to follow to integrate Ninetailed into your website with Next.js.


This guideline walks you through setting up and integrating Contentful, Ninetailed, and Next.js. In this guide, you'll find:
  • How to set up Ninetailed App on Contentful
  • How to install the SDK for Next.js
  • How to use Ninetailed Profiles in Next.js
  • Steps you need to follow to personalize components in Next.js
  • How to integrate Google Analytics with Ninetailed
  • Next steps and further integrations

Step 1: Set Up the Ninetailed App on Contentful

  1. 1.
    Install the Ninetailed App from the Contentful marketplace.
  2. 2.
    Select the organization and space you want to install the app.
  3. 3.
    Authorize the app access and continue installing Ninetailed.
  4. 4.
    Connect your Contentful space to Ninetailed following the Contentful installation steps
  5. 5.
    Get your API Key. You can find your API Key in the Ninetailed account dashboard (You will need your API Key in the next steps):
Ninetailed API key
Find more information about installing Ninetailed app in the Contentful section.

Step 2: Frontend Integration for Next.js

In this step, you'll find the steps you need to follow to add Ninetailed to Next.js. With the Next.js SDK, you can add dynamic content for personalization to any component.

1. Install Next.js SDK

Install the @ninetailed/experience.js-next module via npm or yarn.
Install module via npm:
npm install @ninetailed/experience.js-next
Install module via yarn:
yarn add @ninetailed/experience.js-next

How to Use

This is what the configuration of @ninetailed/experience.js-next looks like:
import React from 'react';
import {
} from '@ninetailed/experience.js-next';
export const App = () => {
return (<>
<NinetailedProvider clientId={YOUR_API_KEY}>
<YourAppCode />
Your API Key can be found within the Ninetailed dashboard at, under the left sidebar item

2. Profile

Ninetailed manages visitor profiles automatically, which gets updated via page(), track(), identify() events. Ninetailed uses profiles internally to calculate your personalizations and render merge tags in your rich text components.
type Profile = {
* An id which can get set by you - e.x. CRM id.
id?: string;
* This is an internal identifier to find the visitor in our system.
anonymousId: string;
* The calculated audiences the visitor is in.
audiences: string[];
* Tratits you have set via identify(id: string, traits: Traits) calls.
traits: Traits;
* The current location of the user.
location: Location;
Traits is a JSON dataset that can be set by you through identify calls. Whenever you send new traits to our system we deeply merge the traits of the user. "Traits" are commonly used in merge tags to build inline personalization like const headline = Hey ${profile.traits.firstname}👋.
type Traits = {
[key: string]: string | number | boolean | Traits;
// example
const traits: Traits = {
"firstname": "Max",
"address": {
"street": "Allee 33"
"company": "Big fat Company"
Location is the last seen location of the user. You would normally use this to merge it into Richtext.
type Location = {
coordinates?: {
latitude: number;
longitude: number;
city?: string;
postalCode?: string;
region?: string;
regionCode?: string;
country?: string;
continent?: string;
timezone?: string;


The useProfile hook makes it really easy for you to access the profile of the visitor.
import { useProfile } from '@ninetailed/experience.js-next';
The hook delivers the profile and the loading and error state.
const Greeting = () => {
const {loading, profile, error} = useProfile();
return <p>Hey {profile.traits.firstname}, nice weather in {}!</p>

3. Analytics & Events

As a Ninetailed App, we need to know about the visitor currently viewing the website to personalize the content. Our customer data platform is in charge of this information. In any case, you need to provide events about the user to our API to generate a profile over time.
In order to make this process as simple as possible, Ninetailed provides the page(), track(), and identify() methods which can be used via the useAnalytics hook or the window object of the browser, for example, in a Tag Manager.


The useNinetailed hook provides the event tracking functions inside your React components.
import React from 'react';
import { useNinetailed } from '@ninetailed/experience.js-next';
const CallToAction = () => {
const { track, page, identify } = useNinetailed();
return (<button
onClick={() => { track('My Event'); }}
Click Me


Page View
Page views should be sent on every page change. Our SDK populates all data needed as, referrer, url, user-agent and other properties to be consumed by the API.
type Page = () => Promise<void>;
Track events are used to describe special actions the user did, like signup or registered_for_newsletter.
type Track = (event: string) => Promise<void>;
By identifying a user you add a custom id to the profile, like a Hubspot id or an id from your internal database. Even more important, you can set traits about this customer, like the firstname, age or anything you want to personalize the content even more.
type Identify = (uid: string, traits: Traits) => Promise<void>;

Tag Manager

The Analytics SDK also add the page(), track() and identify() functions to the window object. That way you can also access them from a Tag Manager. We recommend sending page views directly from the code as soon as the SDK is initialized so the personalizations are not delayed.

4. Displaying Experiences

Experience Component

To make personalizing or experimenting with your components as seamless as possible Ninetailed provides an <Experience /> component that wraps the component you'd like to personalize or experiment on. It automatically detects the properties needed from the wrapped component and also applies a experiences property.
import React from 'react';
import { Experience } from '@ninetailed/experience.js-next';
type HeadlineProps = {
text: string;
const Headline: React.FC<HeadlineProps> = ({ text }) => {
return <h1>{text}</h1>
export const Page = () => {
// These variants normally come from Contentful, just inlined here to see the structure ]
const experiences = [
text: "We build super nice websites for enterprise companies!",
audience: {
id : "enterprise-audience-id" // variants have an audience id, this id is usualy from the Ninetailed SDK
return (<Experience
id="Baseline ID"
text="We build websites for everbody" // this is the baseline for user which are not in a audience.

Inline Personalization

The Ninetailed Contentful App allows your content creators to use inline personalization in Richtext fields. Inline personalization is done by adding embedded entries into the text. Also, using merge tags makes it very easy to use inline personalization.
import React from 'react';
import { documentToReactComponents, Options } from '@contentful/rich-text-react-renderer';
import { INLINES } from "@contentful/rich-text-types";
import { MergeTag } from '@ninetailed/experience.js-next';
const richTextOptions = (links: HeroHeadlineLinks): Options => {
const entryMap = new Map();
for (const entry of links.entries.inline) {
entryMap.set(entry?, entry);
return {
renderNode: {
const id =;
if (id) {
const mergeTag = entryMap.get(id);
return <MergeTag id={}/>;
return <>{`${node.nodeType} ${id}`}</>;
const Greeting = ({ text }) => {
return documentToReactComponents(text.json, headlineOptions(text.links))

Step 3: Connect with Google Tag Manager

By integrating Google Tag Manager with Ninetailed, you can send experience view data to any analytics systems you configure as Google Tag Manager tags.

How to Use

To use, install the package, include it in your project, and initialize the plugin with NinetailedProvider
import { NinetailedProvider } from '@ninetailed/experience.js-next';
import { NinetailedGoogleTagmanagerPlugin } from '@ninetailed/experience.js-plugin-google-tagmanager';
new NinetailedGoogleTagmanagerPlugin()
For more information on the GTM plugin, see the documention.

What's Next

After following these steps, you'll have Ninetailed integrated with Contentful that is ready to start creating personalized content for your audiences. Take a deeper dive by viewing the documentation of rendering experiments and personalizations and creating audiences.