Metrics methodology
Exactly how RevenueHog computes MRR, churn, trials and revenue. Every formula, window and adjustment.
Where the numbers come from
Two sources, with different strengths. Apple's daily reports (Sales and Subscription, pulled with your App Store Connect API key) are the authoritative once-a-day record: revenue per day and a daily snapshot of your active subscriptions per product, state and country. They lag about one day, and on import they reach back about a year (Apple's daily-report limit, not ours).
App Store Server Notifications V2 (once wired; see the setup guide) are the real-time stream: individual purchase, renewal, cancellation and refund events, each cryptographically signed by Apple. They power the live feed, per-customer LTV, and the one adjustment described below that reports alone can't make.
Level metrics (MRR, active subscribers, trials) come from the daily snapshots. Flow metrics (new customers, events per day, revenue per day) come from the reports' per-day rows or the event stream. Mixing the two up is the most common way MRR dashboards go wrong, so this page says which is which for every metric.
MRR
MRR is a point-in-time level: the monthly recurring value of every subscription active on the most recent snapshot day. Each subscription's price covers its whole billing period, so the price is divided by the period's length in months to get a comparable monthly figure, then multiplied by the subscriber count:
# for every subscription row in a paying state on the day:
row_mrr = (price_per_billing_period / period_in_months) * quantity
MRR = Σ row_mrr # over all paying rows, all products
net MRR = same, using proceeds (after Apple's commission) instead of price
# examples
$4.99/mo monthly → 4.99 / 1 = $4.99 per subscriber
$39.99/yr annual → 39.99 / 12 ≈ $3.33 per subscriber
$1.99/wk weekly → 1.99 / 0.23 ≈ $8.65 per subscriberWhich subscriptions count as paying: active subscriptions, paid intro offers, promotional offers, and subscriptions in a billing grace period. Grace is in because Apple extended the term and the subscriber still has access. Billing retry is out, and that is deliberate: by the time a subscription enters retry the term has already ended and Apple has already cut access. It also keeps the two halves of RevenueHog honest with each other, because the live event stream drops MRR at the same moment (the EXPIRED and GRACE_PERIOD_EXPIRED notifications). Counting retry as paying made the snapshot and live MRR disagree by exactly the retrying subscriptions. Free trials are excluded from MRR entirely; they contribute $0 and are counted as their own metric.
Gross vs net: headline MRR uses the customer price; net MRR uses developer proceeds (what's left after Apple's commission). Both are computed the same way from the same rows.
Family Sharing copies are worth $0
Gap days, anchors & deltas
Apple's reports lag about a day, so "today" usually has no data yet. All level metrics are therefore anchored to the most recent day that has a snapshot, and the dashboard says "as of" that day. Per-app and per-product views anchor to the same org-wide day, so drill-downs always agree with the dashboard they came from.
Subscriber levels persist on days Apple didn't report: a missing day doesn't mean zero subscribers. Daily series therefore carry the last observed value forward across gaps (last observation carried forward):
day reported series value
07-01 $1,204 $1,204
07-02 (no rows) $1,204 ← carried forward, not zero
07-03 (no rows) $1,204 ← carried forward
07-04 $1,310 $1,310Days before the first observation are 0. Flow series (new customers, revenue per day) are the opposite: a missing day really is zero and is never filled.
Deltas compare the current level against the gap-filled level 30 days earlier. When the prior value is zero (a newly launched product), the delta is shown as absent rather than a misleading +∞. Per-product deltas are built from each product's own gap-filled series, so a day Apple skipped for one product can't fake a jump.
ARR, active customers, ARPU
ARR is annualized MRR: MRR × 12, computed per axis day for the chart. It's a run rate ("a year at today's MRR"), not a sum of signed contracts.
Active subscribers is the paying-state subscriber count on the anchor day. Active customers adds current trial users on top (paying + trials, the total active base). ARPU is MRR ÷ active (paying) subscribers; it's 0 when there are no paying subscribers rather than a division error.
New customers
A flow, not a level: the count of brand-new subscription starts per day. A first paid subscribe or a free-trial/intro-offer start, from Apple's subscription-event report. Renewals, trial conversions, plan changes and reactivations are existing customers and are excluded. The headline number sums the trailing 30 days and compares it with the 30 days before that; days with no starts count as zero and are never carried forward.
Trials & cancelled trials
The trial count comes from Apple's daily snapshot, which lumps every unexpired trial into one bucket. Apple's reports carry no auto-renew breakdown, so the report alone can't tell a live trial from one whose user already hit "cancel".
The live event stream can, for apps with notifications wired: a trial start whose latest lifecycle event is auto-renew being turned off (and whose trial period hasn't lapsed yet) is a cancelled-but-unexpired trial. By default RevenueHog subtracts these from the current trial and active-customer counts, because they will expire, not convert. A preference ("count cancelled trials") restores Apple's raw counting.
Where the adjustment honestly can't apply
Churn & the trial funnel
Churn shows up two ways. In the live feed it's event volume, each individual churn event. On the overview it's also a rate: subscribers lost during the window ÷ subscribers at the start of it, shown as a percentage per app and portfolio-wide. That is the standard definition (the one RevenueCat uses), and the denominator matters: dividing by the current count would let subscribers who joined mid-window inflate the base the losses are measured against, quietly flattering a growing app. It also means an app can exceed 100%, when someone joins and churns inside the same window. That is real, and it is not capped. The rate is null, not zero, for an app with no subscribers at the window start, including one whose snapshot history only begins mid-window. From the live stream, churn events are: subscription expired, billing grace period expired without recovery, access revoked, and auto-renew turned off (cancellation intent: the subscriber keeps access until the period ends). From the report vocabulary: cancels, expirations, and billing retries that ran out. A renewal entering billing retry is churn risk and is deliberately not counted as churn. Most retries recover.
The trial funnel is intro-offer based, and this is an Apple limitation worth being direct about: Apple's subscription-event report does not split free trials from paid introductory offers: one "start introductory offer" event covers both. So the funnel's "trials" are trial/intro starts, "paid" are intro → paid conversions (including converting early by upgrading), and the conversion percentage is paid ÷ starts within the selected period. It's a period ratio, not a tracked cohort rate: starts late in the window convert after it closes.
Because that ratio compares two groups of different people, the funnel page also shows the real cohort beside it, for apps with server notifications wired. It follows the individual trials that started in the window, by their original transaction ID, to whatever actually happened to each one: converted, churned, or still deciding. Trials that haven't decided yet are counted as maturing, not as failures, which is the honest way to read a cohort that is still young. It also reports the median days to convert. The cohort only sees events from the day notifications were wired forward (or from a history backfill), so a cohort older than that is genuinely incomplete rather than bad.
Revenue per day
Daily revenue is the sum of developer proceeds (net of Apple's commission) across that day's sales-report rows. One-time purchases and annual prepays included, which is exactly what MRR by definition hides. Period totals sum the window ending at the last revenue day and compare against the immediately-prior window of equal length.
Currency conversion
Apple reports revenue per territory in local currencies. Each non-USD amount is converted using the daily ECB reference rate for that sale's date. Only when no published rate exists does a static approximate rate apply, and the row is flagged as estimated. An unknown currency with no rate at all contributes $0 rather than a fake 1:1 conversion, so an unconvertible row can never inflate totals.
Source of truth
Small Business Program
Apple's daily reports state the Developer Proceeds column at your actual commission rate (Small Business Program members see the 85% share there, not the standard 70%), so every report-derived number here already reflects membership. RevenueHog applies no adjustment on top of Apple's figures, because none is needed: the proceeds column is stored as Apple states it, per proceeds currency, and never rederived from a price and a commission rate.
The live feed is the one estimated surface. Real-time events arrive via Apple Server Notifications, which carry the customer price but not your proceeds, so an event's detail page estimates proceeds from that price. Apple takes 30% by default, or 15% with the Small Business setting enabled. If you record your admission date alongside the setting, the reduced rate applies only to events on or after it, because enrolling does not retroactively repay old sales. That label can't see territory taxes or year-two subscription rates, so treat per-event proceeds as an estimate; reports and payouts remain the truth.
Related reading: the guide to tracking MRR for an iOS app covers the same ground from the builder's side (why App Store Connect has no MRR number and what it takes to compute one), and the Small Business proceeds guide covers the program's math and where estimates can still drift.