All posts

Collecting Heatmap Data Without Drowning Your Database

August 16, 20267 min read

The volume problem

A pageview is one event. A session with heatmaps enabled produces dozens: every click, scroll milestone and rage-click burst. Naive collection turns a manageable event stream into an unmanageable one.

Three decisions keep it affordable.

Normalise coordinates at capture

Raw pixel coordinates are meaningless across devices — x: 840 is the right edge on a phone and the centre on a desktop.

Store a percentage of the viewport instead:

const x = +(event.clientX / window.innerWidth * 100).toFixed(2);
const y = +(event.pageY / document.body.scrollHeight * 100).toFixed(2);

Two benefits: one heatmap works across every screen size, and two decimal places is enough precision while keeping the values small.

Scroll depth as milestones, not a stream

Tracking scroll position continuously produces an event per frame. Nobody needs that resolution.

Fire once per milestone — 25%, 50%, 75%, 100% — and only the first time each is reached in a session. A long article produces four events instead of several hundred, and the reports are identical, because "how far down did people get" is a milestone question.

Capture the element, not just the point

A click at 34% across and 71% down tells you where people clicked. It does not tell you what they clicked, which is the actually useful question.

Record a stable selector and the visible text alongside the coordinates. Then "which button gets clicked most" becomes a GROUP BY rather than a visual estimate from a blob.

SELECT text, selector, COUNT(*) AS clicks, COUNT(DISTINCT user_id) AS users
FROM events
WHERE site_id = ? AND type = 'click' AND path = ?
GROUP BY text, selector
ORDER BY clicks DESC
LIMIT 30;

Sample on high-traffic pages

A page with a million views a month does not need every click to produce an accurate heatmap. Sampling at 10% gives a visually identical result for a tenth of the storage.

Sample by session, not by event — sampling individual events breaks funnel and sequence analysis, because you end up with partial journeys.

Rage clicks are worth isolating

Three or more clicks on the same element within about a second usually means something looks interactive and is not. That is a specific, actionable signal, and it is worth detecting at capture time rather than reconstructing later.

It is often the single most useful thing heatmap data produces.

Try InsightsTrack free

Open-source, self-hosted, privacy-first analytics — explore the live demo, no install required.

Open live dashboard