Setting up personalization

Setting up personalization

Estimated duration: 15-30 minutes

This guide demonstrates how to set up personalization and the related metrics in your web application using the Prepr GraphQL API.

Introduction

Prepr lets you create personalized experiences with Adaptive content. With Adaptive content, content editors can make different versions of content for various visitor segments. You can then show the right content to each visitor based on their segment giving them a personalized experience. By doing the one-time setup detailed below, Prepr can track and measure the visitor interactions for each adaptive content element.

Use case

Let's look at an everyday use case. The marketing team wants to improve user experience and the click-through rate of the home page. They've decided to group their customers by those who want to lease electric cars. Based on this segment they add adaptive content to the home page to target these customers.

General website visitors
When customers navigate to the Acme Lease home page, they see a generic page like in the image below.

Acme lease home page

Visitors interested in leasing an electric car
When a potential customer searches for an electric lease car and clicks an Acme Lease ad, they are directed to the electric lease landing page on the Acme Lease website. If they visit the home page again later, they'll see content focused on electric lease cars instead of the generic home page above.

Personalized home page

For this use case, the front-end application has been set up to track each visitor's behavior based on their interests. When they view a the Electric Lease Landing Page, Prepr places them in the Electric Car Buyers segment.

The marketing team can then evaluate metrics in Prepr to measure conversions for each element with adaptive content and determine how well they perform against the generic home page.

Prerequisites

To implement adaptive content for the above example, you need to have the following set up in Prepr:

This guide uses the Home Page content item from the Acme Lease demo data. Take note that adaptive content is defined in a Stack field. Check out the marketers docs for more details on how to add adaptive content to a content item.

Home page content item

Set up personalization in your front end

Before setting up personalization in your front end, make sure the following items are in place:

Now you're ready to set up personalization in the following steps:

  • Step 1: Create a customer ID to track and link each visitor to a variant.
  • Step 2: Retrieve adaptive content using the API.
  • Step 3: Add HTML attributes to track impressions and conversion events.

Create a customer ID

If you're implementing a Next.js project, you can skip this step and install and use the Prepr Next.js package to get the customer ID for you. The Prepr Next.js package uses the __prepr_uid cookie. For your project, you could use your own ID to set the Customer ID instead.

To make sure each web app visitor sees the correct adaptive content when they view a personalized page, Prepr CMS identifies each visitor by a Prepr Customer ID. Based on this value, Prepr can determine which segment the customer belongs to and therefore the related personalized content.

By enabling Prepr tracking, it assigns each visitor a unique ID with a cookie called __prepr_uid. You can use this __prepr_uid value to set the Prepr Customer ID.

Follow the steps below to generate and store a Prepr Customer ID for each visitor:

  1. Check if the __prepr_uid cookie is set.
  2. If the cookie isn't set yet, meaning the first time this visitor views a page, generate a random ID.
  3. Set the __prepr_uid cookie value to the generated ID.
  4. Make this ID available to the web app as a global variable. This variable will be used for the Prepr Customer ID instead of the cookie.

This solution can best be implemented in the middleware of your web app where you have access to reading and setting cookies and can store a global variable. See the following example on how to set this up in the Next.js middleware.

middleware.ts
import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'
import { headers } from 'next/headers'
 
export function middleware(request: NextRequest) {
  //Get the cookie to check if it exists
  let prepr_uid = request.cookies.get('__prepr_uid')?.value
 
  let newResponse = NextResponse.next()
 
  // If the cookie doesn't exist yet, generate a random ID
  if (!prepr_uid) {
    prepr_uid = crypto.randomUUID()
    newResponse.cookies.set('__prepr_uid', prepr_uid, {
      maxAge: 1 * 365 * 24 * 60, // Set for one year
    })
  }
 
  // Create a global variable to make it available to the
  // rest of the web app for the Customer ID
  newResponse.headers.set('Prepr-Customer-Id', prepr_uid)
 
  return newResponse
}

Now that the global variable is set, we can later retrieve the Prepr Customer ID with this helper function:

utils.ts
import { headers } from 'next/headers'
 
export function getPreprUUID() {
  return headers().get('Prepr-Customer-Id')
}

For some frameworks, you could use the Session ID instead of the __prepr_uid cookie in your front end and use this value as the Prepr Customer ID to be sent to Prepr. See the example code snippet below.

$prepr_customer_id = Session::getId();

In this case, make the session persistent by setting the cookie's lifetime parameter to something like 90 days. This means that you get the same session ID even when a customer visits the site multiple times.

