Server side tracking
Capture trusted events from your backend, Stripe webhooks, and jobs. Nothing is automatic here, you supply identity and context explicitly.
When to use it
Send an event from the server when the browser cannot be trusted or is not there: revenue events from payment webhooks, subscription changes from billing jobs, or conversions that happen in an API. The rule of thumb is simple. Behavior belongs in the browser, money belongs on the server.
Setup
The server client ships in the same package under a separate entry point. It runs on Node 18 and up.
import { createServerClient, captureCheckoutFinished } from "@analyse.net/sdk/server";
const analyse = createServerClient({ publicKey: process.env.ANALYSE_KEY! });
captureCheckoutFinished(analyse, {
personId: "user_123",
properties: {
checkout_id: checkoutId,
payment_type: "subscription",
billing_interval: "month",
amount: 4900,
currency: "USD",
plan: "pro",
},
});
await analyse.flush();Events are buffered in memory, so always call flush() before your handler returns. In short lived environments like serverless functions you can pass maxBatchSize: 1 to send every event immediately instead.
The API
| Method | What it does |
|---|---|
createServerClient(config) | Create a client. Takes publicKey, optional host and maxBatchSize. |
capture(input) | Buffer any event. Requires personId or anonymousId. |
captureSignedUp, captureCheckoutStarted, ... | Typed captures for the standard events. |
identify(personId, { anonymousId?, traits? }) | Record an identity link from the server. |
flush() | Send the buffer. Rejects on a non 2xx response and re-buffers the batch for retry. |
shutdown() | Alias for flush(), call it before the process exits. |
Connecting server events to browser sessions
Server events need a personId (your user id, the same one you pass to identify in the browser) or an anonymousId you carried over from the client. As long as the ids match, server events land in the same person timeline as the browser events.