> For the complete documentation index, see [llms.txt](https://docs.elevateab.com/elevate-helpcenter/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.elevateab.com/elevate-helpcenter/developer-reference/storefront-data-reference.md).

# Storefront Data Reference

#### Reading Experiment Data on the Storefront

Elevate exposes active test and variation data directly on the storefront, so you can build your own integrations without calling our API — e.g., injecting a shipping line item property, reading the price applied by a price experiment, or reacting to a custom-code variation.

Everything below is available client-side, on the page, by the time a visitor can interact with it.

***

### 1. Where the data lives

EAB exposes two things on every storefront page:

| Source                   | What it holds                                              |
| ------------------------ | ---------------------------------------------------------- |
| `window.eab_data`        | All active test definitions + store/environment info       |
| Cookies (`ABTL`, `ABAU`) | Which tests **this visitor** is bucketed into / exposed to |

The pattern for almost any integration is:

1. Read the **cookie** to learn which variation the visitor is in.
2. Read **`window.eab_data`** to learn what that variation actually changes (price, content, etc.).

> **Tip:** the fastest way to learn the shape for a given store is to open the browser console and run `console.log(window.eab_data)` and `document.cookie`. The structures below describe what you'll see.

***

### 2. `window.eab_data`

Top-level shape:

```js
window.eab_data = {
  allTests: { /* keyed by testId — see §3 */ },
  selectors: { /* internal CSS/selector config used by our scripts */ },
  currencyFormat: "${{amount}}",          // store money format string
  environment: {
    rootUrl: "/",
    themeId: 123456789,
    themeRole: "main",
    activeCurrency: "USD",                // current presentment currency
    template: { suffix: "", type: "product" },
    isThemePreview: false,
    customerData: {                       // present if a customer is logged in
      loggedIn: true,
      id: 987654321,
      ordersCount: 3,
      totalSpent: "1500.00",
      tags: "vip"
    }
  }
};
```

The two fields you'll use most are **`allTests`** and **`environment.activeCurrency`**.

***

### 3. `window.eab_data.allTests`

An **object keyed by test ID** (not an array). It also contains a reserved `settings` key that is **not** a test — skip it when iterating.

```js
window.eab_data.allTests = {
  settings: { /* global app settings — NOT a test, skip it */ },

  "EAB-TEST-ID-1": { data: { ... }, "<variationId>": { ... }, ... },
  "EAB-TEST-ID-2": { data: { ... }, "<variationId>": { ... }, ... }
};
```

Each test object has:

* a **`data`** key — metadata about the test (§3.1)
* one key **per variation**, keyed by **variation ID** (§3.2)

#### 3.1 `allTests[testId].data` — test metadata

Common fields (exact set depends on the test type):

| Field                                | Meaning                                                                                                                             |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `name`                               | The test name as shown in the Elevate dashboard                                                                                     |
| `type`                               | Test type — e.g. `"PRICE_PLUS"`, `"SHIPPING"`, `"CUSTOM_CODE"`, `"CONTENT"`, `"PAGE"`, `"PRODUCT"`, `"PRODUCT_GROUP"`, `"CHECKOUT"` |
| `isLive`                             | `true` when the test is actively running                                                                                            |
| `currencies`                         | (price tests) currencies the test applies to, e.g. `["USD"]`                                                                        |
| `pathnames` / `excludePathnames`     | (content/custom-code) URL patterns the test runs on                                                                                 |
| `testProducts` / `productIds`        | (product/price tests) the products in the test                                                                                      |
| `collections` / `testPages` / `page` | (page tests) where the test applies                                                                                                 |
| `productSelection`                   | `"specific"`, `"exclude"`, or `"templates"`                                                                                         |

#### 3.2 `allTests[testId][variationId]` — a variation

Every key on the test object **other than `data`** is a variation, keyed by its **variation ID** (these IDs match the Elevate dashboard, so they map to readable names). Common fields:

| Field               | Meaning                                                         |
| ------------------- | --------------------------------------------------------------- |
| `variationName`     | Human-readable variation name                                   |
| `isControl`         | `true` for the control (original) variation                     |
| `trafficPercentage` | Allocation for this variation                                   |
| `templateID`        | (page tests) the Shopify template suffix used by this variation |
| `prices`            | (price tests) per-variant prices — see §6.1                     |
| `productVariants`   | (product tests) variant-level data                              |
| `customCode`        | (custom-code tests) `{ js, css, pathnames, excludePathnames }`  |
| `content`           | (content tests) `{ changes, elements, blocks, customCodes }`    |

> Field availability varies by test type. Inspect a real test with `console.log(window.eab_data.allTests["<testId>"])` to see exactly what's stored for the type you care about.

#### 3.3 Finding a test ID and variation ID by name

You won't usually know a test's ID or a variation's ID up front — you'll know the test's **name** because that's what you see in the Elevate dashboard. `allTests` gives you both IDs through that name, with no other lookup needed:

1. **Find the test ID:** open `window.eab_data.allTests` and loop over its top-level keys (skipping `settings`). Each key is a test ID, and each value has a `data.name` field. Match `data.name` against the test name you see in the dashboard — the key you found it under **is the test ID**.
2. **Find the variation ID:** once you have the test object, loop over its keys again (skipping `data` this time). Each remaining key is a variation ID, and each value has a `variationName` field. Match that against the variation name you're looking for — the key you found it under **is the variation ID**.

Example — given this test object:

```js
window.eab_data.allTests["303718da-350f-4b3c-8ff7-827809a1eaf6"] = {
  "46070": { variationName: "Control", isControl: true, /* ... */ },
  "46071": { variationName: "Variation 1", /* ... */ },
  data: { name: "Price Test 1", type: "PRICE_PLUS", /* ... */ }
};
```

If you're looking for the test named `"Price Test 1"`, that whole object is it — so `303718da-350f-4b3c-8ff7-827809a1eaf6` is the **test ID**. Within it, if you're looking for `"Variation 1"`, `46071` is the **variation ID**.

```js
// Find a test ID by name
const testId = Object.keys(window.eab_data.allTests).find(
  key => key !== "settings" && window.eab_data.allTests[key].data?.name === "123"
);

// Find a variation ID by name, within that test
const test = window.eab_data.allTests[testId];
const variationId = Object.keys(test).find(
  key => key !== "data" && test[key].variationName === "Variation 1"
);
```

> Once you've matched a test/variation by name this way, the IDs are stable for that test going forward — you don't need to re-match by name every page load if you're hardcoding a specific test in an integration.

***

### 4. Cookies — which variation is THIS visitor in?

EAB sets these cookies per visitor:

| Cookie      | Shape                             | Meaning                                                           |
| ----------- | --------------------------------- | ----------------------------------------------------------------- |
| `ABTL`      | `{ "<testId>": "<variationId>" }` | Every test the visitor is **bucketed into**, and which variation. |
| `ABAU`      | `{ "<testId>": true }`            | Tests the visitor has actually been **exposed to** (viewed).      |
| `eabUserId` | string                            | The EAB visitor ID (useful as a line item property).              |

`ABTL` is the source of truth for **"which variation is this visitor seeing?"** The variation IDs in `ABTL` match the keys in `allTests[testId]` (§3.2) and the IDs in the dashboard.

```js
// Example ABTL value:
// { "EAB-TEST-ID-1": "VARIATION-A", "EAB-TEST-ID-2": "CONTROL" }
```

***

### 5. Notes & caveats

* **`window.eab_data` is set by our script.** Make sure your code runs after it exists (it's injected high in the page). If `window.eab_data` is missing, either our script hasn't loaded yet or the store isn't set up.
* **Use `ABTL` for "what is this visitor seeing"**, and `allTests` for "what does that variation do." Reading `allTests` alone tells you what tests exist, not which one the visitor is in.
* **Skip the `settings` key** when iterating `allTests`.
* **Variation IDs are stable and match the dashboard**, so you can map them to readable names either from `variationName` or from the dashboard.
* **Don't know a test's ID or a variation's ID?** Match by name first — see §3.3.
* **Prices are in major units** (`"1100.00"`), while Shopify's `/cart.js` and `/products/{handle}.js` report prices in **cents** — divide those by 100 when comparing.
* **Currency matters for price tests** — always read `window.eab_data.environment.activeCurrency` and use the matching entry in `prices`.
* Don't mutate `window.eab_data` — treat it as read-only. To change what a visitor experiences, act on your own DOM / cart, not on our data object.

***

### A note on custom-code experiments

If you're running a **custom-code experiment**, you don't need to take any of the above into consideration. The custom code you provide will **only run on the specific pages you've configured** and **only for visitors in that variation** — Elevate handles the page targeting and variation bucketing for you. You can just write your code as if it's already on the right page for the right visitor.