Now that the Customer ID is available you can continue the next step to retrieve the adaptive content.

Retrieve adaptive content using the API

Now it's time to retrieve the Home page content item including the adaptive content elements.

Copy the sample code below into your front-end application.

query GetPageBySlug {
    Page(slug: "/") {
        title
        _id
        content {
            __typename
            ... on Hero {
                _id
                sub_heading
                image {
                    url(preset: "Hero", width: 2000)
                    height
                    width
                }
                _context {
                    variant_key
                    variant_id
                }
                heading
                buttons {
                    button_type
                    text
                    external_url
                    link {
                        ... on Category {
                            _slug
                        }
                        ... on Page {
                            _slug
                        }
                        ... on Post {
                            _slug
                        }
                    }
                }
            }
            ... on Feature {
                _id
                heading
                sub_heading
                button {
                    button_type
                    text
                    external_url
                    link {
                        ... on Category {
                            _slug
                        }
                        ... on Page {
                            _slug
                        }
                        ... on Post {
                            _slug
                        }
                    }
                }
                _context {
                    variant_key
                }
                image_position
                image {
                    url(width: 870, height: 570)
                }
            }
        }
    }
}

To retrieve the page content, call the API using the query above and pass a customer ID as a header. The Prepr-Customer-Id header is required to determine which segment a visitor belongs to and as a result which variant a visitor gets.

--header 'Prepr-Customer-Id: <YOUR-CUSTOMER-ID>' 

Follow the Connecting front-end apps guide to learn more about retrieving content items in a specific framework.

As a response to your API request, Prepr sends the variant to be displayed. Your app then needs to build its response based on this variant. If you don't specify a customer ID in the header or the customer ID is for a visitor that does not belong to either segment, then the query response looks like the example below.

{
  "data": {
    "Page": {
      "title": "Homepage",
      "_id": "e0e89d7b-3642-4d19-bb48-6f0cd4a0ca08",
      "content": [
        {
          "__typename": "Hero",
          "_id": "846393bd-dbd0-45f3-8c26-7308c67e8ec7",
          "sub_heading": "Flexible car leasing made easy — drive your dream car today with affordable plans and zero hassle.",
          "image": {
            "url": "https://demo-patterns.stream.prepr.io/7enl9dd5j9u1/w_2000/img-1.png",
            "height": 520,
            "width": 1120
          },
          "_context": {
            "variant_key": "eyJpIjoiZTBlODlkN2ItMzY0Mi00ZDE5LWJiNDgtNmYwY2Q0YTBjYTA4IiwiZSI6IjhpZGJsOHYwNDRvIiwidiI6IjRkMmZlNWQxLTQxODktNDkwNS1hYWU4LWI5YmU3MTljM2YxOSIsImsiOiJBTExfT1RIRVJfVVNFUlMifQ==",
            "variant_id": "ALL_OTHER_USERS"
          },
          "heading": "Welcome to Acme
Lease",
          "buttons": [
            {
              "button_type": "PRIMARY",
              "text": "Find your car",
              "external_url": "/products",
              "link": null
            },
            {
              "button_type": "SECONDARY",
              "text": "Request a Quote",
              "external_url": "/contact",
              "link": null
            }
          ]
        },
        {
          "__typename": "Feature",
          "_id": "3176a1a9-568f-4fba-b9a8-4f7303aa2eec",
          "heading": "Business Leasing",
          "sub_heading": "Optimize your fleet with predictable costs, exclusive tax benefits, and the latest vehicle models. Whether you’re scaling up or refining your mobility strategy, we provide hassle-free leasing solutions so you can focus on growing your business—while we handle everything else.",
          "button": {
            "button_type": "PRIMARY",
            "text": "Learn more",
            "external_url": null,
            "link": {
              "_slug": "electric-lease"
            }
          },
          "_context": {
            "variant_key": "eyJpIjoiZTBlODlkN2ItMzY0Mi00ZDE5LWJiNDgtNmYwY2Q0YTBjYTA4IiwiZSI6Ijg1djZuNHAybnBrIiwidiI6ImFlNGI1NGEwLWUwMWEtNDZlNi04MzRiLTBmMjIxODBlZmU3NiIsImsiOiJBTExfT1RIRVJfVVNFUlMifQ=="
          },
          "image_position": "LEFT",
          "image": {
            "url": "https://demo-patterns.stream.prepr.io/3ahzddb2yuru/w_870,h_570,fx_00,fy_100/pexels-pavel-danilyuk-8425052.jpg"
          }
        },
        {
          "__typename": "Feature",
          "_id": "9e04bb7d-266a-4c54-aed7-2849c9369bb1",
          "heading": "Private lease",
          "sub_heading": "Drive a new car hassle-free with fixed monthly payments. Enjoy flexibility, no ownership worries, and full control over your budget.",
          "button": {
            "button_type": "PRIMARY",
            "text": "Learn more",
            "external_url": null,
            "link": {
              "_slug": "oldtimers"
            }
          },
          "_context": {
            "variant_key": "eyJpIjoiZTBlODlkN2ItMzY0Mi00ZDE5LWJiNDgtNmYwY2Q0YTBjYTA4IiwiZSI6Ijg1djZuNHAybnBrIiwidiI6ImU4MTFiOWY2LTk0YjUtNDY2Mi1hYzdiLWM4ZjliYzc5Y2I5MyIsImsiOiJBTExfT1RIRVJfVVNFUlMifQ=="
          },
          "image_position": "RIGHT",
          "image": {
            "url": "https://demo-patterns.stream.prepr.io/1bfnsywm13mg/w_870,h_570/pexels-ketut-subiyanto-4247821.jpg"
          }
        }
      ]
    }
  }
}

