Skip to main content
@trevosdk/react wraps the browser SDK in a provider and a hook. It depends on @trevosdk/browser under the hood, so one install is all you need:
react >= 18 is a peer dependency.

Provider

Wrap your app once, as high as you can:
The example uses Vite. Match the public configuration mechanism the app already uses: REACT_APP_TREVO_API_KEY for Create React App, GATSBY_TREVO_API_KEY for Gatsby, or the app’s existing browser-safe runtime config for another bundler. Do not copy a Next.js NEXT_PUBLIC_ variable into a non-Next app. The provider initialises the SDK synchronously on first render, keyed on apiKey. A key that arrives later — from runtime config, a consent gate or env hydration — initialises the SDK on the render it appears, and changing the key re-initialises against the new workspace. The provider emits one page_view event (with path) when it initialises — don’t add your own page_view call or visits count twice. The provider also accepts configUrl and ingestionUrl props (endpoint overrides for proxied installs). Passing apiKey={undefined} keeps the SDK from ever starting — a clean way to keep it off outside production. It doesn’t stop an SDK that already initialised this session; for consent withdrawal call trevo.optOut().

Hook

Exposure is recorded on the variant that actually renders. The hook stays subscribed to the SDK, so a variant that could not be resolved on first paint — the first config fetch failed, or identify() had not been called yet — updates as soon as it can be.

Typed variants

Pass an Experiment from defineExperiment() (re-exported here) and the return type narrows to a union, so an unhandled arm is a compile error:
If the variants you declare here drift from the ones configured in Trevo, the SDK logs a warning — which surfaces the mismatch instead of silently returning control.

What renders on the first paint

This is the part worth understanding before you ship an experiment above the fold.
  • Returning visitors resolve from a warm local-storage cache and render the correct variant immediately.
  • First-time visitors have no cache. They render control for one paint, then swap to their assigned variant when config arrives.
Nothing is ever hidden, and exposure fires on the variant that actually rendered — so the data stays correct either way. But a visible swap on a first visit can look like a glitch. Two ways to avoid it:
  1. Resolve on the server. See Next.js — the first paint is already correct for everyone, with nothing hidden. Pass the server-resolved assignments as bootstrap on the provider, or per experiment as useExperiment(key, { initialVariant }).
  2. Use the anti-flicker snippet. See Browser. Hides the page briefly rather than showing the wrong thing.
If neither applies, prefer experiments below the fold or behind an interaction, where a first-paint swap is not visible.

Accessing the client directly

Use this for track() and identify(). For reading variants, prefer useExperiment() — it handles re-rendering when config arrives.

Identifying users

Call identify() as soon as you know who the user is, typically in an effect after auth resolves:
Because identity determines assignment, calling identify() after an experiment has rendered can move the user to a different variant mid-session. Identify before rendering anything under test.