Case study 03
Designing a Workforce Productivity Analytics Platform
Turning activity signals into legible productivity insight — without pretending data is neutral.
- Project
- Employee Productivity & Workforce Analytics Platform
- Published
- 24 July 2026
- Reading time
- 10 min read
- Sections
- 11
Context
Organisations can usually describe what a team delivered. They are much less able to describe how the working day was spent: which applications were in use, which sites absorbed time, how much of the day was genuinely active, and how that changes across a week.
This platform was designed to answer those questions from a centralised administrator dashboard.
Problem
Without a shared, structured view of activity, workload discussions run on anecdote. Managers check in, employees self-report, and neither side has a common record to refer to.
The engineering problem was harder than the reporting one: activity data arrives continuously, is high-volume, is inherently noisy, and includes the most sensitive kind of signal a workplace can collect.
Goal
- Give administrators one dashboard for workforce activity and productivity.
- Track application usage, website activity, active time and idle time.
- Support periodic screenshot capture with explicit retention rules.
- Produce daily, weekly and monthly summaries per employee.
- Keep the data model able to grow from individual events to organisation trends.
Constraints
- No fabricated metrics — while the platform is in development, no numbers are published.
- No claim of legal compliance; monitoring policy is the deploying organisation's responsibility.
- The dashboard must stay responsive with thousands of events per employee per week.
- Screenshots are the most sensitive data type on the platform and needed explicit handling.
Approach
The core idea was to separate collection from interpretation. Raw signals are normalised into sessions first — an application interval, a site visit, an active/idle classification — and only then aggregated into summaries. Dashboards never query raw events directly.
That split keeps the reporting layer fast and, just as importantly, keeps one set of definitions. 'Active time' means the same thing on every screen because it is computed in exactly one place.
Architecture
Managed endpoints
│ (activity signals)
▼
Collector / API ── normalise ──► Activity sessions
│ │
▼ ▼
Screenshots (retention-limited) MySQL
│
▼
Scheduled aggregation jobs
│
▼
Daily · weekly · monthly rollups
│
▼
Administrator dashboard + exportsImplementation
- Employee, team and device records as the reporting spine.
- Activity sessions with active and idle classification.
- Application usage and website activity intervals.
- Screenshot capture events with retention windows.
- Scheduled rollups so dashboards read aggregates, not events.
- Workforce overview, employee drill-down and activity timeline views.
- Filters by employee, team, date range and device; exportable reports.
// Activity is normalised into sessions before it is aggregated.
$session = ActivitySession::open($employee, $device, $startedAt);
$session->recordAppUsage($processName, $windowStart, $windowEnd);
$session->recordSiteVisit($host, $openedAt, $closedAt);
$session->classify($activeSeconds, $idleSeconds);
// Rollups are rebuilt on a schedule so dashboards stay fast.
DailySummary::rebuildFor($employee, $date);Challenges
- Idle detection — a long read and an abandoned desk produce identical input; the classification has to be defensible.
- Volume — per-minute sampling across a workforce multiplies quickly and must be aggregated before it reaches a screen.
- Interpretation — a productivity number without context is an accusation, so the dashboard leads with trends and shape rather than a single score.
- Sensitivity — screenshots and website activity change the character of the data and had to be designed around, not appended.
Solution
Three altitudes of the same data: an organisation-level overview for pattern, a team-level trend for comparison, and an individual timeline for detail. A manager moves between them instead of choosing one view.
Aggregation happens on a schedule rather than on request, so the dashboard reads from rollups. Screenshots carry an explicit retention window, and the language of the interface stays in workforce analytics and activity insight rather than surveillance framing.
Result
In progress. The data model, session normalisation, aggregation jobs and administrator dashboard views are the delivered scope so far.
Lessons Learned
- Define metrics once, in one place. Derived numbers computed in several places will disagree, and disagreement destroys trust in a dashboard.
- Aggregate before you display. Event-level data belongs in the drill-down, never in the overview.
- Data sensitivity is a design input, not a compliance checkbox — it changes what the interface should emphasise.
- An honest 'in progress' status is more credible than a polished page full of invented numbers.
Next step
Have something to build — or something to automate?
Tell me what the system needs to do. I will tell you honestly whether I am the right person to build it.