If the customer ID in the header matches a visitor that belongs to the Electric Lease Buyers segment, then the query response looks like the example below.

{
  "data": {
    "Page": {
      "title": "Homepage",
      "_id": "e0e89d7b-3642-4d19-bb48-6f0cd4a0ca08",
      "content": [
        {
          "__typename": "Hero",
          "_id": "8def39fd-37ed-4c6c-a307-16150591c4a1",
          "sub_heading": "Discover a smarter way to drive with flexible electric car leasing. Enjoy cutting-edge technology, zero emissions, and lower running costs—all with hassle-free plans designed for you.",
          "image": {
            "url": "https://demo-patterns.stream.prepr.io/c4tq51jd2vw/w_2000,ex_1065,ey_0,ew_4576,eh_3661/pexels-hyundaimotorgroup-17395382.jpg",
            "height": 3661,
            "width": 6522
          },
          "_context": {
            "variant_key": "eyJpIjoiZTBlODlkN2ItMzY0Mi00ZDE5LWJiNDgtNmYwY2Q0YTBjYTA4IiwiZSI6IjhpZGJsOHYwNDRvIiwidiI6ImVkYzgwYWViLWMxNmQtNGY0Ni1iMjNkLWJkYzcwODI2N2RkYSIsImsiOiJFTEVDVFJJQy1DQVItQlVZRVJTIn0=",
            "variant_id": "ELECTRIC-CAR-BUYERS"
          },
          "heading": "Drive electric ⚡ Save more. Lease smarter.",
          "buttons": [
            {
              "button_type": "PRIMARY",
              "text": "Find your car",
              "external_url": "/products?category=electric-cars",
              "link": null
            },
            {
              "button_type": "SECONDARY",
              "text": "Request a Quote",
              "external_url": "/contact",
              "link": null
            }
          ]
        },
        {
          "__typename": "Feature",
          "_id": "99b11181-2e2b-4abf-bc37-6e72ed0fb463",
          "heading": "Electric Private Lease",
          "sub_heading": "Drive electric with affordable monthly rates, zero emissions, and no unexpected costs. Enjoy the latest EV models with a hassle-free private lease, including maintenance and road tax—just charge and go!",
          "button": {
            "button_type": "PRIMARY",
            "text": "Learn more",
            "external_url": null,
            "link": {
              "_slug": "electric-lease"
            }
          },
          "_context": {
            "variant_key": "eyJpIjoiZTBlODlkN2ItMzY0Mi00ZDE5LWJiNDgtNmYwY2Q0YTBjYTA4IiwiZSI6Ijg1djZuNHAybnBrIiwidiI6IjBmY2Y4NGEzLTYyNmMtNGExMy05NzMzLThlMmNjMTNlOWY4MCIsImsiOiJFTEVDVFJJQy1DQVItQlVZRVJTIn0="
          },
          "image_position": "RIGHT",
          "image": {
            "url": "https://demo-patterns.stream.prepr.io/4r4fu0i0b868/w_870,h_570,fx_48,fy_53/pexels-kindelmedia-9800029.jpg"
          }
        }
      ]
    }
  }
}

Check out the Manage adaptive content settings doc on how to enable the option to retrieve all matching variants.

