# Data Models and A/B Testing

With Builder, A/B testing works out of the box for Page and Section models, but data models require a bit more set up. In this article we will learn about A/B testing structure in Data models, rendering A/B tests, and delivering the correct variant to users.

## Prerequisites

To get the most out of this document, you should already be familiar with:

- [Data Models](/content/c/docs/models-data/index.html)
- [A/B Testing](/content/c/docs/abtesting/index.html)

## A/B test a data model in code with BuilderContent

A/B testing on a [Data model](/content/c/docs/models-data/index.html) follows the same process as testing a [Page](/content/c/docs/models-pages/index.html) or [Section](/content/c/docs/models-sections/index.html) model. Follow these steps to set up an A/B test for a Data model:

1. Create a Data model entry.
2. Add variants within the entry. Create as many variants as needed to test different content versions.
3. Wrap the data model content in a `<BuilderContent/>` component. This component selects the correct variant and persists the data across a user's session. It also supports server-side rendering (SSR). To enable SSR, pass the content to the content prop, just as you would with a `<BuilderComponent/>`.

The example below demonstrates an A/B test on a `buy-button-cta` Data model. The correct variant is selected and rendered as the call-to-action (CTA) text:

```javascript
import { BuilderContent } from'@builder.io/react'
export function MyComponent() {
  return (
    <BuilderContent model="buy-button-cta" content={buttonCTAContent}>
      {(variant, loading, fullContent) => (
        loading ? <Spinner /> : <button>{variant.ctaText}</button>
      )}
    </BuilderContent>
  );
}
```

**How this example works**

- `variant`: the selected data variant after the A/B test logic determines the correct variation.
- `loading`: a boolean that indicates whether the content is still being fetched.
- `fullContent`: represents the complete raw data from the server, including all variations.

When the content is still loading, a spinner displays. Once the correct variant is selected, its `ctaText` value displays inside a `<button>`.

This way the correct A/B test variation is delivered and persists across a user's session.

## A/B testing structure in Data models

The JSON below represents the data returned by a Data model entry that contains an active A/B test. A/B testing is implemented with the standard `data` property for the default option and a `variations` property containing key/value pairs for each data object for a given variant of the A/B test.

```json
{
  "results": [
    {
      "lastUpdatedBy": "2ej3Ldf2pKYWQiEMPKzdUGcUvU53",
      "folders": [],
      "data": {
        "date": 1699257600000,
        "image": "https://cdn.builder.io/api/v1/image/assets%2F988e5176e08a4773bb301a97f9e56493%2F2c2e0b2072104385b721d941710c8a2b",
        "author": {
          "@type": "@builder.io/core:Reference",
          "model": "author",
          "id": "bbbc29f3d2dc43b7ad820c7709749e42_3e9fc0cb1016406299b45ac368641c99"
        },
        "createdBy": "2ej3Ldf2pKYWQiEMPKzdUGcUvU53",
        "meta": {
          "kind": "data",
          "lastPreviewUrl": ""
        },
        "variations": {
          "1111aaddca3843029a7c5fafaed58ba4": {
            "testRatio": 0.5,
            "createdDate": 1699057084439,
            "data": {
              "date": 1699257600000,
              "image": "https://cdn.builder.io/api/v1/image/assets%2F988e5176e08a4773bb301a97f9e56493%2F70bc2dc8de36427bb19a86be64f1ba6c?format=webp",
              "author": {
                "@type": "@builder.io/core:Reference",
                "model": "author",
                "id": "bbbc29f3d2dc43b7ad820c7709749e42_3e9fc0cb1016406299b45ac368641c99"
              },
              "articleText": "The Pats defeated the Commanders 17-13 in a defensive battle on Sunday. Lorem Ipsum blablablablablabl bal bla b lablaa",
              "genre": "sports",
              "title": "Patriots Defeat Commanders In Close Game",
              "blurb": "New England bounces back in week 9",
              "slug": "pats-commanders"
            },
            "meta": {},
            "name": "Variation 1",
            "id": "1111aaddca3843029a7c5fafaed58ba4"
          }
        },
        "name": "pats-commanders",
        "id": "bbbc29f3d2dc43b7ad820c7709749e42_654c3085cc514cab8d028a5ab581c768",
        "rev": "cp41au6hjiv"
      }
    }
  ]
}
```

### How Builder.io Tracks A/B Test Variants

Each content entry in Builder has a unique content ID, which can be one of the following:

- A standalone unique ID, for example, `bbbc29f3d2dc43b7ad820c7709749e42_654c3085cc514cab8d028a5ab581c768`.
- A combination of your Public API Key and a unique ID, formatted as `{API_KEY}_{UNIQUE_ID}`.

To track A/B test variations, Builder uses a cookie named `builder.tests.{builderId}`. This cookie stores one of two values:

1. The Builder ID, which indicates that the default content is being served.
2. The variation key, which represents the selected A/B test variant.

For example, given the following Data model entry:

```json
"variations": {
  "1111aaddca3843029a7c5fafaed58ba4": {
    "testRatio": 0.5,
    "data": {
      "title": "Stay cool this summer"
    }
  }
}
```

The selected variation would be `1111aaddca3843029a7c5fafaed58ba4`, meaning the cookie `builder.tests.{builderId}` would store this value.

This cookie-based tracking method applies to all A/B tests in Builder, not just those for Data models.

## Handle A/B tests in rendering Data model

When rendering data from a Data model within a Builder components (for example, when setting up [blog templates](https://forum.builder.io/t/dynamic-blog-article-using-next-js/3613)), it's vital to wrap the `<BuilderComponent>` within a `<BuilderContent>` tag.

If you don't, the `<BuilderComponent>` won't be aware of the A/B test cookie for the given data and will only return the default data (from the `data` object in the JSON).

### Get the correct variation

Consider the following example. Begin with raw data stored in the `articleData` variable, obtained through a `builder.get()` call. Pass this data to the `content` prop within the `<BuilderContent/>` component.

```javascript
return (
  <>
    <Head>
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      {!articleData && <meta name='robots' content='noindex' />}
    </Head>
    <BuilderContent model="article" content={articleData}>
      {(data, loading, fullContent) => {
        //data is the data property after the correct variation is chosen
        //loading is the loading state, that returns true while content is being fetched
        //fullContent represents the raw data from the server that contains all variations
        return (
          <>
            <BuilderComponent model="blog-template" content={articleTemplate} data={{ article: data }} />
          </>
        )
      }}
    </BuilderContent>
  </>
);
```

This `data` object is now ready for rendering with the `<BuilderComponent>`. The `articleTemplate` variable specifies the desired Section model, indicating that you want to render that specific segment with the winning variation provided as the `data` field.
