Everything the dashboard does, and what each number means
Every figure below is computed by the same module that serves the public read API, so the dashboard and the API can never disagree about what a number is.
A sentence for every screen, and the rule behind it
Each screen carries a read-out rail: plain sentences that compare this period to the last one and name the most likely explanation. The rules are deterministic and computed server-side from your own rows — the same inputs always produce the same sentence.
- Rule shown beside every sentence, so you can check the arithmetic
- Silence when there is nothing to say — no filler in week one
- Available on every tier, including Free
paywall_shown is up 14% but purchase_completed is flat, so more people are seeing the paywall and the same number are buying.Four numbers, each against the period before it
Opens, sessions, active installs and events, each with a percentage change against the immediately preceding period of the same length. Active installs is a distinct count, which does not add across days — so it is computed over the whole period rather than summed, and labelled as an upper bound when the range reaches past the raw window.
- Ranges of 7, 30, 90 and 365 days, all in the URL
- Debug events excluded by default, one link to include them
- "installs, not people" said on the tile, so nobody misreads it
Opens and sessions, one point per day, zero-filled
A day with no data is drawn as zero, not skipped, so a gap looks like a gap. Series two is dashed as well as coloured, because colour is never the only signal. Legend entries toggle, and a rollover card gives you the exact figures for a day.
- Hollow points where the sequence number shows a batch never arrived
- Freshness line: when the last batch actually landed
Top events, with the installs behind each one
Every event name is a link into its property breakdown: which values of which flat properties came with it, capped and merged across raw rows and rollups so the total is counted once. Renamed events are spotted and flagged rather than silently splitting a series in two.
- Pin the events you check every morning
- Explicitly null and absent are folded into one row, and labelled
| EVENT | COUNT | INSTALLS |
|---|---|---|
| app_open | 12,481 | 1,904 |
| paywall_shown | 3,102 | 1,188 |
| purchase_completed | 214 | 207 |
variant: b 1,604 · a 1,498 · not set 0App version, OS, device and locale
Top ten of each, so you know which OS version you can finally drop and which device is producing the crashes. Context lives with the raw events rather than the rollups, so this section is raw-window only — and it always states the window it actually covered instead of implying the range you picked.
Whether installs come back, week by week
Weekly install cohorts and the share of each that opened the app again in the weeks after. Cohorts too young to judge are shown as pending rather than as a drop, so a partial week never looks like a cliff.
| COHORT | W0 | W1 | W2 | W3 |
|---|---|---|---|---|
| Jul 20 | 100% | 48% | 36% | 31% |
| Jul 27 | 100% | 51% | 39% | pending |
| Aug 3 | 100% | 44% | pending | — |
Did the release make things better or worse?
Pick two app versions and compare sessions per install, event rates and adoption curve across them. Read-outs name the events that moved most, and say plainly when adoption is too young to call.
export_failed per install0.11 → 0.31Or run the whole pipeline yourself
The SDK and the Cloudflare Worker + D1 backend are MIT-licensed and complete: ingest, read API, nightly rollups, retention pruning, admin CLI, conformance suite. Deploying it is two commands into your own Cloudflare account. The hosted dashboard is the part we sell; the data pipeline is not held back.
Open source details →git clone https://github.com/awizemann/swift-stats cd swift-stats/backends/cloudflare npx wrangler login npm run deploy