Holdout test results
/v1/analytics/holdoutWhat the chat widget adds, measured: the visits that saw it against
the visits the organization's holdout test kept from it (set with
holdoutPercent in PATCH /v1/widget/settings). Both arms are read
the same way, from the storefront's own cart: the share of visits
that added anything (conversionRate), and cart value added per
visit, as the store's cart reported it. The widget arm also carries
what it did with the widget (opens, messages, adds Stylor made, adds
of products it had shown, counted by the same rules as the rest of
analytics).
Reading it
comparison holds each difference (widget minus holdout), its
relative lift, a 95% confidence interval (low, high) and a
two-sided pValue. verdict calls it:
early: the smaller arm has fewer than 200 visits (visitsNeededsays how many more).split_off: the arms did not come out at the share set, so visits were lost on one side; nothing should be read from the figures.widget_betterorwidget_worse: the conversion rate differs at 95% confidence.no_difference_yet: enough visits, and no difference at that confidence.
Visits whose arm was forced (the stylor_arm store-page parameter)
are left out. Figures are read from daily rollups, so today's trail by
a few minutes. A visit open across midnight counts on both days.
Query parameters
1Which test. The running one, else the one that ended last, when absent.
Response
test and results are null when the organization has never run one.Every test, the running one first.
The test.
The share of visits held out.
When it started.
When it ended; null while running.
Whether it is the running test.
The test read, shaped as an entry of tests.
verdict, visitsNeeded, confidence, arms (widget and holdout: visits, convertedVisits, conversionRate, cartAdds, cartValueCents, cartValuePerVisitCents; the widget arm also launcherVisits, openedVisits, messagedVisits, assistedCartAdds, stylorCartAdds, stylorCartValueCents), comparison (conversionRate and cartValuePerVisitCents, each treatment, control, diff, relative, low, high, pValue, significant), split (expected, observed, pValue, ok), days, startDay, endDay, timezone.
Errors
20Every error is JSON with a single error string unless noted. Match on the status code; the message is for humans.
Holdout test not found: <holdoutId>No test with this id belongs to the key's organization.
curl -X GET "https://stylor.ai/api/v1/analytics/holdout" \
-H "Authorization: Bearer $STYLOR_API_KEY"{
"tests": [
{
"id": "hold_3f9a1c2b7d4e5f60",
"percent": 10,
"startedAt": "2026-10-01T09:00:00.000Z",
"endedAt": null,
"running": true
}
],
"test": {
"id": "hold_3f9a1c2b7d4e5f60",
"percent": 10,
"startedAt": "2026-10-01T09:00:00.000Z",
"endedAt": null,
"running": true
},
"results": {
"verdict": "widget_better",
"visitsNeeded": 0,
"confidence": 0.95,
"arms": {
"widget": {
"visits": 18412,
"convertedVisits": 1031,
"conversionRate": 0.056,
"cartAdds": 1290,
"cartValueCents": 7318400,
"cartValuePerVisitCents": 397.5,
"launcherVisits": 18390,
"openedVisits": 1402,
"messagedVisits": 911,
"assistedCartAdds": 214,
"stylorCartAdds": 88,
"stylorCartValueCents": 612300
},
"holdout": {
"visits": 2051,
"convertedVisits": 92,
"conversionRate": 0.0449,
"cartAdds": 109,
"cartValueCents": 640200,
"cartValuePerVisitCents": 312.1
}
},
"comparison": {
"conversionRate": {
"treatment": 0.056,
"control": 0.0449,
"diff": 0.0111,
"relative": 0.247,
"low": 0.0016,
"high": 0.0206,
"pValue": 0.022,
"significant": true
}
},
"split": {
"expected": 0.1,
"observed": 0.1002,
"pValue": 0.93,
"ok": true
},
"days": 34,
"startDay": "2026-10-01",
"endDay": "2026-11-03",
"timezone": "America/Denver"
}
}