Take note of the following important context fields:

  • kind - This returns a value of PERSONALIZATION when adaptive content is enabled for this element in the Stack.
  • variant_id - This returns a value of the segment for the variant, for example, ELECTRIC-CAR-BUYERS. This value is ALL_OTHER_USERS for the variant not assigned to any specific segment.
  • variant_key = A unique ID for the variant. You will use this field value in the next step to indicate which components need to be tracked for impressions.

You can do a test run with the adaptive content in Prepr before launching it on your live website:

  1. Open the API Explorer as described here.
  2. Copy and paste the GraphQL query above into the Operations pane.
  3. Run the query. You'll get the section header for ALL_OTHER_USERS because you didn't send a customer ID.
  4. Under the Header section, enter Prepr-Customer-Id with a Customer ID value in one of the segments. On the Segments screen, find the ID on the right when you edit a specific customer.
  5. Re-run the query. You'll now get one of the section headers with adaptive content.

Add HTML attributes to track impressions and conversion events

To track visitor interactions with adaptive content and get accurate metrics, you need to add HTML attributes to the page elements with adaptive content. When you add these attributes, the tracking pixel automatically tracks impressions and your chosen conversion events. Collaborate with the marketing team to choose the element and the corresponding event that indicates a conversion in the page with adaptive content.

For the example in this guide, there's a hero section with some specific text and a call-to-action button for each variant. This means you can report on the following types of visitor interactions:

  • Impressions: How many visitors viewed the hero section for each variant.
  • Clicks: How many visitors clicked the CTA button for each variant.

Prepr determines the conversion rate and other related metrics based on these events and shows you which variant performed best.

Follow the steps below to track impressions and conversion events:

  1. To start collecting impressions, add the HTML attribute data-prepr-variant-key to the Hero section. The impression is then recorded when the Hero element scrolls into view.

  2. Set the data-prepr-variant-key value to the _context.variant_key value returned in the API query response.

  3. To start collecting clicks, add the HTML attribute data-prepr-variant-event to the CTA button. The click is recorded when the CTA button element is clicked.

    ...   
      return ( 
          /* Set the HTML attribute with the matching data-prepr-variant-key to collect impressions for the whole section */
          <section className="bg-primary-50" data-prepr-variant-key={item._context?.variant_key}>
              <div className="mx-auto max-w-8xl p-spacing flex flex-col items-center md:flex-row gap-8 py-10 lg:py-20">
                  <div className="basis-6/12">
                      <h1 className="text-mb-5xl lg:text-7xl text-secondary-700 font-medium break-words text-balance">{item.heading}</h1>
                      <p className="text-mb-lg text-secondary-500 lg:text-lg mt-4 lg:mt-6 text-balance">{item.sub_heading}</p>
                      <div className="flex gap-4 mt-8 xl:mt-10">
                      <div>
                          {/* Set the HTML attribute to collect click events on the link */}
                          <Link href='#' data-prepr-variant-event><Button>Find your car</Button></Link>
                      </div>
                      </div>
                  </div>
              </div>
          </section>
      )
    ...

    Example code snippet with HTML attributes to track impressions and clicks

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".

That’s it. You've set up adaptive content in your website. Now, you can show each visitor a personalized hero section based on their clicking behavior.

As visitors interact with your web app, data will be collected and metrics will be visible in the adaptive content group. Go to the Home page content item to see the metrics.

Adaptive content metrics

After some time the marketing team will be able to evaluate metrics to determine how well the variants with adaptive content perform and adjust the content, if necessary.

Congratulations, you have successfully set up adaptive content on your web app.

Check out the marketers' adaptive content guide to get a full picture on the steps needed to add adaptive content to your website.

Other use cases

Other than segments based on visitor behavior, you can set up personalization for other criteria.

Segments from external CRM/CDP systems

It's possible to set up adaptive content based on segments maintained in other CDP/CRM systems. In this case, you need to reference these external segments from within Prepr using the segment unique identifier from that system.

To set up personalization for external segments, follow the steps below.

  1. Create a new segment in Prepr and set the ID value to the segment unique identifier copied from your CRM/CDP system.

  2. Retrieve adaptive content using the API with one difference — pass the Prepr-Segments header instead of the Prepr-Customer-Id. For more information, refer to our API documentation.

  3. If the segment is based on external customer data, ensure that your front end is connected to the external CRM/CDP system for data retrieval.

Want to learn more?

Check out the following chapters:

Schedule a free consultation

Do you want to get started with adaptive content but still have questions or want a demo?

Schedule a free call (opens in a new tab) with a Prepr solution engineer.

Was this article helpful?

We’d love to learn from your feedback