Watches what visitors do on a page: records sessions, draws heatmaps of clicks and scroll depth, and asks them a question in a pop-up survey.
Build me session replay and heatmaps that replace Hotjar — and read the warning first. Two things make this ALMOST. **Replay that survives real pages** — single-page applications, shadow DOM, lazy content — is genuinely difficult. And **automatic masking**, without which a recording quietly becomes a database of what people typed, including things they should never have typed into a form you are recording. That second one is not a technical risk, it is a breach waiting to happen. Mask by default or do not build this. STACK - Node 20+ with Fastify - SQLite through better-sqlite3 for metadata, files or object storage for the streams - rrweb for recording and playback. Do not write a DOM recorder — it is years of edge cases, and the edge cases are exactly what makes this ALMOST - Playwright for page snapshots - Caddy in front MASKING, BEFORE ANYTHING ELSE - Mask by default, reveal by exception. The opposite ordering guarantees something sensitive is captured on the first day - Every input's value masked unless explicitly allow-listed. Password fields never captured under any configuration — delete the code path rather than making it a setting - Payment fields and anything marked sensitive replaced with blocks in the browser, before the data leaves. Masking on the server is too late - Text maskable by selector, so a page showing personal data records as layout without content - A test page with a password, a card number and an address, recorded, with the stored stream read by hand before this goes near production. Do that every release REPLAY THAT SURVIVES REAL PAGES - Single-page applications: record route changes as events so the timeline has meaningful boundaries, and make sure the DOM snapshot at each is complete - Shadow DOM and web components need explicit handling; a recorder that ignores them records a page with holes in it - Lazy-loaded content and virtualised lists produce enormous mutation streams. Cap the events per session and stop recording rather than degrading the page - Iframes and canvases are not captured unless deliberately enabled, and their absence is shown in the player rather than silently blank - Fonts and stylesheets must resolve at playback time — inline what you can, and store what you cannot, or every replay renders in a fallback font and looks wrong WHAT MAKES A REPLAY USEFUL - Automatic detection of rage clicks, dead clicks, error events and abandoned forms, marked on the timeline. Those markers turn hours of video into a short list worth watching - Console errors and failed requests beside the player - Skip inactivity by default, speed control, and a keyboard for the whole thing - Sampling: a percentage of sessions plus every session with an error, which is where the value is HEATMAPS - Per breakpoint, always. A click at 390 pixels and one at 1440 are not the same click, and one map over one screenshot is a picture of nothing - Coordinates stored as a selector plus an offset as well as a ratio, so the map survives a layout change - An element-based map — this button was clicked 412 times — is more useful than a pixel cloud and is immune to reflow. Build that first - Scroll depth normalised against the document height at the time, per breakpoint - A minimum session count before a map is shown, with the count displayed. Forty sessions looks convincing and means nothing SURVEYS - A short question triggered by page, behaviour or an event from your own code - Frequency rules first and conservative: once per person, not in the first session, not within days of another. A product that asks constantly is a product people mute RETENTION AND RIGHTS - Days, not months, enforced by a sweeper that deletes metadata and blobs - Deletion by user identifier in one command - Every replay viewing recorded with who watched what. That log is what keeps the tool honest inside your own company - All of it written in your privacy notice in plain words OPERATIONS - .env: DATABASE_PATH, BLOB_PATH, BASE_URL, HASH_SALT, SESSION_SECRET, RETENTION_DAYS, SAMPLE_RATE - Migrations on boot, each once; measure bytes per session early and set sampling from that - Health endpoint reporting ingest lag and free space WHAT MATTERS MOST Masking, then per-breakpoint maps. Read a real recorded stream by hand and look for anything you would not want to read aloud; everything else here is a video player.
What you lose
- Session replay that survives single-page apps, shadow DOM and lazy-loaded content
- Automatic masking of inputs, so recordings do not quietly become a database of typed passwords
- Heatmaps aggregated across viewport sizes rather than one screenshot with dots on it
- Storage and playback of thousands of sessions without you paying for the bandwidth
- On-page surveys with targeting rules and a response dashboard
If you would rather not build
- Microsoft Clarity — free, closest paid-feature parity, with its own tracking
- FullStory — paid, replay and analytics for larger teams
What it costs
as published on their pricing page
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $39/mo | — | — |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
OpenReplay
$0Session replay and DOM recording, self-hosted so the video never leaves your servers.
openreplay/openreplayfree · open source
PostHog
$0Product analytics, session replay and flags in one self-hostable stack.
PostHog/posthogfree · open source
Why this verdict
our own opinion · changed only by a person
52/100
Verdict kinda at 52: heatmaps and a one-question survey are a genuine weekend, and the relative-coordinate trick is the only hard idea in it. Session replay is the other half of the product and is a much larger build with a much larger privacy surface — the prompt deliberately leaves it out.
History
tracked since 9 Aug 2026 · nothing is ever overwritten
Questions about Hotjar
answered from the record above
Is Hotjar free?
No — the plan we track is $39 a month. Observe Plus around $39/month billed annually for 100 daily sessions; recordings and heatmaps are priced separately by volume.
Can you replace Hotjar by building your own?
ALMOST. A weekend of work, and real gaps remain. Replacement score 52 out of 100, build time a weekend. Read what you lose before you decide.
How much does Hotjar cost?
$39 a month on Observe Plus — $468 a year. Recorded 9 Aug 2026.
What do you lose by replacing Hotjar?
Session replay that survives single-page apps, shadow DOM and lazy-loaded content; Automatic masking of inputs, so recordings do not quietly become a database of typed passwords; Heatmaps aggregated across viewport sizes rather than one screenshot with dots on it; Storage and playback of thousands of sessions without you paying for the bandwidth; On-page surveys with targeting rules and a response dashboard. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Hotjar?
Yes: OpenReplay, PostHog. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

