JavaScript API tests
JavaScript API tests let you render each variant yourself in your own theme or app code, using window.abtest to ask which variant a visitor is assigned to.
What a JavaScript API test is
The other three test types change what the visitor sees for you: URL tests redirect between two page URLs, template tests serve an alternate theme template via ?view=, and theme tests compare a duplicate theme via ?preview_theme_id. None of them touch your code, and the app never creates or edits theme files.
A JavaScript API test is different. Sofcy - A/B Test & CRO still assigns each visitor to a variant and keeps that assignment stable, but you render the difference. Your theme or app code asks the storefront API which variant is active for this visitor and then shows the matching experience — a different headline, a rearranged section, a new button, a swapped layout, whatever you can express in code. Sofcy - A/B Test & CRO handles assignment, targeting, and measurement; you handle the rendering.
This is the most flexible test type and the only one that requires code. Every test type — including the JavaScript API type — is available on every plan. The Base plan lets you keep any 2 distinct test types in play at once (across draft, running, and paused experiments); Premium is unlimited. Use it when the change you want to test cannot be expressed as a separate URL, template suffix, or theme.
JavaScript API tests need developer work. If you only need to compare two pages, an existing template suffix, or a duplicate theme, use a URL, template, or theme test instead — none of those require code.
Requirements
- The app embed must be enabled. The
window.abtestobject is provided by the Sofcy - A/B Test & CRO storefront app embed (theme app extension). Enable it under Online Store > Themes > Customize > App embeds, and keep the Web Pixel enabled so views, conversions, and revenue are recorded. - You need to add code. The variant rendering lives in your theme (Liquid/JavaScript) or in your own storefront app — Sofcy - A/B Test & CRO does not generate it.
- An active plan. Every test type, including JavaScript API, is available on every plan; the Base plan allows any 2 distinct test types in play at once, Premium is unlimited. See Plans.
The core pattern
Every JavaScript API test comes down to one question: is a given variant active for this visitor? You answer it with window.abtest.isHypothesisActive(variantId), which returns a Promise<boolean>; resolve it and branch your rendering on the result.
const active = await window.abtest.isHypothesisActive("<variant-id>");
active
? renderVariant() // the change you are testing
: renderControl(); // the original experience
A more complete example that waits for the API to be ready before checking:
<script>
window.abtest = window.abtest || {};
(window.abtest.q = window.abtest.q || []).push(function () {
// isHypothesisActive returns a Promise — resolve it before branching.
window.abtest.isHypothesisActive("VARIANT_ID_FROM_APP").then(function (active) {
if (active) {
// Visitor is in this variant — render your version.
document.querySelector(".hero__title").textContent =
"Free shipping on every order";
}
// Otherwise do nothing and let the original render.
});
});
</script>
Because you own the rendering, you decide how the variant looks and you are responsible for keeping the control (unchanged) path correct. Assignment stays stable for a visitor, so repeated calls for the same variant id return the same answer across their visit. For the exact method signatures, the ready queue, and how to check more than one variant, see the JavaScript API reference.
To avoid a flash of the control before your variant renders, keep the changed element hidden or neutral until the API is ready, then reveal it. The JavaScript test workflow covers this pattern end to end.
Where to get the variant id
The variantId you pass to isHypothesisActive() comes from the app, not from your code. When you create a JavaScript API test, each variant is assigned an id that you copy into your rendering logic.
- In the Sofcy - A/B Test & CRO admin, create a new experiment and choose the JavaScript API test type.
- Define your variants (control plus one or more variations).
- Copy each variant's id from the test setup screen.
- Reference those ids in your theme or app code with
isHypothesisActive().
Treat the ids as fixed strings. If you recreate the test, the ids change, so update your code to match.
Automatic vs manual trigger
A JavaScript API test can start measuring in one of two ways, which you choose when you set up the test.
| Trigger | When the visitor is entered into the test | Use it when |
|---|---|---|
| Automatic | As soon as the page loads and the visitor matches your targeting rules, the app assigns them and counts the view. | The tested element is on the page from the start — for example a landing page headline or a product-page layout. |
| Manual | The visitor is entered only when your code signals that the relevant moment has been reached. | The tested experience appears later or conditionally — after a tab is opened, a step is reached, or content is rendered by your own script. |
With automatic trigger you generally only need to call isHypothesisActive() and render. With manual trigger you also tell the API when the visitor should be entered, so that a view is not counted for people who never actually reach the tested experience. The exact call and lifecycle for manual triggering are documented in the JavaScript test workflow.
Manual triggering keeps your results honest: a visitor who never sees the tested element should not count as having been tested. Choose manual when the change is below the fold, behind an interaction, or rendered asynchronously.
Targeting, results, and revenue
JavaScript API tests behave like every other test type once they are running. You can restrict who enters with audience targeting rules — device, new vs. returning, and country — and only matching visitors are assigned.
Results are computed with Bayesian statistics: chance to beat control per variant, per-variant conversion rate and revenue, and segment breakdowns. Because assignment is stamped as a cart attribute, revenue attribution still credits the right variant even when checkout happens through Shop Pay or a third-party checkout. When a winner is clear you can apply it, though for a JavaScript API test "applying" the winner in your storefront means keeping the winning variant's code — the app manages assignment and reporting, not your theme files.
Next steps
- JavaScript API reference — the full
window.abtestsurface, includingisHypothesisActive(). - JavaScript test workflow — a step-by-step build, including automatic and manual triggering.
- Data and consent — how the API behaves with opt-out consent.
- Audience targeting and Results and statistics.