SDK
Server-side events
sendServerEvent, auth, idempotency, and integration patterns.
Server events close the loop on offline conversions: CRM closed-won, Stripe invoice.paid, Calendly bookings, support upgrades. They merge to identities via email or user_id.
'use server';
import { sendServerEvent } from '@trackrift/sdk/server';
export async function onDealWon(email: string, value: number) {
const { ok, status, eventId } = await sendServerEvent({
endpoint: process.env.TRACKRIFT_COLLECTOR_URL ?? 'https://api.trackrift.com',
token: process.env.SERVER_INGEST_TOKEN!,
event: {
event_name: 'sales_closed',
email,
value,
currency: 'EUR',
source: 'crm',
properties: { pipeline: 'default', stage: 'closed_won' },
},
});
if (!ok) throw new Error(`Trackrift s2s failed: ${status}`);
return eventId;
}ServerEvent fields
| Field | Required | Notes |
|---|---|---|
| event_name | yes | snake_case — sales_closed, purchase, etc. |
| conditional | Required if no user_id — identity merge | |
| user_id | conditional | Your app user id |
| value + currency | recommended | Revenue attribution |
| source | yes | server | offline | crm |
| event_id | no | Auto-generated UUID if omitted |
| timestamp | no | ISO8601 — default now |
Pass stable event_id to survive webhook retries
await sendServerEvent({
endpoint: process.env.TRACKRIFT_COLLECTOR_URL!,
token: process.env.SERVER_INGEST_TOKEN!,
event: {
event_id: `stripe_${invoice.id}`,
event_name: 'purchase',
email: customer.email,
value: invoice.amount_paid / 100,
currency: invoice.currency.toUpperCase(),
source: 'server',
},
});