analytics:read.
Where they come from
They are not derived from tracked events. They are recomputed nightly from your subscriptions and invoices — the mirror of what your payment gateway holds — into one row per environment, UTC day and currency.Rows are per currency, and never summed across
Two prices in two currencies are two amounts somebody chose, not conversions of one another, so nothing here adds them together.fx_rate and fx_rate_source
exist so that the day a converted total is drawn, the rate used and where it
came from are on the row rather than in whoever drew the chart. Until a rate
source exists they stay null and "" — which sends a reader to check, instead
of asserting a conversion nobody performed.
What each number means
The four movement buckets partition the per-customer difference between D-1
and D, per currency: new when yesterday was zero, churned when today is zero,
expansion and contraction for a move between two nonzero amounts. A customer who
upgrades and another who downgrades on the same day show up in both middle
buckets rather than netting to nothing.
Normalization
Annual is amortized. A yearly price divides by 12, a weekly one multiplies by 52⁄12, a daily one by 365⁄12, and a price billed every n intervals spreads over its own span. MRR is a monthly rate, so every interval is expressed in it. One-time prices never enter MRR. A lifetime deal is revenue, not recurring revenue; it appears in invoices and in revenue by channel. Trials are out. A trial is a promise to maybe pay, and counting it books revenue that churns silently when the card is never entered. A subscription enters MRR when its trial ends — read from the trial’s end timestamp rather than from the status column, so a webhook that has not yet flippedtrialing to
active cannot hide a conversion.
Discounts, proration and tax enter through the invoice, never the price. What
a customer agreed to pay is the immutable catalogue price this rollup reads, so
MRR here is contracted MRR. Cash — what actually arrived, coupons and
proration included — is the invoice’s own money, and it is what revenue by
channel counts.
LTV is ARPA divided by the monthly logo-churn rate, computed over a trailing
30-day window: customers paying 30 days ago who pay nothing today, over
customers paying 30 days ago. With no churn in that window the answer is null,
not infinity — an undefined LTV is not an enormous one, and a null sends the
reader to the churn column instead of printing a number nobody should plan
around.
NRR is a 12-month window: what the customers who were paying 365 days ago
pay today, over what they paid then. null when there was no such cohort.
Statuses with no timestamp to place them in time — paused, incomplete, unknown —
are excluded outright rather than guessed at. A paused subscription asserting
revenue would be exactly the reassurance that stops somebody checking.
What a mirror can reconstruct, and what it cannot
These numbers are derived from a copy of what your gateway holds, and the gateway rewrites its rows in place. A subscription’s start, its cancellation and its trial end are timestamped, so a past day can be valued honestly. A quantity change is not. A seat count that went from 3 to 5 reads as having always been 5. So the nightly job recomputes about 8 UTC days and freezes everything older as it was written. That freeze is the only history a mirror can keep — and it is why reprocessing further back would repaint last quarter with this quarter’s seat counts. A correction inside the window lands by itself on the next run; outside it, what is stored is the history.Revenue by acquisition channel
- A customer is a team, and a team has no landing page — a person does. The channel of a customer is therefore the first-touch attribution of its founding contact: the earliest membership, ties broken deterministically.
- Colleagues do not get their own channel. Somebody invited onto a team arrived through your product, not through a campaign, and crediting their UTM would credit the wrong door.
- Imported customers keep the channel that won them, because an imported line carries its own attribution and it lands on the contact at birth.
- The money is the invoice’s: what was actually paid, discounts and proration included, in the invoice’s own currency, grouped per currency and never summed across.
- Empty
utm_*strings are the honest form of “no attribution recorded” — direct, or a contact created before the attribution existed.
?ref= code rides in that same first touch, and it is what
referrals are owed on — the same capture answering a
different question: this asks which channel won the customer, that asks who gets
paid for it.