Skip to content

Recipe: track revenue server-side

The reliable place to record revenue is your backend, right after a payment settles. Browser tracking can be blocked or the tab can close before a purchase confirms. Emitting the event server-side from your payment handler guarantees it counts, and lets you make it idempotent.

  • unit: pass the same id you experiment on (the visitor id, user id, or account id you use for assignment). This is what ties the revenue to the right variant or flag.
  • value in cents: send minor units so metric math is exact. $49.99 is 4999.
  • eventId: a stable idempotency key so a retried webhook does not double-count.
  1. Do this in the code path that confirms the charge, a Stripe webhook handler, a queue worker, or the success branch of your checkout logic.

    POST /v1/track
    curl -X POST https://statskit.ai/api/v1/track \
    -H "Authorization: Bearer ssk_live_…" \
    -H "Content-Type: application/json" \
    -d '{
    "unit": "user_8f21",
    "event": "purchase",
    "value": 4999,
    "currency": "usd",
    "props": { "plan": "pro" },
    "eventId": "evt_ord_10432"
    }'
  2. If your experiments assign on user_id, pass that same user_id as unit. If they assign on the visitor id, pass the visitor id (read it off the purchase’s statskit_visitor_id metadata; see Stripe attribution). A mismatched unit will not link the revenue to any assignment.

  3. Payment webhooks retry. Pass a stable eventId derived from the payment (the order id, or the Stripe event.id) so re-delivery is de-duplicated. Do not use a random uuid, a retry would generate a new one and count the sale twice.

  4. Define a custom metric with aggregation: "sum", event: "purchase", direction: "higher", format: "usd", and attach it as the primary metric on the experiment. Revenue then shows per variant in results.