Skip to main content
By the end of this page your app will be assigning users to a variant and sending conversions back to Trevo. You need a workspace and its SDK key. The key is in Settings → SDK keys and looks like tsk_live_…. It is publishable — it ships in your JavaScript bundle by design, and it can read your experiment config and post events, and nothing else: it cannot read results, change experiments, or touch workspace settings.

Where the key goes

Pasting the key into init() is fine for a first test. For anything deployed, put it in an environment variable so rotating it never needs a code change: Two rules keep this from going wrong:
  • Match the key class to the surface. Browsers use the publishable tsk_live_… key. Server SDKs use a server key (tsk_secret_…, created in Settings → SDK keys with platform Server), which must never reach a browser — the API rejects a secret key sent with an Origin header for exactly that reason.
  • Redeploy after adding or rotating a key. Bundlers compile public env vars into your JavaScript at build time, and hosts like Vercel apply env changes to new deployments only. Until you redeploy, the live build keeps the old key and its events are rejected.

1. Install

No bundler? Load the CDN build instead — it exposes a global called Trevo. Pin the exact version in production:

2. Initialise

Once, as early as your app boots:
Call identify() when you know who the user is — usually right after login:
Identity decides which variant a user gets, so calling identify() later can move someone from one variant to another. Call it as early as you can, and before rendering anything you are testing.

3. Read a variant

getVariant() is synchronous and does no network call — assignment is a local hash of the user’s identity and the experiment key. The same user always gets the same variant. Keep your existing loading boundary visible until the first apply; reading once before ready() can return control and never update when config arrives. It returns 'control' for an experiment key it has never seen, so shipping this code before the experiment exists in Trevo is safe. Calling getVariant() also records an exposure — “this user saw this variant”. That is the denominator for your results, so only call it where the user genuinely sees the thing. To read an assignment without recording an exposure:

4. Record a conversion

Nothing is tracked automatically by the browser SDK (@trevosdk/react’s provider is the one exception — it emits a page_view on mount). A conversion exists only where you write one:
Events are batched and sent in the background, including on page unload. You do not need to flush manually, though trevo.flush() exists if you want to force it.

5. Check it arrived

Open Data → Events in your workspace and refresh — the table doesn’t auto-update. Your event should appear within a few seconds. The Connect your app drawer (topbar → Connect SDK) polls live if you’d rather watch it arrive. If nothing shows up, see No events arriving.

What to do next

  • Using React? install/react has a provider and a hook that handle initialisation for you.
  • On Next.js? install/nextjs resolves variants on the server so the first paint is already correct — no flash of the control version.
  • Tracking conversions on a backend? install/node, install/python, or install/ruby. Server-side events are immune to ad blockers and closed tabs, which improves the numbers for your browser experiments too.
  • Building a mobile app? install/react-native buckets users identically to the web and is built for offline queues and app-store constraints.
  • Multiple variants? defineExperiment() gives you a typed union and makes an unhandled variant a compile error. See Typed variants.

The whole thing