@trevosdk/node runs experiments and records conversions from your backend. It uses
web-standard APIs only — fetch, AbortSignal, timers — so it runs on Node 18+, Bun, Deno,
and edge runtimes.
Why use it
Conversions that cannot be blocked. Asubscription_started fired from a Stripe webhook
is never lost to an ad blocker, a closed tab, or a failed beacon. This improves the numbers
for your browser experiments too, which is the most common reason to adopt it before
running a single backend experiment.
Experiments only a backend can run — pricing and packaging, search ranking, prompt or
model choices, lifecycle email content. The variant is a code path, not a UI element.
Properties the browser shouldn’t be trusted with — plan, seat count, MRR.
Create a client
You need a server key:tsk_secret_…, from Settings → API keys with platform Server.
It is shown once. Never put it in client code — secret keys sent with an Origin header are
rejected.
Identity is passed per call
A server holds no ambient user state, so every call takes the identity explicitly:userId never
creates that link, and the user’s pre-login activity is never attached to their conversion.
Bucket with the identity the browser is using at that moment — the user id when
identified, otherwise the trevo_id cookie. Anything else assigns the same person different
variants on the client and the server.
Linking identities without a cookie
Webhooks and cron jobs have no cookie to read. State the link directly:anonymousId belongs to one user — pointing it at a
different user is rejected and changes nothing.
Idempotency
Payment providers replay webhooks, and a conversion counted twice inflates whichever variant that user was in. Pass a stableinsertId derived from the thing that happened:
Serverless
Timers do not survive between invocations, so flush explicitly before returning:shutdown() before exit — it stops timers and flushes once.