---
title: "Page personalization and component A/B/n testing"
slug: "page-personalization-and-component-a-b-n-testing"
abstract: "The XM Cloud add-on enables Next.js applications to render personalized page variants, render component variants for A/B/n testing, and capture page view analytics."
---
# Page personalization and component A/B/n testing

The XM Cloud add-on integrates Next.js applications with the page personalization, component A/B/n testing, and analytics features of XM Cloud. The add-on uses [Next.js Middleware](https://nextjs.org/docs/advanced-features/middleware) architecture to enable personalization and A/B/n testing, combined with the [Events package in the Sitecore Cloud SDK](https://doc.sitecore.com/sdk/en/developers/005/cloud-sdk/sitecore-cloud-sdk-for-javascript.html) to capture page view events in the user's browser.

> [!note]
> Component A/B/n testing requires JSS version 22.1 or later.

The add-on is automatically included in all projects created using the starter kit, so you don't need to manually configure anything to enable personalization or A/B/n testing. For other projects, you can enable the add-on using the [JSS initializer](https://doc.sitecore.com/xp/en/developers/hd/20/sitecore-headless-development/the-jss-app-initializer.html).

The add-on includes the following elements for supporting personalization and A/B/n testing:

- A Next.js middleware plugin that calls the Cloud SDK.
- A React component for page view events using the Cloud SDK.
- A page props factory plugin.
- Additional environment variables for configuration.

> [!note]
> The add-on works in combination with the following features:
>
> -   [Personalized page variants](https://doc.sitecore.com/xmc/en/users/xm-cloud/en/create-a-page-variant.html) created in [Pages](urn:resource:component:895513).
>
> -   [A/B/n testing](https://doc.sitecore.com/sai/en/users/sitecoreai/a-b-n-testing.html) for comparing the performance of two component variants across different segments of your customer base.
>
> -   Analytics data from page and form events.
>
>
> When published, page and component variants are stored in the page layout data in Experience Edge.

## Page personalization overview

The following diagram shows how JSS sends a request to determine which variant of a personalized page to render for a visitor, based on how personalization is set up for that page. In this diagram, the middleware used to communicate with Sitecore Personalize is Cloud SDK.

![Sequence diagram showing the process for fetching personalized page variants.](https://doc.sitecore.com/api/markdown-image/sai/en/developers/jss/22/jss-sai/images/nextjs-personalze-addon.png)

Personalize identifies the page variant to display based on the context of the site visit, such as the visitor's geolocation details and their local time. It returns a page variant by rewriting the page path (personalized rewrite path).

The Next.js app parses the personalized rewrite path to get the details of the page variant. It then renders the layout and displays the correct personalized page to the visitor. Each time someone visits the page, the Cloud SDK captures [a page view event](https://doc.sitecore.com/sdk/en/developers/005/cloud-sdk/en/concepts-tracking.html) that can be used in web analytics, segmentation, personalization, and more.

> [!note]
> Your site must have [analytics identifiers](https://doc.sitecore.com/sai/en/users/sitecoreai/create-and-manage-sites.html) for analytics to work. They're added automatically in most cases, such as when you [create an environment using the starter kit](https://doc.sitecore.com/sai/en/developers/sitecoreai/getting-started-with-sitecoreai.html).

## Component A/B/n testing overview

The following diagram shows how JSS requests and renders component variants whenever someone visits a page on which one or more component A/B/n tests are running. In this diagram, the middleware used to communicate with Personalize is Cloud SDK.

![Sequence diagram showing the process for fetching component variants.](https://doc.sitecore.com/api/markdown-image/sai/en/developers/jss/22/jss-sai/images/XMC_JSS_Component_AB_Testing_Flow.png)

When the visitor accesses the page, a request is sent to Personalize. If component A/B/n tests are running on the page, Personalize selects one variant of the component being tested and returns the corresponding variant ID (if more than one component is being tested, it returns a variant ID for each of those components). The component ID or IDs are then used to fetch layout data and are added to the personalized rewrite path for the page.

## Understanding the personalized rewrite path

The personalization implementation in the Next.js XM Cloud add-on uses a rewrite path to identify variants for personalization and A/B/n testing.

The rewrite path is:

- Set by Personalize middleware, based on the identified page or component variants.
- Read by the Next.js app to manipulate the layout and feed to page view events.
- Used to [enable static generation for personalized page variants](https://doc.sitecore.com/sai/en/developers/jss/22/jss-sai/configure-personalization-in-a-next-js-jss-app.html "Configure personalization in a Next.js JSS app").

    > [!important]
    > Static generation does not currently work with component-level A/B/n testing.

The implementation encapsulates the logic for these processes so that you don't have to manipulate this path directly. However, it's helpful to understand how these paths are constructed to help you troubleshoot or customize them.

For page personalization, the path includes a single page-level `variantID`. For component A/B/n testing, the path includes one or more component-level `variantID`s. The resulting path will have the following structure:

```plaintext
/_variantId_<variantId-1>[/_variantId_<variantId-2>/_variantId_<variantId-3>/.../]/<path>

```

For example:

- A page with the path `/foo/bar` and the personalized variant `1234` is represented by the path `/_variantId_1234/foo/bar`.
- A page with the path `/foo/bar` and component-level variants `component1_1234` and `component2_5678` is represented by the path `/_variantId_component1_1234/_variantId_component2_5678/foo/bar`.

## APIs

The XM Cloud add-on uses the following code artifacts to render personalized page variants:

### PersonalizeMiddleware

`PersonalizeMiddleware` is a Next.js middleware handler that enables page personalization and A/B/n testing.

The middleware:

1. Makes a call to Experience Edge to get personalization information about the page, including variants.

    The following example query requests a page variant ID for personalization:

    ```graphql
    query($siteName: String!, $language: String!, $itemPath: String!) {
      layout(site: $siteName, routePath: $itemPath, language: $language) {
        item {
          id
          version
          personalization {
            variantIds
          }
        }
      }
    }
    ```

2. Calls the personalization endpoint with request or user context to determine the page variant or component variants to display.

    ```js
    data = await this.graphQLClient.request<PersonalizeQueryResult>(this.query, {
      siteName,
      itemPath,
      language,
    });
    ```

    The following example response includes a page variant ID as requested:

    ```js
    {
      layout: {
        item: {
          id: '35D149DAEB2047E185F14E2BC484AF58',
          version: 1,
          personalization: { variantIds: [ '9521beac72a44ab4a457082f636910c6' ] }
        }
      }
    }
    ```

3. Rewrites the response to the specific page variant or component variants using the personalized rewrite path.

### normalizePersonalizedRewrite

The `normalizePersonalizedRewrite` function removes personalization data from a personalized rewrite path so that layout data can be appropriately retrieved. The function is used by the Page Props Factory `extractPath` function defined in the `src\lib\page-props-factory\extract-path.ts` file of a Next.js application with the Personalize add-on installed.

### getPersonalizedRewriteData

The `getPersonalizedRewriteData` function extracts personalization data (`variantId` and `componentVariantIds`) from a personalized rewrite path. The Page Props Factory plugin for personalization, defined in the `src/lib/papge-props-factory/plugins/personalize.ts` file, passes the data to the `personalizeLayout` function.

### personalizeLayout

The `personalizeLayout` function modifies layout data to use a specific variant based on the provided `variantId` parameter and an optional `componentVariantIds` parameter. The default layout is then modified based on the matching variants. The function also sets the `variantId` property on the Sitecore context.

### CdpHelper

The `CdpHelper` class provides the `getPageVariantId` function that gets the page variant identifier in the format required for the `pageVariantId` parameter of a page view event.

### getGroomedVariantIds

The `getGroomedVariantIds` function accepts a flat list of `variantIds` and returns an object containing one page-level `variantId` and the `componentVariantIds` array.

If the page is not personalized and does not have A/B/n testing running on any components, the object contains default data:

```js
{
  variantId: '_default',
  componentVariantIds: [],
}

```

If the page is personalized, `variantId` is specific to the assigned page variant. For example:

```js
{
  variantId: 'page-variant-12345',
  componentVariantIds: [],
}

```

If the page includes any component A/B/n testing, the `componentVariantIds` array lists the IDs of the assigned variant for each component. The following example represents a page containing two components with A/B/n testing:

```js
{
  variantId: '_default',
  componentVariantIds: ['component-ABC_variant-123', 'component-XYZ_variant-456'],
}

```

## Environment variables

You use environment variables to configure personalization in a JSS Next.js app.

The following table lists the environment variables specific to personalization.

- Variable: Description
- `NEXT_PUBLIC_PERSONALIZE_SCOPE`: Optional.Unique page identifiers are used to run personalization flows and analytics. However, if any of your pages were created through site serialization, identical page identifiers might exist across different XM Cloud environments.Use this variable to isolate personalization data between such XM Cloud environments. It creates a unique page or component personalization identifier for each environment.
- `PERSONALIZE_MIDDLEWARE_CDP_TIMEOUT`: Optional.Value in milliseconds. It allows you to fine-tune the timeout for CDP calls within the personalization middleware. If the timeout is exceeded, the user sees the default page.
- `PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT`: Optional.Value in milliseconds. It allows you to fine-tune the timeout for Experience Edge calls within the personalization middleware. If the timeout is exceeded, the user sees the default page.