Analytics dashboard (org & region)
Analytics is a core, always-on reporting surface — it isn’t a licensable module and has no on/off toggle at the org level. National admins reach the full org-wide view at /org/analytics; regional admins reach a region-scoped view at /region/analytics that’s almost identical, minus one tab. This page walks both tiers together, since they share nearly all of their UI.
What you see
The Analytics dashboard: Overview tab with the KPI deck and Chapter Health Heatmap.
Both pages share the title “Analytics”. The subtitle differs slightly by tier:
- Org tier: “Org-wide KPIs, chapter health, cohort retention, and AI reports.”
- Region tier: “Region-wide KPIs, chapter health, and cohort retention.” (no mention of AI reports, since that tab doesn’t exist here)
Above the tabs, both tiers show the same two controls:
- A chapter-status filter dropdown: “Active chapters only” (default) / “Active + Inactive” / “Active + Suspended” / “All chapters”. Inactive and suspended chapters can skew org-wide or region-wide averages, so the Overview KPI deck, heatmap, cohort chart, comparison table, and export default to active chapters only and let you opt the others back in. The Adoption tab’s headline numbers are the one exception — see Adoption tab below.
- An Export dropdown with two options: “Download CSV” and “Download Excel (XLSX)”.
The tabs themselves differ by tier:
| Tier | Tabs |
|---|---|
| Org | Overview, Retention (if Operations enabled), Cohorts, Comparisons, Adoption, AI Reports |
| Region | Overview, Retention (if Operations enabled), Cohorts, Comparisons, Adoption — no AI Reports tab |
Only national admins reach /org/analytics (further filtered to national-admin scope in the org sidebar); regional admins reach /region/analytics for their own region, and national admins can also open it. Nobody else can reach either route.
Overview tab
KPI deck
Seven KPI cards render at the top of the Overview tab, in this exact order, each animated with a count-up on load:
- Avg Retention — percent (this card is featured/wider than the rest)
- Avg Compliance — percent
- Avg Dues Collection — percent
- Avg PNM Conversion — percent
- Avg Membership Growth — percent (can be negative)
- Chapters At Risk — a plain count, not a percent
- Avg Compliance Overdue — percent
These are averages across whatever set of chapters the chapter-status filter currently includes.
Avg PNM Conversion is the one card here that depends on a license. Recruitment lives in the Operations module, so an org without Operations neither computes nor returns pnm_count, pnm_converted, or pnm_conversion_pct — the key is absent rather than zero, in new snapshots and in historical ones read back through the heatmap and comparison views. Every other metric on this page is unaffected.
Chapter Health Heatmap
Below the KPI deck sits the Chapter Health Heatmap card — title “Chapter Health Heatmap”, description “Click any row to view that chapter’s Analytics tab.”
- One row per chapter, one column per thresholded metric:
retention_pct,compliance_pct,dues_collection_pct,pnm_conversion_pct,membership_growth_pct,consecutive_decline_months,compliance_overdue_pct,compliance_critical_pct. - The three headcount metrics (
total_members,active_members,alumni_members) are deliberately not columns here, even though they appear in the Comparisons dropdown and the chapter trend chart. Every cell in this grid is coloured red/amber/green against a threshold, and a headcount has no threshold — the column would be permanently gray, costing width on an already-wide table while telling you nothing. Use Comparisons to rank chapters by size, or a chapter’s Trend tab to see its headcount over time. - Each cell renders as a color-coded “traffic light” badge — see Understanding the color coding below.
- Rows are clickable. Clicking a row navigates to that chapter’s own Analytics view in-page, via a
?chapter={id}query param, with a “← All chapters” control to come back.
If there’s no snapshot data yet, the heatmap shows an empty state: title “No snapshot data yet”, description “Snapshots collect nightly — first data available tomorrow.”
Cohorts tab
The Cohorts tab hosts a card titled “Retention by Cohort”, description “Retention curves grouped by pledge class or joining semester.”
Two toggle buttons control the grouping dimension:
- “Joining Semester” (the default) — groups members by calendar term. A join month of August or later is
Fall YYYY; a join month of June or July isSummer YYYY; a join month of May or earlier isSpring YYYY. - “Pledge Class” — groups members by academic year. A join month of August or later counts toward next calendar year’s pledge class (e.g. joining in September 2026 puts you in “Pledge 2027”).
The chart itself is a line chart with one line per cohort. When the selected metric is a percentage, the Y-axis is fixed to a 0–100 domain. The tooltip shows formatted values, a legend is shown, and lines render without dots at each data point.
If there’s no cohort data for the current filters, the tab shows an empty state: title “No cohort data available”, description “Try a different pledge class or joining semester range.”
Comparisons tab
(Org and region tiers only — this tab does not exist at the chapter tier. See Chapter Analytics — officer/admin view for what a chapter officer sees instead; a single chapter has nothing to compare itself against within this feature.)
Three controls sit above the ranked table:
- A metric dropdown — all 11 metrics, defaulting to Retention % (
retention_pct). That is the 8 thresholded metrics in the traffic-light table below, plus the three headcounts (Total Members, Active Members, Alumni Members). The headcounts are plain counts with no thresholds, so they rank chapters by size rather than by health, and their badge renders gray rather than red/amber/green. They are also the reason this list is longer than the heatmap’s columns — see Chapter Health Heatmap. - A Top-N selector — 5 / 10 / 20 / 50, defaulting to 10.
- An order selector — “Highest first” / “Lowest first”.
The table itself shows a rank number, the chapter name, and the selected metric’s value rendered as a traffic-light badge. Rows are clickable and drill into that chapter’s own analytics, the same way heatmap rows do.
If there’s no data for the current metric/range, the tab shows an empty state: title “No data available”, description “Try a different metric or a broader top-N range.”
Understanding the color coding
The Chapter Health Heatmap, the Comparisons table, and per-metric badges elsewhere on the page all use the same traffic-light thresholds:
| Metric | Green | Amber | Direction |
|---|---|---|---|
| Retention % | ≥ 85% | ≥ 70% | higher is better |
| Compliance % | ≥ 90% | ≥ 70% | higher is better |
| Dues Collection % | ≥ 90% | ≥ 70% | higher is better |
| PNM Conversion % | ≥ 50% | ≥ 25% | higher is better |
| Membership Growth % | ≥ 0% | ≥ -10% | higher is better |
| Compliance Overdue % | ≤ 5% | ≤ 15% | lower is better |
| Critical Compliance % | ≥ 95% | ≥ 80% | higher is better |
| Consecutive Decline (months) | ≤ 0 mo | ≤ 2 mo | lower is better |
| Weekly Active % (Adoption tab) | ≥ 35% | ≥ 15% | higher is better |
Two of these eight metrics are inverted from the rest — Compliance Overdue % and Consecutive Decline are “lower is better,” so a small value is green and a large value is red. Everything else follows the usual “bigger is better” direction. Anything outside the amber range renders red; a chapter with no data for a metric renders gray.
Retention tab
If your org has the Operations module enabled, a Retention tab appears on both the org and region pages, hosting the same Retention dashboard used elsewhere in the platform (KPI cards, alerts, acknowledge/resolve workflow, snapshot browsing). This page doesn’t re-explain that mechanics — see:
- Analytics Retention tab — post-enable runbook — enabling and first-30-minutes setup for Retention
- Retention snapshots and alerts — the full alert lifecycle and severity rules
- Retention surveys (officers) — the qualitative counterpart to the quantitative snapshots
Adoption tab
The Adoption tab answers a different question than the rest of this page: not “is this chapter healthy” but “are people actually using the platform.” It’s built from real usage data — a LoginEvent row written at every password, Google OAuth, SSO, and passkey sign-in, plus a PageViewEvent row written on every route change — rather than from the membership/compliance/finance snapshots the other tabs use.
Unlike the rest of this page, the KPI deck, the live band, trend chart, Device, funnel, and module-usage cards ignore the chapter-status filter and always cover every chapter in the org (or region) regardless of status — a chapter marked inactive or suspended doesn’t stop its members from being real logged-in users, so excluding them would just undercount adoption. Only the Engagement by chapter table below respects the filter, since it’s meant for drilling into a specific chapter’s status.
Population legend
Above the deck, two numbers anchor every card below: Active Members (undergrad + associate — the population most of the deck counts) and Total Memberships (every membership in the org, alumni included — the population Module Usage and the Device card’s 7-day split count). Read a card’s count against whichever of these two it names.
KPI deck
Six cards sit beside the featured Active · last N min cell: Weekly Active, Monthly Active, Ever Activated, Avg Days Since Login, Total Active Users, and Median Session.
Every card shows a count, with its share underneath as a sublabel. That ordering is the point: a bare percentage doesn’t say how many people, and a bare count doesn’t say whether that’s healthy for an org this size — but “18 · 34% of active members” says both.
Total Active Users is the one interactive cell. A pill toggle switches its population between Active (undergrad/associate, matching Weekly/Monthly Active) and All (every membership, matching Module Usage), and a second toggle switches its window between 7d, 14d, and 30d. Switching populations changes the percentage’s denominator too — Active reads against Active Members, All reads against Total Memberships.
The populations these cards count are not the same, which is why the legend above states both and each card’s sublabel says which one it used:
| Card | Counts |
|---|---|
| Active · last N min, Weekly Active, Monthly Active, Ever Activated | Members with an active status (undergrad/associate) |
| Total Active Users | Either population, per its own toggle |
| Module Usage, Device (7 days), Adoption funnel | See each card’s own caption |
Before this was stated on the cards, an org could see “2 people have ever logged in” beside “15 unique users viewed pages this week” — every figure correct, the page still unreadable.
The live band
Three cards sit under a “Right now” band with a Live marker. Everything in it is presence-based and refreshes while the tab is open; everything below it is historical.
Active · last N min (the featured KPI cell) is a count of members in scope seen inside your org’s presence window. That window is a setting — 2, 5 or 15 minutes — and the card names whichever one your org chose rather than assuming five. See Presence & Activity settings.
This is the one number on the tab that is not built from LoginEvent, because LoginEvent cannot answer it: a login row is written once per sign-in, so a member who signs in at 9am and works in the app until 5pm produces exactly one event, at 9am, and nothing after. Presence is recorded separately — every authenticated request stamps that member’s user id with the current time in Redis, and this counts the stamps inside the window that belong to members in your scope.
Two things it deliberately does not claim:
- It is not “Online.” What the platform knows is that a request arrived from that member inside the window — not that they are at their desk, and not that they are free to answer one. A member reading a long page without clicking still counts; a member who left a tab open over lunch does not.
- It is not a claim about anyone in particular unless you have turned that on. Whether a named member appears in the roster below is a separate setting from the count, and defaults to officers only.
If a presence figure shows an em dash (—) rather than a number, presence could not be read — the number is unknown, not zero. A zero would read as “nobody is using the platform”, which is an alarm worth acting on, so it is never shown unless it is genuinely measured. Everything else on the page (and every request anyone is making) is unaffected: presence is only ever an observer.
Concurrent Users
A line chart of the last 24 hours, one point per minute, plus today’s peak and today’s unique members.
Presence itself keeps no history — a stamp is worth knowing for minutes and worth nothing after that — so a background task samples the count once a minute and keeps the samples in Redis on a 48-hour horizon. They are deliberately not a database table: a table would mean a migration, a row-level-security policy and a retention rule for data whose value expires within a day.
A minute the sampler missed is drawn as a gap, not a zero. A missed beat rendered as a crash to zero would invent an outage.
Active Members
Who is in the app right now, most recently seen first: name, chapter, the module they are in, their device, and how long ago they were seen. The list is capped at 100 rows — it is a display list, and the exact count is the KPI cell above it.
This card is governed by the individual presence indicator setting, which starts at officers only. Where it is hidden, the card says so rather than rendering an empty list.
In Right Now
The same members, grouped by which module they are in. Governed by the current module setting, which starts hidden — an admin has to turn it on.
Weekly Active Users trend
A 90-day line chart of the org-wide (or region-wide, at the region tier) count of weekly-active members, read from the same nightly snapshot pipeline as the rest of Analytics.
🔴 A count, on an axis that fits the data. This plotted a percentage on a fixed 0–100 axis until a later fix, which meant a real org’s line sat flat along the floor: at 0.4% adoption, doubling to 0.8% was invisible. A count auto-scales, so movement shows at any adoption level — and “27 people” is what somebody acts on. Hover any point for the share as well. Before login data has had two weeks to accumulate, this shows an empty state: title “Collecting data”, description “Login tracking just started — check back in a few days.”
Device
A web-vs-native-app split with a Now / 7 days toggle.
- Now — of the members active right now, from presence.
- 7 days — logins over the last 7 days, from the platform value captured on every login event. It does not yet distinguish iOS from Android.
These were two separate cards until they were merged. The same donut against two different denominators, two cards apart, reads as contradictory data rather than as two facts.
Adoption funnel
Four stages, each narrower than the last: Invited (active members) → Ever logged in → Active this week → Power user (5+ distinct login days in the last 7 days).
Module Usage & Session Length
Answers a question login data alone can’t: once someone’s in, what do they actually use? A route-change ping fires as members navigate the app (buffered through Redis and flushed to Postgres every two minutes, so this never adds latency to a page load), and these cards summarize the last 7 days of that data:
- Module Usage — a horizontal bar per module (Members, Chapters, Documents, Learning, and so on), ranked by page views, each showing its view count and unique-user count.
- Session length, shown in the Today card as a distribution with the median and p90 beneath it — the average span, in minutes, of a member’s page views before a 30-minute idle gap starts a new session, and how those sessions are spread across buckets. An average alone hides the shape: a handful of long sessions and a mass of one-page bounces average out to something that describes neither. A session with a single page view contributes 0 minutes — an honest artifact of measuring duration by route-change pings, not smoothed away with an assumed per-page dwell time.
Every routed page is classified. A page view is attributed to a module by its route, and for a while 55 routed pages had no entry in that table — /org/dashboard among them — so all of them collected under Other, which then ranked first. A test now walks the page tree and fails on any route that would land there.
Both show a “Collecting data” empty state until page-view pings have accumulated. This data is kept for 14 days, shorter than the login-event history behind the rest of this tab, since it’s a much higher-volume signal and this tab only ever needs a recent window for it.
Engagement by chapter
One row per chapter with its weekly-active percentage and a status badge — Thriving (≥35%), Steady (15–34%), or At risk (<15%), using the same traffic-light thresholds as the rest of the page (weekly_active_pct in the table under Understanding the color coding).
A chapter that stays At risk for 14 consecutive daily snapshots (two weeks) triggers an in-app notification to org admins — not email. The two-week wait is deliberate: it’s a baseline-building guard so a chapter isn’t flagged the first day its numbers dip.
AI Reports tab (org tier only)
The org tier’s AI Reports tab is where report generation and history live. It replaced the standalone Reports page, and /org/reports now redirects to Analytics. See Reports dashboard for how report generation works; this page doesn’t repeat that content.
Exporting data
The Export dropdown (org and region tiers only — there’s no export at the chapter tier) offers two formats:
- Download CSV — columns:
chapter,captured_at,total_members,active_members,alumni_members,retention_pct,compliance_pct,dues_collection_pct. - Download Excel (XLSX) — the same columns, with the header row bolded and each thresholded metric cell color-filled to match its traffic-light state (the three headcount columns are left unfilled, having no threshold). The downloaded file is named
analytics-export.xlsx.
At the region tier, the export is automatically scoped to the regions you administer. If you are a regional admin of more than one region, it covers all of them; no region needs to be selected manually.
Region tier: what’s different
Everything above applies identically at the region tier, with three differences:
- No AI Reports tab. Regional admins don’t get the AI-assisted report generator.
- Automatic region scoping. The heatmap, cohort chart, comparison table, and export all scope themselves to the regions you administer (all of them, if you have more than one) on the backend — there’s no region selector to operate in the UI.
- The subtitle reads “Region-wide” instead of “Org-wide,” and drops the “AI reports” mention.
Otherwise, the Overview KPI deck, Chapter Health Heatmap, Cohorts tab, Comparisons tab, color coding, and export all work exactly as described above.
Related
- Member Analytics Visibility settings — the per-org setting that controls what regular chapter members see (does not affect this page)
- Presence & Activity settings — the presence window, and who may see that a named member is currently active
- Chapter Analytics — officer/admin view — the chapter-tier equivalent of this page, for chapter officers and presidents
- Chapter Analytics snapshot — what a regular chapter member sees instead of a full dashboard
- Retention snapshots and alerts — full depth on the Retention tab
- Reports dashboard — full depth on the AI Reports tab’s underlying feature
Last verified against v0.73.23 (2026-08-16), plus the presence dashboard (2026-09-02). Adoption tab (login-based activity) added in v0.73.21; its headline numbers made org-wide regardless of chapter status in v0.73.23. Analytics module + Retain/Surveys consolidation, v0.65.0. This page was previously undocumented.