What goes in a people analytics dashboard in Metabase?
A people analytics dashboard gives leaders a governed view of workforce shape and movement: headcount, starts, exits, departments, locations, employment status, and time off. Build it from HRIS data synced into a permissioned database model.
What does a people analytics dashboard look like?
Here's the layout this guide builds: headcount against plan at the top, then the shape of the workforce by department, location, employment status, and manager, then movement, absence planning, and the records people ops still needs to clean up. Read it in the monthly business review and before each planning cycle.

Which cards belong on this dashboard?
- Current headcount by department, location, manager, and employment status
- Starts and exits by month
- Open positions and filled positions by org
- Time off scheduled by team and month
- Headcount plan vs. actual
- Employee records with missing required fields for ops cleanup
What data does this dashboard need?
- Worker or employee table with status, start date, termination date, department, location, manager, and worker type.
- Organization, department, location, and cost-center reference tables.
- Position or requisition table for plan vs. actual.
- Time-off requests and balances when absence planning is in scope.
How do you build it?
- Sync ATS or HRIS data into a database, then connect that database to Metabase.
- Create reusable models for jobs or requisitions, applications, stage history, interviews, offers, sources, workers, and organizations as needed.
- Create one saved question per card, using consistent metric definitions and permissioned models.
- Add dashboard filters for department, location, role family, recruiter, hiring manager, source, and date range.
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'
) AS month
)
SELECT
m.month,
COUNT(*) FILTER (
WHERE w.start_date < m.month + INTERVAL '1 month'
AND (w.termination_date IS NULL OR w.termination_date >= m.month)
) AS ending_headcount,
COUNT(*) FILTER (WHERE date_trunc('month', w.start_date) = m.month) AS starts,
COUNT(*) FILTER (WHERE date_trunc('month', w.termination_date) = m.month) AS exits
FROM months m
LEFT JOIN modeled_workers w
ON w.start_date < m.month + INTERVAL '1 month'
GROUP BY m.month
ORDER BY m.month;