Overview
Experiments assigns each visitor to a variant of a configured A/B test and keeps that assignment sticky — the same visitor receives the same variant on every subsequent visit, resolved locally after the first assignment rather than requested from the API again.
Implementation
Install
Quick start
Experiment config belongs on Core — the experiments array you pass to initEmbeddables or EmbeddablesProvider. initExperiments reads it through core.getExperiments(); you never pass a separate experiments option.
The first call for a visitor with no stored assignment calls the Embeddables API, persists the result locally, and returns the variant. Every call after that reads the sticky value — no extra network round-trip, and getAssignedVariantKey() is typed so an invalid variant key for that experiment fails at compile time, not at runtime.
Assignment requests only ever send the project and experiment identifiers — never the visitor’s identity.
initExperiments options
Server (SSR)
The server entry reads experiment config from server.getExperiments() and sticky assignments from request cookies. It never writes cookies back — setting the response cookie stays in your SSR layer. serverAssignments is not a server option; pass it to initExperiments on the client to pre-seed variants the server already resolved before hydration.
initExperimentsServer options
React
Register Experiments through EmbeddablesProvider’s modules prop — the CLI generates the list in embeddables/_dist/modules — then read variants with useExperiment.
The generated list is ordered analytics → experiments → forms, so Analytics is on Core before Experiments initializes. The experiments config is read from the ambient Core instance’s getExperiments() — same as the non-React entry points. useExperiment({ experimentId }) returns { variantKey, variantTitle, status, error }, where status is one of:
useExperiment throws if the Experiments module is not enabled in your generated modules.
Assign on demand
useExperiment assigns as soon as it renders. To book the exposure at a specific step instead, use useAssignExperiment:
A later useExperiment({ experimentId: 'exp-hero' }) reads the sticky assignment back without another request. assignExperiment resolves to undefined while the module isn’t registered, and rejects when the request fails.
Analytics
Experiments never imports Analytics. In non-React code, create an Analytics client yourself and pass it in:
In React, the CLI orders modules analytics → experiments → forms, so Experiments auto-wires core.getAnalyticsInstance() for exposure tracking — you don’t wire anything by hand. Enable both modules in your config.yaml and the generated modules handles the rest.
When Analytics is enabled, each newly fetched assignment fires one experiment:assigned event — a sticky assignment already in storage never fires it again. If that event fails to send, the visitor’s variant assignment is unaffected; it was already persisted before tracking ran.