Add personalization to your Next.js website

Prepr CMS enables editors to create adaptive content directly in their content items to personalize elements of web pages. This makes setting up personalization really simple and effective in increasing engagement and conversions. This chapter of the Next.js complete guide shows you how to add personalization to your Next.js website.

At the end of this section, you'll see a personalized header in the home page for visitors interested in electric cars.

Personalized home page

The steps below make use of the Adaptive content in the Homepage content item from the Acme Lease demo data.

Home page content item

Homepage content item with Adaptive content for the Header and Car recommendations sections.

This chapter continues from the previous section, Set up data collection. If you haven't yet enabled Prepr tracking in your Next.js project, follow the steps in this section first. Otherwise, let's get started.

Set up personalization for the home page

You can show different personalized versions of the content to different groups (Segments) of visitors. To show the right variant to the right visitor:

  • Every visitor is given an ID that resolves to a segment they belong to.
  • In your front end, you need to send this ID along with the query to retrieve the right variant.
  • This is done by setting the value for the API request header, Prepr-Customer-Id, when you make the API request to retrieve the content.

By installing the Prepr Next.js package in the previous section, you've already prepared your API request headers.

Add customers to segments

For this setup we'll make use of the Electric Car Lovers segment in the Acme lease demo data. Make sure that the segment in your Prepr environment includes the condition, Customers who did view specific items, Landing Page Electric Car, at least once.

segment builder

If you need more details, checkout the Segments docs.

You previously enabled Prepr tracking in your website. This means a customer gets added to the Electric Car Lovers segment whenever they view the Landing Page Electric Car content item.

You can test this with the following steps:

  1. Go to the Electric Car landing page in your website using the slug electric-lease. For example, http://localhost:3000/electric-lease

    Electric Car landing page

  2. In your Prepr environment, go to the Segments page and click the Electric Car Lovers segment. You should see matching customers in this segment like in the image below.

    Electric Car segment customers

To make sure that customers in the Electric Car Lovers segment see Electric Car adaptive content when they visit the home page, you need to set the API request header, Prepr-Customer-Id, when you retrieve the page content. Based on this value, Prepr will check the segment that this customer belongs to and will retrieve the matching personalized variant.

Because you installed the Prepr Next.js package previously, your API request headers are already prepared.

Set the API request headers

Since the API request headers are already prepared, you can simply set the API request headers for your page. To set the API request headers, update your page.tsx with the highlighted code below:

./src/app/[[...slug]]/page.tsx
import HeaderSection from "@/components/HeaderSection";
import ImageAndTextSection from "@/components/ImageAndTextSection";
import {getClient} from "@/ApolloClient";
import {GetPageBySlugDocument, GetPageBySlugQuery} from "@/gql/graphql";
import {notFound} from "next/navigation";
import { getPreprHeaders } from '@preprio/prepr-nextjs'
 
async function getData(slug: string) {
    const {data} = await getClient().query<GetPageBySlugQuery>({
        query: GetPageBySlugDocument,
        variables: {
            slug: slug,
        },
        context: {
            // Call the getPreprHeaders function to get the appropriate headers
            headers: await getPreprHeaders()
        },
        fetchPolicy: 'no-cache',
    })
 
    if (!data) {
        return notFound()
    }
 
    return data
}
 
export default async function Page({params}: { params: { slug: string | string[] } }) {
    let {slug} = params
 
    if (!slug) {
        slug = '/'
    }
 
    if (slug instanceof Array) {
        slug = slug.join('/')
    }
 
    const data = await getData(slug)
    const elements = data.Page?.stack.map((element, index) => {
        if (element.__typename === 'SectionImageAndText') {
            return <ImageAndTextSection key={index} data={element}/>
        } else if (element.__typename === 'SectionHeader') {
            return <HeaderSection key={index} data={element}/>
        }
    })
 
    return (
        <div>
            <meta property='prepr:id' content={data.Page?._id}/>
            {elements}
        </div>
    );
}

Test your adaptive content

Now that people who visit the Electric lease landing page are being grouped into the Electric Car Lovers segment, you can test the adaptive content. To test the adaptive content for the Electric Car Lovers segment follow the steps below.

  1. Go to the Electric Car landing page in your website. For example: http://localhost:3000/electric-lease.
  2. Wait a few seconds and go back to the home page. You can now see the personalized header in the home page like in the image below.

Personalized home page

To see the non-personalized header, you can reset the cookies and refresh the page as follows:

  1. Right-click the page to Inspect the page, click the Application tab. Under the cookies, click your localhost. You'll notice the __prepr_uid cookie in the list.

  2. Right-click the localhost entry to Clear the cookies and refresh the page. You should now see the non-personalized header in the home page.

