ProveBetter

Guide

Server-side A/B testing: how it works and when to use it

Server-side A/B testing means the variant decision happens in your backend, before the page renders — not in the visitor's browser. Your code asks an experimentation service which variant a visitor gets, serves it, and reports the outcome. No snippet, no SDK, no flicker, because nothing client-side ever runs.

If you've ever wondered how to A/B test something a JavaScript snippet can't reach — a paywall, a price, a recommendation order, an API response — this guide is for you. It covers what server-side A/B testing actually is, the honest tradeoffs against client-side testing, how to do server-side A/B testing on ProveBetter in three steps, why sticky assignment matters, what you can test, what happens when things break, and how to tell when you have a winner. The exact endpoint semantics live in the API reference; this page is the layer above it: should you test in the backend, and how does it fit together.

What is server-side A/B testing?

In client-side testing, a snippet in the browser decides which variant to show. In server-side testing — also called back-end A/B testing, or server-side experimentation when you include feature-flag-style logic — the decision happens in application code, before the visitor's page or API response is assembled.

The flow looks like this:

  1. A visitor requests a page or endpoint. Your backend identifies who they are (a user id, session id, or first-party cookie).
  2. Your code calls the experimentation service with that stable id and the test key.
  3. The service returns a variant — A, B, C, D, or E — and your code renders or returns exactly that variant.

The visitor never sees a script load, never sees a flash of the wrong content, never participates in the assignment at all. That is the point: some decisions cannot be made in the browser, because the browser never sees the backend's inputs. A paywall decision depends on the user's account state. A pricing decision depends on the plan your code just looked up. A recommendation order depends on data your server computed. Those are code decisions, so the test has to live in code.

This is also what people mean by A/B testing without JavaScript: the browser is not involved in the experiment, which matters for tests where you don't want to ship any client code at all.

Server-side vs client-side testing: the tradeoffs

Neither approach is better — they fit different kinds of changes. Be honest about that before you pick a tool.

Client-side testing is the fastest way to test visible copy. If the change is a headline, a button label, or a hero image, you don't need an engineer: ProveBetter's client-side path is one snippet. You author the variants in the builder, paste the generated block once, and edit copy from the dashboard afterward. The boot snippet is about 1.4 KB gzipped and hides test elements for at most 2 seconds while the visitor's variant loads; on a slow connection, visitors see the control page and are never counted. Client-side is the right default for most marketing experiments.

But client-side testing physically cannot reach backend decisions. A snippet in the <head> cannot read your billing system, cannot change a price before the checkout page's server renders it, cannot swap an API response body. That is why Optimizely — the incumbent with the most mature visual editor — split its product into Web (browser experiments) and Feature Experimentation (code decisions), sold as separate products. On ProveBetter, both run in one platform: you pick client-side or server-side per experiment, and both read out in the same dashboard with the same statistics. There is no product split to navigate. (The tradeoff is real: if you specifically want a browser visual editor at enterprise scale, Optimizely is a legitimate choice — this page is about when the decision belongs in code.)

You want to change…Client-side (one snippet)Server-side (plain HTTP)
Headlines, buttons, images, copyYes — fastest path, no engineeringOverkill — needs a developer
Pricing, plans, paywallsCan't reach it from the browserYes — the decision lives in your code
Auth, sessions, personalizationCan't reach it from the browserYes
API responses, backend logicCan't reach itYes
Zero client footprint (no JS, no flicker)Snippet runs in the browserYes — nothing ships to the client
Fastest possible startYesRequires wiring two API calls

The rule of thumb: if the change is visible on the page, client-side is usually cheaper. If the change is a decision your code makes, test it server-side.

How server-side A/B testing works on ProveBetter

Three steps, two plain-HTTP endpoints, no SDK — a small A/B testing API your backend already knows how to talk to. Any language that speaks HTTP works: Node, Python, Go, Ruby, PHP, Java — nothing to install.

Step 1 — create the test. In the builder, pick In my app (server-side), choose a name and a target metric, set your variants (2–5, labeled A/B/C/D/E) and their traffic percentages, and launch. Tests support future scheduling — start next week, start next quarter. Your test key appears on the test card and dashboard; it's the credential your backend uses.

Step 2 — assign a visitor. From your backend, call /api/assign with the test key and a stable visitor id:

curl -X POST https://www.provebetter.com/api/assign \
  -H 'Content-Type: application/json' \
  -d '{"testKey":"YOUR_TEST_KEY","visitorId":"user-1234"}'

The response tells you the visitor's variant (variantKey), whether they're in the test (inTest), and why (reason). When inTest is true, serve the returned variant; when it's false, serve your default behavior. A variant is just a name your code maps to actual behavior — a different price point, a different paywall treatment, a different response body.

Step 3 — report the outcome. When the visitor converts, post the event to /api/events with the same test key and visitor id. You can label conversions with an event name — for example form_fill for a form-fill goal — which the dashboard shows in its event breakdown.

The same test key also works for client-side tests, so a team can A/B test a headline with the snippet and a paywall in code, in the same account, with the same statistics engine on both. For full request/response examples and edge cases, see the API reference.

