Skip to main content
Every one of these numbers is a normalization decision wearing a name. MRR is “revenue, monthly” only after somebody has said what an annual plan contributes, whether a trial counts and where a discount lands — and two products that answer those differently produce two numbers that cannot be compared. This page is the answers. The panel draws them under Analytics → Revenue and Analytics → Overview, behind 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.
Amounts are in the currency’s minor unit — cents, for most of them.

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 flipped trialing 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

This is the join no point tool can make, because no point tool sees both the landing page and the invoice: paid invoices grouped by the first-touch UTM of the customer’s founding contact.
  • 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.
A ?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.

Whose midnight

Days are UTC at storage and your organization’s timezone at display, the same rule the event counts follow. Deciding it once is what lets a revenue chart and an event chart be laid over each other.