Analytics (E7)
Four computation modules sit under includes/analytics/:
OMembership_Analytics- daily snapshot coordinatorOMembership_MRR- revenue mathOMembership_Cohort- retention cohortsOMembership_Health- per-member health score
MRR and ARR
OMembership_MRR::current() sums the monthly-equivalent price of every active recurring membership. Free, one-time, and lifetime memberships are excluded (they roll up as "active members" via MRR::active_count()).
The interval-to-monthly conversion:
day -> (amount / count) * 30
week -> (amount / count) * 4.345
year -> (amount / count) / 12
month -> amount / countARR is just current() * 12.
Cohort retention
OMembership_Cohort::retention( $months ) returns a retention matrix keyed by signup month. Each cell is the share of that cohort still active N months in. Used by the dashboard cohort chart and exposed via REST.
Member health
The health score is a composite (0 to 100):
| Component | Weight |
|---|---|
| Last login recency | 25% |
| Lessons completed | 30% |
| Discussion participation | 25% |
| Billing health | 20% |
Scores are cached in wp_omem_health_scores and recomputed daily via omembership/health/recompute. The batch worker processes up to 500 active members per run. The filter omem/health/score lets integrations adjust the final value.
Daily snapshot
The omembership/analytics/snapshot worker runs once a day and writes a compact rollup to the omembership_analytics_snapshot option so dashboard reads stay cheap:
php[
'mrr' => 4821.50,
'active' => 312,
'cancelled_30' => 8,
'new_30' => 41,
'computed_at' => '2026-05-14 03:00:00',
]The same payload is appended to wp_omem_events as type analytics.snapshot for historical trending.
REST endpoints
All analytics endpoints require the omem_view_reports capability (granted to administrators and shop managers by default):
GET /wp-json/omem/v1/reports/mrr
GET /wp-json/omem/v1/reports/cohort
GET /wp-json/omem/v1/reports/courses
GET /wp-json/omem/v1/reports/engagement
GET /wp-json/omem/v1/members/{id}/healthOMembership_DB::memberships_per_day( $days ) returns a dense sparkline for the dashboard (zero-filled so chart renders stay smooth).

