> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abtestly.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtime bindings

> Every name available inside a variant's JavaScript. What each one is, where it comes from, why the order matters.

Every variant's JavaScript runs inside a function that gets a small
set of names passed in as function arguments. These are the runtime
bindings.

## The names

| Binding                | What it is                                            | Type   |
| ---------------------- | ----------------------------------------------------- | ------ |
| `ABTESTLY_EXP_ID`      | The experiment's UUID                                 | string |
| `ABTESTLY_EXP_KEY`     | The experiment's short key (e.g. `checkout-simplify`) | string |
| `ABTESTLY_VARIANT_KEY` | The variant's short key (e.g. `control`, `variant-1`) | string |

Legacy aliases exist for backwards compatibility (`EXP_ID`,
`VARIANT_KEY`), do not rely on them for new code.

## The order

If you inspect the compiled variant function, the parameters land at
specific positions. The exp key is `arguments[4]`. This ordering is
stable, a new binding at a later position does not shift existing
ones.

Rule of thumb: reference the bindings **by name**, not by position.
The names are stable public API; the positions are an implementation
detail.

## Using them

Inside variant JS:

```js theme={null}
console.log('Applying', ABTESTLY_EXP_KEY, ABTESTLY_VARIANT_KEY);

// Key your own storage per-variant
localStorage.setItem(`myapp:${ABTESTLY_EXP_KEY}:${ABTESTLY_VARIANT_KEY}`, '1');

// Track a variant-scoped custom event to your own analytics
window.analytics?.track('variant_applied', {
  experiment_key: ABTESTLY_EXP_KEY,
  variant_key: ABTESTLY_VARIANT_KEY,
});
```

## Why the key and not just the UUID

The UUID is stable but not human-readable. The key is short,
human-readable, and immutable, cloning an experiment mints a new
key so referencing by key does not silently target the wrong test.

If your goal is "log which variant applied", the key is what a human
reading logs wants to see.

If your goal is "call an internal API that stores per-experiment
state", either works, the UUID is a slightly better primary key
because it is opaque and cannot be confused with anything else.

## What is *not* in scope

* **`this`.** The variant function's `this` is set to the runtime's
  internal apply context, not `window`. Reach for `window` explicitly
  if you need it.
* **Any DOM helper.** Use `document.querySelector`, `abtestly.waitFor`,
  or your own libraries, the runtime does not inject jQuery-shaped
  shortcuts into scope.
* **A framework's runtime.** React, Vue, and friends are not
  auto-imported. If your variant needs a framework, load it via
  [Dev libraries](/build/dev-libraries) or from the page itself.

## `onApply` callback signature

If you use `abtestly.onApply(...)`, the callback receives an
`ApplyContext` object with:

* `experimentId` and `experimentKey`, same as the bindings above.
* `variantKey`, same as the binding.
* `routeRevision`, a monotonic counter that ticks on every SPA
  route change. Compare against it inside an async apply to detect
  supersession:

```js theme={null}
abtestly.onApply(ABTESTLY_EXP_ID, async (ctx) => {
  const startRev = ctx.routeRevision;
  const data = await fetchSomething();
  if (ctx.routeRevision !== startRev) return; // superseded, abort
  doThingWith(data);
});
```

## Stability

The three canonical names, `ABTESTLY_EXP_ID`, `ABTESTLY_EXP_KEY`,
`ABTESTLY_VARIANT_KEY`, are stable public API. They do not change
without a major version bump. Legacy aliases stay for at least one
major version.
