Mostly about the parts that are harder than they look: telling a dead click from a slow one, noticing a redesign without being told, and why a heatmap quietly starts lying the day after you ship.
Sampling the pointer on a 100 ms timer and counting grid cells turns a minute of mousemove from ~7,000 events into a few hundred integers — and produces a better signal than the trail would have.
You cannot tell from the DOM whether an element has a handler, so Isotherm detects dead clicks by watching what the user believed and whether the page blinked.
The SDK hashes the DOM skeleton with runs of identical siblings folded to `tag*`, so a new column forks the heatmap version but a 25th table row does not.
Painting each point in its final colour gives you a scatter plot with big dots; density has to compound in the alpha channel before anything gets a hue.
Caching a hydrated Site model made every second request 500 with __PHP_Incomplete_Class; caching a flat readonly value object fixed it and made the ingest path queueable.
An `await requestAnimationFrame` inside the snapshot settle pass hung forever in background tabs, holding the server's single-visitor election lock and blocking every other visitor.
Incrementing a bucket per scroll event counted one visitor several times in the shallow bands; the fix is a per-session high-water mark with the curve derived at read time.
An error that is only visible in debug mode is not handled, it is hidden — and in a browser SDK, "debug mode" means a mode nobody is ever in.
fetch() dies with the page, so Isotherm's final flush uses sendBeacon on visibilitychange → hidden — the only lifecycle event a mobile tab reliably gets.
Snapshots of a marketing page came back as a tall dark void, because reveal libraries hold elements at opacity:0 until an IntersectionObserver fires — and a snapshot has no scripts to fire it.
The site key ships in every tracked page's HTML. The Origin header is the only real gate, it stops browsers and not curl, and two of the comments I wrote around it are wrong.
One dashboard query left-joined two has-many tables and aggregated; every SUM came out multiplied by the session count, and nothing looked broken.
Drawing a heatmap needs a copy of the page, but asking every visitor for one turns a customer's traffic spike into an attack on your own server — so the server elects exactly one.
Isotherm calls it rage at three trusted clicks within 1000 ms that are each within 40 px of the newest one, resets after emitting, and draws each as a discrete marker.
A headless screenshot can't log into the admin panel it's supposed to photograph, and a flat image has no elements to re-anchor clicks onto. The DOM snapshot is the cheaper answer.
Old clicks drawn over a new layout still render, still look plausible, and are wrong — so Isotherm fingerprints the DOM and lets the page declare its own version instead of asking a human to.