Assignment proxy

The storefront runtime asks this Shopify app-proxy endpoint which variant a visitor should see; the response drives every test type.

This page is informational. In almost every case you should call window.abtest, which wraps this endpoint for you. Reach for the raw request only when you are debugging or building a custom integration.

What it does

The assignment endpoint takes an anonymous visitor id and returns the visitor's variant for every live experiment on the shop. The app embed calls it once per page and then applies the results — a redirect, a template or theme parameter, or a signal your JavaScript reads through window.abtest.

It is served under the Shopify app proxy, so it lives on the merchant's own storefront domain rather than on the app host. A typical mounted path looks like /apps/ab/assign, where /apps/ab is the proxy prefix Shopify forwards to the app. The visible path depends on the merchant's app-proxy configuration, so treat /apps/ab/assign as an example, not a fixed URL.

Why it runs through the app proxy

Routing through the Shopify app proxy — instead of a cross-origin API on the app host — gives the storefront runtime three properties it depends on:

Request

The endpoint responds to a GET request forwarded by the Shopify app proxy. Shopify appends its own signed parameters (including shop and the HMAC signature); the runtime supplies the rest as query parameters.

ParameterRequiredMeaning
vidYesThe anonymous visitor id used for bucketing. Must be 8 to 128 characters.
previewNoForces one experiment to a chosen variant for merchant or QA preview, bypassing bucketing. Validated against live experiments, so a stale value is ignored.
activateNoAn experiment id. Enrols the visitor in a manual-trigger test they have now reached (see below).
shopAdded by ShopifyThe shop domain, taken from the proxy-authenticated session when present.

Targeting inputs — device, new vs returning, country, UTM parameters, referrer, and cookies — are read from the forwarded request itself, not passed as explicit parameters. See audience targeting.

The request is authenticated as a Shopify app-proxy call. A request that does not carry Shopify's HMAC signature is rejected with 401, so you cannot exercise the endpoint by hitting it directly outside the proxy.

Response

The endpoint always returns JSON with Cache-Control: no-store. On success the body has three fields:

{
  "assignments": [
    {
      "experimentId": "exp_123",
      "type": "url",
      "variantId": "var_b",
      "deferred": false,
      "variants": [
        { "id": "var_a", "isControl": true,  "config": { ... } },
        { "id": "var_b", "isControl": false, "config": { ... } }
      ]
    }
  ],
  "clientIntegrations": [ ... ],
  "preview": false
}
FieldMeaning
assignmentsOne entry per live experiment the visitor was assigned to.
clientIntegrationsEnabled client-side providers the runtime should initialise.
previewtrue when a preview override applied; tells the runtime not to cache or track the visit.

Assignment entry fields

FieldMeaning
experimentIdThe experiment this assignment belongs to.
typeThe test type: URL, template, theme, or JavaScript.
variantIdThe variant assigned to this visitor.
deferredtrue when the bucket is computed but the visitor is not yet enrolled — used by manual-trigger tests before activation.
variantsThe experiment's variants, each with id, isControl, and its config.

Manual-trigger and preview behaviour

Two query parameters change how enrolment works:

Failure handling

The endpoint is built to fail open — a broken app must never break the storefront:

Because the runtime handles all of this — the visitor id, the activate callback, preview, and applying each assignment — building against window.abtest and the JavaScript test workflow is the supported path. Read this page to understand what happens underneath.