Skip to content
Hosted in Europe. Your test data is stored in the European Union.Hosted and stored in EuropeLearn more

Assign on the server, measure through the API, roll out in steps.

The server helper assigns visitors before rendering, with no flicker. The API receives events from your servers. Rollouts follow your guardrails and roll back on their own.

Server helper
// proxy.ts: assignment before rendering
const { setCookie, assignments } = assignRequest({
  cookieHeader, url, userAgent,
  config,  // GET /api/v1/config, cached in memory
  consent, // the visitor’s choice
});
assignedVariants(assignments);
// { "date-livraison": "b" }

No framework dependency: the same function works in a Next.js proxy, a Node server, or at the edge.

A badly wired test shows on screen and in the data.

The most common problems when experimentation moves from marketing to engineering teams.

  • FlickerA script that changes the page after it renders shows the original for a split second.
  • Diverging assignmentsIf the server and the browser don’t share the same draw, a visitor switches versions from one page to the next.
  • Flags without measurementA flag turns a feature on; without a comparison, nobody knows what it changed.
  • Rollouts without a safety netSwitching all traffic at once exposes every visitor to a regression.
  • Scattered eventsOrders in the back office, clicks in analytics: the test sees only part of the story.

Events arrive from anywhere; rollouts roll back on their own.

Send orders from your servers.

The script sends exposures and conversions from the browser. The API receives what only your server knows: confirmed orders, amounts, measurements. It responds 202 with a count of accepted and rejected events.

Timestamps can be up to 5 minutes in the future and 7 days in the past. The public API rejects secret keys.

Events API
POST /api/v1/events
x-probant-key: "pk_…"

{ "events": [
  { "type": "conversion", "visitorId": "…",
    "metric": "commande", "value": 89.9 }
] }

From feature flag to rollout, one configuration.

The life of a feature that’s tested and then rolled out, without switching systems along the way.

  1. Create

    Create the experiment in a layer.

    Each test takes a slice of its layer. Probant rejects a slice that overlaps another.

    In the productSlices are set in increments of 0.01% of traffic.
  2. Assign

    Assign before rendering.

    The server helper reads the cached configuration and returns each test’s variant, or the reason for exclusion: holdout, slice, URL, or device.

    In the productSame cookie as the script: probant_id, 390 days at most.
  3. Measure

    Send exposures and conversions.

    The script measures in the browser; the API receives orders confirmed by your servers.

    In the productUp to 500 events and 256 kB per request.
  4. Decide

    Read the report.

    Verdict, range, corrected gain, and checks, computed on per-variant aggregates.

    Demo storeFree shipping progress bar: showing progress toward free shipping: revenue per visitor +6.0% measured, +4.9% expected once corrected for the winner’s curse. The effect on margin isn’t established yet: +3.0% measured, range from -0.7% to +6.7%.
  5. Roll out

    Ramp up in steps.

    The exposed share goes into the configuration; guardrails are reread at every check, with automatic rollback.

    In the productSteps: standard, 25%, 50%, and 100%; cautious, 10%, 25%, 50%, and 100%.
  6. Clean up

    Remove the flag.

    Once the variant is served to everyone, the original’s code can go: a forgotten flag is a code path nobody tests anymore.

    In the product“Remove from code” status after 14 days served to all visitors.

By the numbers.

< 7 KBcompressed browser script, loaded asynchronously
10,000deterministic assignment buckets
500events at most per API request
390 daysmaximum lifetime of the probant_id cookie, never extended

Frequently asked questions.

Does the script make the page flicker?

The script doesn’t hide the page while it loads: each change applies as soon as its element exists, then again on every re-render, before the next paint. To avoid any flicker, assign on the server: the page arrives already in the right variant.

Do server-side assignment and the script give the same variant?

Yes. Both read the same cookie (probant_id) and run the same deterministic draw over 10,000 buckets, so a visitor keeps their variant everywhere, with nothing stored on the server.

Can we send orders from our back office?

Yes, through the events API: up to 500 events and 256 kB per request, timestamped up to 7 days in the past. Each event is validated on its own, so one bad event doesn’t block the others.

What happens if Probant doesn’t respond?

The server helper keeps the configuration in memory: if Probant is slow or unavailable, the previous one is still used, and your site doesn’t wait for Probant on every page. Until a configuration has been received, the site shows the original.

How do we install the server helper?

It has no framework dependency: the documentation describes how to install it, with a Next.js proxy example.

Other use cases

The same engine, for other site areas and other teams. The demo opens on the screen this page describes.

  • Open demo, no sign-up
  • Free to start, no overage charges
  • Database and compute in Amsterdam, with Scaleway