Visitor Analytics & Live Alerts
First-party visitor analytics built into the CMS — anonymous session and page-view tracking, a live traffic dashboard, and real-time Slack/email alerts when someone visits or converts.
- Category
- CMS & Web
- Tech stack
- Next.js
- MySQL
- Slack webhooks
- Nodemailer
- Metrics
- Zero third-party trackers
- Real-time Slack + email alerts
- Role
- Design + build
Content
A tracking beacon in the public layout writes anonymous sessions, page views and conversion events to the CMS database (migration 0014). The Traffic tab on the analytics dashboard shows live visitors, uniques, views, bounce rate, and breakdowns by device, browser, country, referrer and top pages. A notification layer pushes new-visitor and conversion alerts to Slack (incoming webhooks) and email, with per-channel enable flags and graceful failure handling.
Problem
Third-party analytics are blocked by ad-blockers, over-collect data, and live outside the CMS. I wanted to know who is on the site right now and get pinged when it matters — without shipping visitor data to anyone else.
Decisions
First-party from the start: third-party analytics get ad-blocked, over-collect, and keep the data outside the system of record. Sessions are anonymous — no accounts, no cross-site identity — which gives up some analytical power and is the right trade for a personal site. The alert channels are wired to fail alone: Slack and email each have their own enable flag and their own error handling, so a webhook outage can never take a page view down with it.
Limitations
Anonymity is a real constraint, not a slogan — there is no returning-visitor identity beyond the session, so "who came back" is answered in aggregates, not names.
Outcome
Full visibility of site traffic with zero third-party trackers, plus real-time Slack pings on visits and conversions.
How this was built
Built with AI assistance (Claude Code). The architecture, the decisions and the trade-offs are mine; a lot of the implementation was written in pair with the model. I work this way deliberately — it's why one person can run a system this size — and the reasoning behind every call here is documented above.