Revenue & retention

Report conversions and churn from your backend so your onboarding analytics show real money — what a trial is worth and which path pays off.

Onboarding analytics show you who activated. Connect revenue and you also see who paid: what a trial is worth, which onboarding path turns into paying customers, and whether those customers stick around.

You report billing events from your backend — a conversion, a renewal, a refund, a cancellation — using the same user id you already pass the browser SDK. Sunboard attributes the money to that user's onboarding journey.

It works with any billing setup. You call it from the code that already runs when a customer pays or cancels, so Stripe, Paddle, and your own invoicing all work the same way.

Set it up

Get a secret key

In your project dashboard, open Settings → Secret key and generate one. It's shown once, so store it in a server-side environment variable such as SUNBOARD_SECRET_KEY. Keep it on your server — never ship it to the browser.

Install the server SDK

npm i @sunboard/node

Requires Node.js 18 or later.

Report billing from your backend

import { Sunboard } from "@sunboard/node";

const sunboard = new Sunboard({ secretKey: process.env.SUNBOARD_SECRET_KEY! });

// A trial converts to paid. Amounts are in the smallest currency unit (cents).
await sunboard.revenue({
  userId: user.id,
  amount: 4900,
  currency: "usd",
  idempotencyKey: invoice.id,
});

// A customer cancels or lapses.
await sunboard.churn({ userId: user.id });

Pass the same userId you give the browser SDK so revenue lands on the right onboarding journey.

Billing events

revenue() records money coming in; churn() records a customer leaving. The event type defaults to conversion:

MomentCall
Trial converts to paidrevenue({ ..., type: "conversion" }) (default)
Subscription renewsrevenue({ ..., type: "renewal" })
Upgrade or add-onrevenue({ ..., type: "expansion" })
Money refundedrevenue({ ..., amount: -4900, type: "refund" })
Subscription cancels or lapseschurn({ userId })

Amounts are whole numbers in the smallest currency unit (cents for USD), with an ISO currency. Refunds use a negative amount. churn() takes no amount — it just marks the end of a customer's subscription.

Safe to retry

Pass an idempotencyKey (your invoice or charge id works well) and sending the same event twice is ignored instead of counted twice.

You can also record product events from your backend with sunboard.track({ userId, eventName }) — useful when the action that proves value happens on your server instead of in the browser.

What you see

Once billing is flowing, your project dashboard and sunboard analytics revenue show:

  • Trial → paid conversion, overall and per onboarding path and segment
  • What a trial is worth on average
  • Revenue per activated user versus everyone else
  • Time to paid — how long conversion takes
  • Retention and churn by onboarding path
  • Net revenue (refunds included) and lifetime value per customer

The /sunboard.analyze skill reads these too, so it can prioritize fixes by revenue, not just by where users drop off.

On this page