Dashboard

What goes in a community engagement dashboard?

An engagement dashboard measures whether the community is a conversation or a broadcast: how much gets posted, how much of it gets answered, how fast, and how many people carry the load. The uncomfortable cards — unanswered questions and contributor concentration — are the ones worth building first.

For: Community managers, developer relations, support leads, and moderators. Refresh: daily, or hourly if moderators work the queue live. Source: modeled community, forum, and event tables in a Metabase-connected database.

Which cards belong on this dashboard?

  • Posts, replies, and reactions per week
  • Active member ratio: active members ÷ registered members
  • Top contributors by replies, with staff and non-staff separated
  • Unanswered questions older than 48 hours
  • Median time to first reply, by week
  • Replies per topic distribution
  • Share of activity from staff vs. community members
  • Channels or categories ranked by activity and by unanswered rate

What data does this dashboard need?

  • Posts and replies with member ID, topic ID, parent post ID, and timestamps
  • A flag distinguishing questions from discussion posts
  • A staff or team-member flag on the member record
  • Reactions or likes joined to the post they belong to
  • Category, channel, or space labels for the breakdowns

How do you build it?

  1. Land forum, community-platform, and event data in a database and keep member IDs, post timestamps, event IDs, and RSVP status.
  2. Build models at the grain this dashboard needs, with the active-member window and the check-in rule as explicit columns.
  3. Create one saved question per card and certify the shared models and definitions.
  4. Add dashboard filters for Date range, category or channel, staff vs. community, post type, member segment.
  5. 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

Median time to first reply on questions, by week (PostgreSQL)PostgreSQL
WITH questions AS (
  SELECT
    p.post_id,
    p.topic_id,
    p.created_at
  FROM community_posts p
  WHERE p.parent_post_id IS NULL
    AND p.post_type = 'question'
    AND p.created_at >= CURRENT_DATE - INTERVAL '90 days'
), first_reply AS (
  -- Only replies from someone other than the asker count as a response.
  SELECT
    q.post_id,
    MIN(r.created_at) AS first_reply_at
  FROM questions q
  JOIN community_posts r
    ON r.topic_id = q.topic_id
   AND r.created_at > q.created_at
   AND r.member_id <> (
     SELECT member_id FROM community_posts WHERE post_id = q.post_id
   )
  GROUP BY q.post_id
)
SELECT
  date_trunc('week', q.created_at)::date AS week,
  COUNT(*) AS questions_asked,
  COUNT(f.first_reply_at) AS questions_answered,
  ROUND(
    100.0 * COUNT(f.first_reply_at) / NULLIF(COUNT(*), 0), 1
  ) AS answered_pct,
  ROUND(
    EXTRACT(epoch FROM PERCENTILE_CONT(0.5) WITHIN GROUP (
      ORDER BY f.first_reply_at - q.created_at
    )) / 3600.0, 1
  ) AS median_hours_to_first_reply
FROM questions q
LEFT JOIN first_reply f USING (post_id)
GROUP BY 1
ORDER BY 1;

Dashboards

Integrations

Metrics

Analytics

FAQ

Why median time to first reply rather than average?
Because one question that sat unanswered for three weeks drags the average into meaninglessness. Response-time distributions are long-tailed by nature, so report the median for the typical experience and p90 for the tail — never the mean.
How do I count questions that were never answered?
Keep them in the denominator and out of the duration math. If unanswered questions are excluded entirely, response time improves every time the community ignores something. The pattern above uses a LEFT JOIN so unanswered questions still count toward the answered rate.