Why sticky assignment matters

Sticky assignment means the same visitor gets the same variant every time. On ProveBetter it works in two layers:

That matters for three reasons.

First, a consistent user experience. A visitor should not see price A on one page load and price B on the next because their request happened to hash differently the second time. Invisible state-switching is how you lose users and trust.

Second, valid statistics. If visitors shuffle between variants on reload or across sessions, your two groups stop being clean samples. Conversions get attributed to mixed experiences, and the test's answer stops meaning anything. Sticky assignment keeps each visitor wholly in one variant, so the numbers stay honest.

Third, live traffic control without chaos. You can adjust traffic percentages mid-test — say, move a 50/50 split toward the variant that's performing — and only new visitors see the rebalanced split; existing visitors stay put. A visitor's variant changes in exactly two situations: you declare a winner (everyone in-test gets it), or you move a variant's traffic to 0% (its visitors are re-bucketed).

Your one responsibility: keep visitorId stable for the same human across requests — a user id, a session id, or a first-party cookie. Never something that changes per request. Lose the id and the visitor gets a fresh bucket draw, which is also a new exposure. The API reference spells out the full stickiness semantics.

What you can test server-side

Anything where the behavior difference is decided in code:

Every test targets exactly one metric, chosen at creation: call, click, form fill, sale, signup, retention, or a custom event. That focus keeps the test's question single and readable — one experiment, one question, one metric. Custom events reach the dashboard through /api/events, so a server-side "pricing test," for example, targets sale and reports each checkout completion.

What happens when things break

Server-side testing moves the experiment into your request path, so failure handling is a design question, not an afterthought. ProveBetter is fail-safe by design, and the rule is simple: serve your default and never block the request.

Two operational notes: both endpoints are unauthenticated by design (the browser SDK uses the same ones from customer sites), so a test key is the capability to assign and convert against that test — keep server-test keys in your backend, not in client code. And after you wire it up, the API reference's verify checklist walks through four checks — same visitor twice returns the same variant, fresh visitors land roughly on your split, a conversion appears in the dashboard, and ending the test flips everyone to default.

When to declare a winner

ProveBetter runs two statistical engines side by side on every result: a frequentist engine and a Bayesian engine, each summarized in a plain-language verdict. The industry splits into camps here — Optimizely's Stats Engine is sequential and frequentist (p-values); VWO popularized the Bayesian "chance to beat." ProveBetter shows you both, in plain language, so you don't need an interpreter (or a statistics degree) to read a verdict.

The verdicts come with trust banners that tell you when not to trust them: a sample-ratio mismatch (SRM) watch and a small-sample validity notice. And if you rebalance traffic while a test is running, the dashboard says so outright — "traffic changed mid-test — results may be biased" — because the change itself can confound the read. An honest answer about a biased test is worth more than a confident answer about a broken one.

When a winner is clear, roll it out to 100% of traffic with one click. Everyone in-test gets the winning variant from then on, new assignments included, and every traffic, schedule, status, and winner change is recorded in the audit trail. A test becomes a decision, and the decision has a paper trail.

Getting started

Server-side testing needs an engineer for the initial wiring — that's the honest cost, and it's why you only pay it for tests that belong in code. The surface area is small: two endpoints, a test key, a stable visitor id, and your default as the fallback.

Pricing is event-volume based, and it's published on the pricing page: Free at $0 with 1M events per month and no credit card, Small at $199/mo (5M events), Medium at $399/mo (25M), Enterprise at $1,999/mo (100M). Every analytic feature — both stat engines, the trust banners, export, the audit trail — is on every tier; tiers scale on event volume, never on seats or gated features. For visible-copy tests, the client-side install path needs no engineer at all.

Frequently asked questions

Do I need an SDK to run server-side tests with ProveBetter?
No. Server-side testing is two plain-HTTP calls — POST /api/assign to get a visitor's variant and POST /api/events to report outcomes. No client library, no JavaScript, no snippet. If your backend can make an HTTP request, it can run a server-side test. (Client-side tests, by contrast, use the snippet — the install page covers that path.)
What counts as a stable visitor id?
Anything that identifies the same human across requests: a user id, a session id, or a first-party cookie your code sets. The one thing it must never be is a value that changes per request — a random nonce, a per-request token, a timestamp. An unstable id re-buckets the visitor on every call: a new variant, a new exposure, and noisy results.
Can I change traffic percentages after the test starts?
Yes. You can rebalance live — for example moving 50/50 to 70/30 — and sticky assignment keeps existing visitors in their variant; only new visitors see the new split. One caveat: changing allocation mid-test can bias results, so the dashboard flags it ("traffic changed mid-test — results may be biased"). If you can, set the split you expect to need at creation and rebalance only when you have a reason.
Can I run client-side and server-side tests together?
Yes — one platform, one account, one dashboard. The same test key works for both. A/B test the headline with the snippet and the paywall in your backend code, and read both verdicts with the same statistics engine. You choose per experiment where the decision belongs; you don't choose per vendor.

Ready to run your first server-side test? Pricing is published — Free starts at $0 with no credit card.