Skip to main content
LIVE · DEVSOLEIL
Retail · PropTech

E-Max PCM  Retail Footfall & Occupancy Analytics

Multi-tenant analytics platform that turns real-time camera-sensor webhooks into footfall, occupancy, dwell-time, and demographic insights for shopping-mall operators — with streaming Excel reports and strict per-tenant data isolation.

Overview

The brief.

Shopping malls install two families of vision sensors: perimeter entry/exit cameras that count the whole mall, and in-store area sensors that count individual zones. E-Max PCM is the ingestion and analytics brain behind them — devices push high-frequency webhooks, the platform validates and stores every event, keeps a live occupancy figure per camera, and answers the business questions: how many people entered today, which entrance is busiest, what's the adult/child split, how long do people stay.

Project snapshot

The essentials.

Industry
Retail · PropTech
Services
web-apps
Client
E-Max PCM logoE-Max PCM
Riyadh, Saudi Arabia
Headline outcome
~60×Webhook noise cut
Tech stack

What we built with.

The project

What we built, in detail.

The backend is an API-first Laravel service that absorbs every sub-endpoint the camera firmware emits through a single wildcard webhook route, dispatching by URL path and payload shape — one entry point, three behaviors (live presence, count events, historical replay), resilient to firmware naming drift. Aggregation endpoints are time-bucketed and cached, covering footfall, current occupancy, traffic quality, dwell time, demographic splits, per-entrance breakdowns, and day-by-hour heat maps. A React single-page app consumes the API, and on-demand Excel reports stream large workbooks without memory blow-ups. Every domain row carries a tenant key enforced by a global query scope, so one deployment serves many mall operators with strict data isolation and role-based access.

Key features

The pieces that
make it click.

01

Real-time webhook ingestion

A single wildcard route absorbs heartbeats, count uploads, and historical replays from the line-crossing cameras, tolerating both the official spec spelling and the firmware's observed spelling.

02

Live occupancy tracking

Presence pings update a single current-occupancy figure per device instead of inserting into a high-volume table, so "how many people are in this zone right now" is answered instantly.

03

Statistics API

Mall-level and area-level endpoints for footfall, occupancy, traffic quality (passby/turnback/conversion), dwell time, adult/child and gender splits, per-entrance breakdowns, and day×hour heat-map patterns — time-bucketed and cached.

04

Streaming Excel reports

A report-registry/builder pattern maps each report type to a builder class; roughly ten report catalogues stream large workbooks with low memory, keeping mall and area data sources strictly separate.

05

Multi-tenant with role-based access

Every row carries a tenant key auto-filtered by a global query scope; super-admin, tenant-admin, and read-only viewer roles are enforced by middleware, with super-admin tenant impersonation for support.

06

Remote device management

The API pushes configuration (upload interval, data mode, timezone) back to cameras inside heartbeat responses, and surfaces unknown device serials seen in the wild but not yet registered.

Challenges & solutions

What was hard.
How we solved it.

Challenge

Camera firmware spelling drifts from the official protocol spec.

Solution

Webhook dispatch keys on both the URL path suffix and the payload signature — the presence of a live-occupancy field, a count field, or a replay array decides the behavior — so one endpoint handles three sub-protocols and survives firmware naming drift.

Challenge

Adding multi-tenancy to a live schema without breaking production.

Solution

A staged migration sequence — add a nullable tenant column, seed a default tenant and backfill, then lock it NOT NULL — plus a shared trait and global scope that make isolation automatic, with documented escape hatches for the two bulk paths that bypass the ORM.

Challenge

The device protocol mixes three time units, and reports must show Riyadh time.

Solution

Timestamp conversions (seconds, milliseconds, microseconds) are centralized in one handler helper; the database stores UTC, and the display timezone is applied only at the stats/report boundary.

Challenge

Future analytics needs are unknown — schema changes must not require re-ingesting data.

Solution

Every event row retains the full original webhook payload in a JSON column alongside the extracted fields, so promoting a nested field to its own column later is a backfill, not a data migration.

The result

What changed
after launch.

~60×Webhook noise cut

The platform speaks the camera protocol well enough to push configuration back down to devices inside heartbeat responses — remotely tuning upload intervals to cut webhook noise roughly 60×. Multi-tenancy was retrofitted onto the live single-tenant schema with a staged nullable → backfill → NOT NULL migration sequence, with no downtime and no data loss.

Tags
#Laravel#PHP#MySQL#REST API#Sanctum#Multi-tenant#IoT Webhooks#Retail Analytics#Excel Reports#React#Pest
Visit the live app (login)
Previous project

RSE Automation ERP

RSE

Next project

Metal Flow — Bilingual ERP for Metal Trading

Metal Flow

Reach us directly — no forms, no wait

Let'stalk.

Drop us a message or call us directly. We reply to every enquiry — usually the same day.