Write A/B tests as plain JavaScript and CSS.

ABTestly is code first. A variation is real JavaScript and real CSS that you author in a full editor, review with a static code check, and preview on your live site before a single visitor sees it. No generated selectors, no drag and drop, no hidden runtime tradeoffs.

The short version. Every variant is JavaScript, CSS, or a redirect URL, written in the Monaco editor. A variation code check reads your code back on every save. Global JS and curated dev libraries keep shared code out of each variant. Preview links show any variant on the real page without recording data. Review changes shows your edits as a diff before you save, and History keeps every saved version of each variant's code.

No visual editor, on purpose

Visual editors are useful for a copy tweak. Serious client side experiments often need production aware JavaScript, controlled CSS, reliable cleanup, and measurement developers can inspect. ABTestly makes that the default rather than the exception. You author JavaScript and CSS directly, target real routes and audiences, and measure exposures explicitly.

Code first does not mean workflow light. You still move from scope to QA to interpretation, without hiding a single technical decision.

How a variation is built

Every experiment has an Original, the unchanged control, plus one or more variants. Each variant carries three things:

Each variant has a JavaScript pane and a CSS pane. Most variants only need to wait for the target element to exist and then change it. If you have SPA support turned on, you pair the change with a cleanup so the DOM undoes itself on a route change.

The Monaco editor

Variant code is authored in Monaco, the code editor from VS Code, with syntax checking that runs on every change. Save is blocked when there is a syntax error, so a broken variant cannot go live. Cmd or Ctrl and S saves without leaving the editor, and either pane opens fullscreen.

Once an experiment has been running long enough for its results to matter, the variant code freezes to stop an accidental mid flight change from inflating your effect size. If you genuinely need to change a running variant you can pause, edit, and resume for a fresh epoch, or reset the data and start over. Both are confirmation gated.

Review every change, keep every version

Saving a running experiment republishes it, so a stray edit reaches visitors as soon as you save. Before you save, Review changes swaps the editor for a diff of your unsaved edits against the saved code, in the same Monaco editor: side by side when there is room, inline when there is not. It works on the JavaScript and the CSS tab, you can keep editing and save from the diff itself, and a note above the diff names any library you added or removed, since a code diff cannot show those. The experiment form offers the same comparison as Compare with saved, and so does the banner that recovers an autosaved draft.

The ABTestly variant code editor in Review changes mode on the variation.js tab. The saved code is on the left and your changes are on the right, with the changed lines highlighted: the button text changes from Secure checkout to Complete my order, the background color changes, and a new line adds a Free returns within 30 days note. The toolbar shows Libraries, Back to editor, Cancel and Save.
Review changes. Illustrative example, demo data.

Every save that changes a variant's code is kept as a version. Open History on a variant to list its versions, newest first, each with who saved it, when, and the test's status at the time. Pick any two to compare them, or use a quick pick:

The ABTestly History panel for Variant B, in the light theme. Under the Previous save, Since launch and Since last reset buttons, a note reads “No code changes since launch”. Below are four revisions: revision 4, ticked, saved by Tom while the test was Scheduled and marked as already the saved code; revisions 3 and 2, saved by Aisha and Lukas while the test was a Draft; and revision 1, the code before history began, marked Baseline. Every row has a Restore this version button.
The History panel after Since launch. Illustrative example, demo data.

Restore this version loads an earlier version into the editor as an unsaved draft and opens Review changes. Nothing is written until you save, and that save goes through every check a normal save does.

Versions are stored in ABTestly for the life of the experiment, so there is no Git or GitHub connection to set up. Experiments that existed before code history start with a baseline version of each variant. Anyone who can view an experiment can open its history, and the Activity log shows variant code changes as a diff. Read the documentation.

A second set of eyes on every variation

Because you write real JavaScript and CSS, ABTestly reads it back. Every publish, save, and resume runs a static review of your variation code and flags the mistakes that quietly break experiments. It never blocks your publish.

The check catches common mistakes before they reach visitors, a querySelector() that can return null, an eval() that breaks under a strict Content Security Policy, or variation CSS that hides the whole page instead of using the platform anti flicker option. It is a set of heuristics, not a guarantee. If you are comparing tools, it is worth asking each of them what happens to the code you write in it after you hit save. See what it checks.

Global JS for shared code

Global JS is a single JavaScript block that runs once per page, before any variant, for shared helpers, polyfills, or one time analytics wiring. Instead of copying the same utility into every variant, you define it once and let variant code use it. It runs after the consent gate has passed and the visitor is not opted out, and it is wrapped in a try and catch so an error there does not stop variant JavaScript from running. The editor counts bytes and refuses to save over a 50 KiB cap. Global JS is available on the Pro plan and above.

Dev libraries, attached once

When two variants both need a carousel library you do not want two copies on the page. Attach a curated library, such as Splide or GLightbox, to a variant from a picker, and the runtime injects the script and CSS exactly once per page, on the pages a variant actually applies to. Each catalog entry is pinned to a specific version with an SRI hash, and you can attach up to three libraries per variant. Dev libraries are available on the Pro plan and above.

Preview and QA before launch

Any variant can be previewed on your live site without launching the test. A preview link opens your real site with one specific variant rendered, exactly as a matching visitor would see it, without starting the test and without recording any data. It works on draft experiments before you have ever launched and on running ones, and the link is shareable, so a teammate can open it and see the same thing. When something looks off on a real page, open devtools and call window.__abtestly.debug() to see whether this visitor was in the test, whether the change ran, and whether the result was tracked.

Runs on any front end

ABTestly loads as one lightweight snippet, about 31 KB gzipped with a loader under 1.5 KB, so it runs wherever your site already runs, React, Vue, Angular, Svelte, Next.js, plain HTML, Shopify, and single page apps. It loads asynchronously and does not block rendering. For the full pipeline that turns that snippet into an applied variation and an audited result, read the browser A/B testing runtime.

Quick answers

Does ABTestly have a visual editor?

No, by design. You author variations as JavaScript and CSS in the Monaco editor, so you get production aware code, controlled CSS, reliable cleanup, and measurement you can inspect. A visual editor hides tradeoffs that serious client side experiments cannot afford.

What can a single variant contain?

JavaScript, CSS, or a redirect URL. JavaScript and CSS panes live side by side per variant, and redirect variants fire the exposure event before sending the browser to an alternate page for split URL tests.

Can I reuse code across variants?

Yes. Global JS runs one shared block before any variant for helpers and polyfills, and dev libraries let you attach a curated library like Splide or GLightbox once per page. Both are on the Pro plan and above.

Can I check a variant before launching?

Yes. A preview link renders one variant on your live site without starting the test or recording data, and the variation code check runs a static review on every publish, save, and resume without ever blocking your publish.

Can I see what changed in a variant's code, and undo it?

Yes. Review changes shows your unsaved edits as a diff against the saved code before you save. History keeps every saved version of each variant's code for the life of the experiment. You can compare any two versions, jump straight to what changed since launch or since the last reset, and restore an earlier version into the editor as an unsaved draft.

Capabilities on this page reflect current ABTestly documentation. Global JS and dev libraries are on the Pro plan and above. See the pricing page for current plans and limits.

author your first test

Write a variation
in real code.

Drop the snippet on one page, author a variant in JavaScript and CSS, and preview it before a visitor ever sees it.