Skip to main content
@trevosdk/browser assigns variants and records events in the browser. It never touches the DOM — your own code branches on the variant it returns. Under 10kb gzipped, no dependencies. This is the plain JavaScript SDK — on React use @trevosdk/react, which wraps it in a provider and a hook.

Install

Without a bundler

The CDN build exposes a global called Trevo. Pin the exact version in production — the floating channels change under you with no deploy on your side.
Use v0 or latest for prototyping only.

Initialise

Use your bundler’s public prefix — NEXT_PUBLIC_, VITE_, PUBLIC_. Fail explicitly when it is missing; passing an empty string makes setup fail later and is much harder to diagnose. The key is publishable (tsk_live_…) and belongs in your client bundle. Server keys (tsk_secret_…) are rejected from browsers. Where the key goes lists the variable for each stack — and why a key change needs a redeploy. init() is re-entrant — calling it again reconfigures rather than duplicating.

Options

Identify the user

Before this, users are bucketed on an anonymous id kept in local storage and mirrored to a trevo_id cookie (1 year, SameSite=Lax) — the cookie is what lets your backend and SSR bucket the same visitor. After it, they are bucketed on your user id — which means identify() can change a user’s variant. Call it as early as you can, and before rendering anything under test. Anonymous ids are per browser, so the same person on a phone and a laptop is two participants until they sign in. On logout:
The user id is cleared and a fresh anonymous id is minted, so the SDK keeps assigning and tracking — the visitor is simply a new anonymous participant.

Read a variant

Synchronous, no network call, and deterministic — the same identity and key always produce the same variant. Unknown keys return 'control', so this is safe to ship before the experiment exists. The first call records an exposure, deduplicated per identity and variant within a 10-minute window. Calls made before config has loaded return control and record nothing, so a page that reads only once, before ready(), never counts that visitor. The SDK warns in the console and reports a read_before_ready SDK error for it, once per experiment, and the experiment’s page in the dashboard shows how many visitors were missed. Read inside onChange() and after ready(), as above, and it never fires. To read without recording an exposure:

Typed variants

defineExperiment() returns a typed union and turns an unhandled variant into a compile error — so a variant added in Trevo that your code does not handle fails the build instead of silently falling through:

Track conversions

Batched automatically — a flush is triggered once 50 events are queued or every couple of seconds, and on page unload; a single request carries up to 500 events (the server’s cap). trevo.flush() forces a send if you need one. Limits: event names up to 500 characters using A–Z a–z 0–9 _ . - $ only (anything else is dropped with a console warning); properties up to 8KB serialised.

Waiting for config

On a first visit the SDK has no cached config, so getVariant() returns 'control' until the first fetch lands. Returning visitors read from a warm cache and are correct immediately.
Config is polled every 60 seconds and cached in local storage for 24 hours, so a slow network delays the first visit only. ready() also resolves after the first fetch fails. Keep the onChange() subscription shown above so a later successful poll updates the view instead of pinning that visitor to control. To avoid the flash of control on a first visit entirely, either resolve variants on the server (Next.js) or use the anti-flicker snippet below.

Anti-flicker

Hides the page until variants are resolved, with a safety timeout so a blocked or failed SDK can never leave your page blank:
Inline it in a <script> in <head>, before anything renders. It reveals automatically after 1 second by default:
Set it in a script that runs before the snippet — it’s read once, at snippet execution — and values above 10 s are clamped to 10 s. With manualReveal: true, call trevo.reveal() once you have committed the variant. Server-side bootstrapping is better where you can do it — nothing is hidden and there is no timeout to tune.
reset() leaves the SDK working: the visitor becomes a new anonymous participant, so post-logout page views, variant reads and conversions are still recorded. optOut() is the opposite — queued events are discarded rather than delivered, and no new anonymous id is minted. Both are idempotent and safe to call before init().

API summary