Quick Start for Developers (Next.js)

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

Overview

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. Install the Ninetailed App from the Contentful marketplace.

  2. Select the organization and space you want to install the app.

  3. Authorize the app access and continue installing Ninetailed.

  4. Connect your Contentful account to Ninetailed App and then:

    1. create an organization

    2. confirm your settings

    3. complete installation

  5. Get your API Key. You can find your API Key in the Ninetailed App configuration (You will need your API Key in the next steps):

Find more information about the install process 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/client-sdk-nextjs module via npm or yarn.

Install module via npm:

npm install @ninetailed/client-sdk-nextjs

Install module via yarn:

yarn add @ninetailed/client-sdk-nextjs

How to Use

This is what the configuration of @ninetailed/client-sdk-nextjs looks like:

import React from 'react';
import {
PersonalizationProvider
} from '@ninetailed/client-sdk-nextjs';
export const App = () => {
return (<>
<PersonalizationProvider apiKey={YOUR_API_KEY}>
<YourAppCode />
</ProfileProvider>
</>);
}

Your API Key can be found in the Ninetailed App configuration.

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;
};

useProfile

The useProfile hook makes it really easy for you to access the profile of the visitor.

import { useProfile } from '@ninetailed/client-sdk-nextjs';

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 {profile.location.city}!</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.

useAnalytics

The useAnalytics hook provides the event tracking functions inside your React components. This is very handy if you want to send events from your code.

import React from 'react';
import { useAnalytics } from '@ninetailed/client-sdk-nextjs';
const CallToAction = () => {
const { track, page, identify } = useAnalytics();
return (<button
type="button"
onClick={() => { track('built new Rick'); }}
>
build new Rick
</button>);
}

Events

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

Track events are used to describe special actions the user did, like signup or registered_for_newsletter.

type Track = (event: string) => Promise<void>;

Identify

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. Personalization Components

Personalize Component

To make personalizing your components as seamless as possible Ninetailed provides a <Personalize /> component that wraps the component you'd like to personalize. It automatically detects the properties needed from the wrapped component and also applies a variants property.

import React from 'react';
import { Personalize } from '@ninetailed/client-sdk-nextjs';
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 variants = [
{
text: "We build super nice websites for enterprise companies!",
audience: "enterprise-audience-id" // variants have a audience id
}
]
return (<Personalize
component={Headline}
variants={variants}
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/client-sdk-nextjs';
const richTextOptions = (links: HeroHeadlineLinks): Options => {
const entryMap = new Map();
for (const entry of links.entries.inline) {
entryMap.set(entry?.sys.id, entry);
}
return {
renderNode: {
[INLINES.EMBEDDED_ENTRY]: (node) => {
const id = node.data.target.sys.id;
if (id) {
const mergeTag = entryMap.get(id);
return <MergeTag id={mergeTag.id}/>;
}
return <>{`${node.nodeType} ${id}`}</>;
}
}
};
};
const Greeting = ({ text }) => {
return documentToReactComponents(text.json, headlineOptions(text.links))
};

5. Server Side Rendering

You can use Next.js to fetch personalized content from the server and serve a fully updated page via server side rendering.

import {
PersonalizationProvider,
getServerSideProfile,
} from '@ninetailed/client-sdk-nextjs';
import { Hero } from './Hero';
const Page = ({ ninetailed, data }) => {
<PersonalizationProvider profile={ninetailed.profile} apiKey={API_KEY}>
<Personalize component={Hero} headline={data.headline} variants={data.variants}/>
</PersonalizationProvider>
}
export async function getServerSideProps() {
const profile = await getServerSideProfile(ctx, {
apiKey: API_KEY,
});
const data = await getPageData();
return { props: { ninetailed: { profile }, data } };
}
export default Page

Step 3: Connect with Google Analytics

By integrating Google Analytics with the Ninetailed, you can send Ninetailed events to Google Analytics for analysis.‌

How to Use

To use, install the package, include it in your project, and initialize the plugin with AnalyticsProvider

import { AnalyticsProvider } from '@ninetailed/client-sdk-nextjs';
<AnalyticsProvider plugins={
[
googleAnalytics({
trackingId: 'UA-1234567'
})
]
}
>

Find more information about how to integrate Google Analytics with Ninetailed.

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.

Find more information about how to create personalized content for your audiences in the Personalized Content and Audience Builder documents.