Dashboards & metrics
The buckets, funnels, and access rules behind every number the Club dashboards show you — and why an empty block is never a guess.
Club's dashboards (Money, Live pulse, the Fansly account board, and any custom block you build) all draw from the same small set of underlying ideas. This page explains them once so the how-to pages can stay short.
The money leaderboard's four buckets
Every paying fan on the Money dashboard's leaderboard lands in exactly one of four buckets. In the panel they show up as:
| Bucket | What it means | Panel label |
|---|---|---|
| A resolved source | The fan came in through a link/domain you track. | the source's own name |
| Organic | Paid, but arrived with no source signal at all (direct visit, search, word of mouth). | Organic (OF) |
| Pending | Money or a subscription exists, but nothing is assigned yet — a link can still fix this. | Needs a source |
| Checking | A brand-new paying fan whose event-driven source check hasn't finished. | Checking source |
The fourth bucket — checking — is easy to miss if you only know the leaderboard from older docs: it holds fans whose money is already visible but whose tracking-link check is still in flight. It is not a queue you work through by hand; it resolves itself as the check completes, and its row only appears on screen once it actually holds a fan.
“balanced: true” is not the real integrity check
The leaderboard response carries a balanced flag (buckets sum to the account total), but
that sum is true by construction — any leftover money is deliberately swept into organic,
so it can never fail to balance, even if a fan were double-counted. The real double-count guard
is a separate pair of fields: how many bucket memberships were counted vs. how many distinct
fans that represents. When they differ, a fan landed in more than one bucket at once — that's
the bug balanced can't see.
Evidence level: how sure is a row?
Every leaderboard row (real source, organic, pending) carries an evidence level built from its own money, not carried over from anywhere else:
- hard — a click or a link/campaign we can point to.
- llm — a source guessed from reading a fan's DM history.
- mixed — the row folded both a hard and an llm-attributed fan together.
- none — no evidence at all (the sentinel rows).
This matters most when rows get rolled up (a creator- or tenant-wide view sums several pages together): the evidence label is recomputed from the summed money every time, never copied forward from the first page. A row that started "hard" on page one but absorbed a DM-guessed fan from page two is relabeled "mixed" — otherwise the label would quietly overstate how solid the row's evidence is.
The fan-entry funnel and cohort trend
Every leaderboard row (and the account-wide summary) carries the same seven-counter funnel:
new, old, ftl (free-trial-link entries), paid (paid-link entries), paid_after
(entries or returns that actually paid), ftl_paid (trial entries that converted), and
entered (everything, including unknown-type entries). Its "new" edge tolerates a one-hour
window of vendor clock skew, so a fan entering in the last hour of a window isn't wrongly
excluded.
The cohort trend — the day-by-day "new fans' revenue" line behind the ARPNU chart — is built from that same funnel scan and the same payment scan the revenue trend already loaded. It costs no extra database query: it's aligned index-for-index with the revenue trend series, so the two can be drawn on the same axis without a second fetch.
Empty blocks explain themselves
A dashboard block that has nothing to show never guesses why. The backend returns one of exactly four machine codes:
no_data_in_window— collection is working, this window just had no events.not_connected— no successful collection has ever happened for this account.source_not_collected— the platform doesn't send this data; it will never resolve on its own.maturing— the numbers exist but the platform hasn't closed out the window yet.
The panel's Why? button on an empty block reads this code straight from the server. See Diagnose why a dashboard block is empty for what to actually do about each one.
The metrics registry and per-key access
Every number that can go into a custom block, or into the batch GET /dashboard/metrics read,
comes from one shared registry: a passport per metric key (money.net, fans.active_paid,
fans.mrr_cents, traffic.*, tg.channel_subs, Fansly's fyp.*, and more) declaring its unit,
whether it has a history series, and which access rule protects it. A metric key can never enter
the registry without a matching access rule — that's checked at import time, not discovered
later as a live bug.
Access is checked per key, not per request
A team member who can only see traffic data doesn't get a blanket 403 on a batch that also asks
for money keys. Each key in the batch is checked on its own: their traffic.* keys come back
with real numbers, and their money.* keys come back {"error": "forbidden"} — same response,
same 200. The panel shows those individual tiles as "no access" instead of failing the whole
card. See Permission gating surprises
for what this looks like in practice.
Custom dashboard blocks
Beyond the built-in tiles, an owner can assemble their own blocks — a number, a sparkline, a chart, a formula, or a set of bars/donut/funnel slices — by picking metrics straight out of the registry. See Build a custom dashboard block for the actual flow; conceptually, a custom block is just a small stored recipe (which metrics, which chart type, an optional formula) that reads the same registry and obeys the same per-key access rules as everything else.
Background: the walk reserve
One attribution signal never shows up as a button anywhere: the walk reserve. When a fan's first touch is a trial code, and campaign membership records make exactly one source unambiguous for that code, a background writer fills in that fan's source automatically — but only where it is certain, and never by overwriting a stronger click/link source or another writer's own canonical mapping. It's a quiet enrichment step behind the organic/pending split, not a task you work.
What's next
- Watch the live activity pulse — the fastest-moving dashboard surface.
- Diagnose why a dashboard block is empty
- For the full source-leaderboard drill (per-country, per-link, per-fan), see Source attribution.
Vault & content concepts
The mental model behind the content vault — what the index actually is, how OnlyFans writes are staged, and the shared truths content endpoints all reuse.
Wall posting
How scheduling a post or story to your OnlyFans wall actually works — the plan table, the two write gates, and why scheduling and delivery are separate steps.