Chapter 03 · 5 min

Installing the SDK and verifying events

Client and server, one identity, and the green tick that means it is live.

See it in the demo. See the events arriving.See the events arriving →

In a Next.js app, @trevosdk/react resolves variants and reports exposures and browser events, while @trevosdk/nextjs ties server rendering to Next.js's request hook. That hook gives every visitor a stable trevo_id cookie before the page renders, so the server and the client agree on one identity and the first paint is already the right variant. Next.js 16+ calls that hook proxy; Next.js 14 and 15 call it middleware.

npm install @trevosdk/nextjs @trevosdk/react

// proxy.ts (Next.js 16+; use middleware.ts + middleware on Next.js 14/15)
export { proxy } from '@trevosdk/nextjs';
export const config = { matcher: ['/((?!api(?:/|$)|_next/static|_next/image|favicon\\.ico|sitemap\\.xml|robots\\.txt|.*\\.(?:avif|css|eot|gif|ico|jpe?g|js|json|map|mjs|mp3|mp4|otf|pdf|png|svg|ttf|txt|wav|webm|webp|woff2?|xml|zip)$).*)'] };

// app/layout.tsx
import { getTrevoBootstrap } from '@trevosdk/nextjs';
import { TrevoProvider } from '@trevosdk/react';

export default async function Layout({ children }) {
  const bootstrap = await getTrevoBootstrap();
  return (
    <TrevoProvider apiKey={process.env.NEXT_PUBLIC_TREVO_API_KEY} bootstrap={bootstrap}>
      {children}
    </TrevoProvider>
  );
}

Tracking the funnel

Page views are automatic. Everything else is a track() call with the event name your funnel uses. In Terra & Twine, add_to_cart fires from the product page button, checkout_started from the cart, and purchase_completed on the client.

// client
trevo.track('add_to_cart', { product: slug, value: priceCents / 100 });

If an authoritative conversion lives in a separate non-Next backend, install that backend's server SDK there — for example, @trevosdk/node in a Node service — and record it idempotently with a server key. A standard Next app does not need the Node SDK as a third package.

Where the key goes

The key comes from Settings → SDK keys in the dashboard, and each half of the SDK wants a different class of key. The browser gets the publishable tsk_live_… key in a public env var your bundler compiles into the JS — NEXT_PUBLIC_TREVO_API_KEY on Next.js, VITE_TREVO_API_KEY on Vite. Servers get a secret tsk_secret_… key in TREVO_SECRET_KEY; it must never reach a browser, and the API rejects it if it ever does. One gotcha catches nearly everyone: hosts apply env changes to new deployments only, so after adding or rotating a key, redeploy — until then the live build keeps the old key and its events are rejected.

Verifying the first event

The dashboard shows a “receiving events” signal the moment the first event arrives, and a config heartbeat before that, so “SDK running, nothing tracked yet” is distinguishable from “SDK not installed”. If the first event does not arrive: check that the API key is public-prefixed and set in the environment the build uses, that the middleware matcher covers the route, and that an ad blocker is not swallowing the ingestion request in your own browser.