Pulse Analytics

Custom analytics dashboard tracking pageviews, clicks, and full user journeys across multiple sites

Next.jsTypeScriptSupabaseVercelTailwind CSSPostgreSQL
pulse.kevinnorgaard.com/?mock=true
Pulse Analytics screenshot

01Problem Statement

Google Analytics is bloated, privacy-invasive, and blocked by most ad blockers — meaning traffic data for personal projects is incomplete and unreliable. I needed a lightweight, self-hosted analytics tool that could track real user behavior across multiple subdomains (portfolio, project sites) with full session-level detail, without relying on third-party cookies or scripts that get blocked.

02Architecture

A lightweight first-party tracker script (< 4 KB) is embedded on each site and sends events (pageviews, clicks, scrolls, time-on-page) to the Pulse API. The API route enriches events with geo data from Vercel edge headers (country, region, city) and device metadata, then inserts into Supabase. The dashboard queries Supabase to render metrics, charts, geographic breakdowns, and full session-level user journey timelines with cross-subdomain stitching.

03Data Model

Supabase Events Table

CREATE TABLE events (
  id            UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  site_id       TEXT NOT NULL,
  visitor_id    TEXT NOT NULL,
  session_id    TEXT NOT NULL,
  event_type    TEXT NOT NULL,        -- pageview | click | scroll | time_on_page | dead_click | rage_click
  timestamp     TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  url           TEXT,
  title         TEXT,
  referrer      TEXT,
  scroll_depth  SMALLINT,
  element_text  TEXT,
  element_href  TEXT,
  active_time   INTEGER,              -- ms spent on page
  click_count   SMALLINT,             -- for rage clicks
  country       TEXT,
  region        TEXT,
  city          TEXT,
  device_type   TEXT,
  browser       TEXT,
  os            TEXT
);