clear cookies

Add HTML attributes to track impressions and conversion events

Your personalization is running successfully, however there are no metrics being recorded yet. You can see this with the Awaiting data message at the top of the Adaptive content block in the Homepage content item.

Home page content item

To get Prepr to start showing some metrics data, you need to add HTML attributes to elements in your adaptive content. When you add these attributes, the tracking code you added in the previous section automatically tracks impressions and your chosen conversion events.

  1. To start collecting impressions and clicks, add the HTML attributes data-prepr-variant-key and data-prepr-variant-event to the Header section as shown in the highlighted code below. The impression is recorded when the Section header element scrolls into view. The click is recorded when the CTA button element is clicked.
./src/components/HeaderSection.tsx
import Link from "next/link";
import {FragmentType, getFragmentData} from "@/gql";
import {SECTION_HEADER_FRAGMENT} from "@/queries/GetPageBySlug";
 
interface HeaderSectionProps {
    data: FragmentType<typeof SECTION_HEADER_FRAGMENT>
}
 
export default function HeaderSection(props: HeaderSectionProps) {
    const {_context, title, image} = getFragmentData(SECTION_HEADER_FRAGMENT, props.data)
    
    return (
        <div className='px-4 md:px-10 lg:px-20' data-prepr-variant-key={_context?.variant_key}>
            <div className='mx-auto max-w-7xl w-full'
            >
                <div className='flex flex-wrap gap-y-8 py-16 md:flex-nowrap flex-shrink-0'>
                    <div
                        className='flex items-start justify-start flex-grow-0 flex-col space-y-16 md:basis-8/12 lg:basis-7/12'>
                        <h1 className='text-neutral-900 text-5xl font-medium lg:text-6xl'>
                            {title}
                        </h1>
                        {/* Searchbar */}
                        <div className='flex items-stretch justify-stretch w-full sm:max-w-xl rounded-full'>
                            <div
                                className='flex w-full justify-between rounded-l-full border-2 border-blue-600 bg-white px-4 py-2 lg:px-8 lg:py-4'>
                                <div
                                    className='flex w-full basis-5/12 items-center justify-between gap-3 md:gap-6 text-lg md:text-xl text-black hover:cursor-pointer lg:text-2xl'>
                                    <span>Brand</span>
                                    <TriangleDownIcon/>
                                </div>
                                <div className='mx-4 h-10 border-l-[1px] border-l-black lg:mx-5'></div>
                                <div
                                    className='flex basis-5/12 items-center justify-between gap-3 md:gap-6 text-lg md:text-xl text-black hover:cursor-pointer lg:text-2xl'>
                                    <span>Model</span>
                                    <TriangleDownIcon/>
                                </div>
                            </div>
                            <Link
                                href='#' data-prepr-variant-event
                                className='flex items-center text-nowrap rounded-r-full bg-blue-600 px-4 text-base md:text-lg font-bold text-white hover:cursor-pointer hover:bg-blue-700 lg:px-8 lg:text-2xl'>
                                FIND A CAR
                            </Link>
                        </div>
                    </div>
                    <div className='flex w-full justify-end md:basis-6/12 lg:h-[23.75rem] lg:basis-7/12'>
                        <img
                            src={image?.url || ''}
                            alt={image?.caption || ''}
                            className='object-contain'
                        />
                    </div>
                </div>
            </div>
        </div>
    )
}
 
function TriangleDownIcon() {
    return (
        <svg
            xmlns='http://www.w3.org/2000/svg'
            width='18'
            height='18'
            viewBox='0 0 18 18'
            fill='none'>
            <path
                d='M9.86603 16.5C9.48112 17.1667 8.51888 17.1667 8.13398 16.5L2.0718 6C1.6869 5.33333 2.16802 4.5 2.93782 4.5L15.0622 4.5C15.832 4.5 16.3131 5.33333 15.9282 6L9.86603 16.5Z'
                fill='currentColor'
            />
        </svg>
    )
}

If you want to track a conversion other than a click event, e.g. a quote request, then set your data-prepr-variant-event to the custom event. For example: data-prepr-variant-event="QuoteRequest". Check out the Personalization doc for more details.

  1. To start recording metrics, go to the home page in your website, click the FIND A CAR button.

  2. Now when you view the adaptive content in your Homepage content item, you can click the Metrics link and see the number of impressions and clicks like in the image below.

Adaptive content metrics

Congratulations! You have successfully set up personalization with metrics in your Next.js website. Now, you can install the preview bar to your website.

Was this article helpful?

We’d love to learn from your feedback