What goes in a community member growth dashboard?
A member growth dashboard answers "is the community actually getting bigger, and where do new members come from?" — new joins, the members who went quiet, net growth, and whether each joining cohort sticks around. It lives or dies on one decision you have to write down: what counts as an active member.
Which cards belong on this dashboard?
- New members this month vs. the same point last month
- Net member growth: joins minus members who went inactive
- Member growth rate by month
- Joins by source (search, referral, product, event, invite)
- Cohort retention: share of each join cohort still active by month
- Time from signup to first post
- Active members by month against total registered members
- Members who never posted, as a share of registrations
What data does this dashboard need?
- A member table with a stable member ID and a join timestamp
- Activity events (posts, replies, reactions, logins) with member IDs
- An explicit, documented definition of an active member
- Acquisition source on the member record, captured at signup
- Deletion and anonymization flags, so removed accounts don't rewrite history
How do you build it?
- Land forum, community-platform, and event data in a database and keep member IDs, post timestamps, event IDs, and RSVP status.
- Build models at the grain this dashboard needs, with the active-member window and the check-in rule as explicit columns.
- Create one saved question per card and certify the shared models and definitions.
- Add dashboard filters for Date range, source, member segment, platform or space, first-post status.
- Show data freshness and the definitions in use — community exports run on a schedule, and every viewer should know what "active" means here.
Example card SQL
WITH months AS (
SELECT generate_series(
date_trunc('month', CURRENT_DATE - INTERVAL '12 months'),
date_trunc('month', CURRENT_DATE),
INTERVAL '1 month'
)::date AS month
), joins AS (
SELECT
date_trunc('month', joined_at)::date AS month,
COUNT(*) AS new_members
FROM community_members
GROUP BY 1
), active AS (
-- "Active" here means at least one post or reply in the month.
-- Swap in reactions or logins if that is your definition, but say
-- which one the dashboard uses.
SELECT
date_trunc('month', p.created_at)::date AS month,
COUNT(DISTINCT p.member_id) AS active_members
FROM community_posts p
GROUP BY 1
)
SELECT
m.month,
COALESCE(j.new_members, 0) AS new_members,
COALESCE(a.active_members, 0) AS active_members,
COALESCE(a.active_members, 0)
- LAG(COALESCE(a.active_members, 0)) OVER (ORDER BY m.month)
AS net_active_change,
ROUND(
100.0 * (COALESCE(a.active_members, 0)
- LAG(COALESCE(a.active_members, 0)) OVER (ORDER BY m.month))
/ NULLIF(LAG(COALESCE(a.active_members, 0)) OVER (ORDER BY m.month), 0), 1
) AS active_growth_pct
FROM months m
LEFT JOIN joins j USING (month)
LEFT JOIN active a USING (month)
ORDER BY m.month;