Manual experiments
A manual experiment has no DOM applicator. StatsKit decides the variant, but you render it. Use manual experiments for server-rendered pages, feature branches in your own code, backend pricing, or anything the tracker cannot reach into the DOM to change.
Assignment is still deterministic and sticky: the variant is a hash of the unit id plus the experiment key, so the browser and your server agree for the same unit.
Create one
Section titled “Create one”Create a manual experiment with type: "manual". A goal is required (the event name you will emit for conversions), and selector is omitted.
curl -X POST https://statskit.ai/api/v1/experiments \ -H "Authorization: Bearer vsk_live_…" \ -H "Content-Type: application/json" \ -d '{ "type": "manual", "name": "Onboarding flow test", "goal": "activated", "statsEngine": "bayesian", "variants": [ { "key": "control" }, { "key": "b" } ] }'The response includes the assignment key you use below. The first variant’s key must be control.
Get the variant
Section titled “Get the variant”Call statskit.experiment(key). It returns the variant key ("control", "b", …) or null, and fires the exposure on the first call for that visitor.
const variant = statskit.experiment("onboarding-flow-test-a1b2");
if (variant === "b") { showNewOnboarding();} else { showDefaultOnboarding();}POST /v1/experiments/:key/assign with { unit }. It returns the variant and logs the exposure.
curl -X POST https://statskit.ai/api/v1/experiments/onboarding-flow-test-a1b2/assign \ -H "Authorization: Bearer vsk_live_…" \ -H "Content-Type: application/json" \ -d '{ "unit": "user_8f3a", "url": "/onboarding" }'{ "experiment": "onboarding-flow-test-a1b2", "unit": "user_8f3a", "variant": "b" }url is optional. unit is required.
async function assign(experimentKey, unit) { const res = await fetch( `https://statskit.ai/api/v1/experiments/${experimentKey}/assign`, { method: "POST", headers: { Authorization: `Bearer ${process.env.VERSUCH_SECRET_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ unit, url: "/onboarding" }), }, ); const { variant } = await res.json(); return variant; // "control" | "b" | …}
const variant = await assign("onboarding-flow-test-a1b2", "user_8f3a");Use the same unit you convert on
Section titled “Use the same unit you convert on”Record the conversion
Section titled “Record the conversion”When the visitor completes the goal, record it against the same unit.
- Browser:
statskit.track("activated", { plan: "pro" })records a conversion tied to the assigned variant. - Server: emit the goal event server-side for the same unit.
Either way, the goal name must match the goal you set at creation. See Tracking conversions for the full track API and server-side emission.
statskit.track("activated", { plan: "pro" });