Feedback and bug reporting inside a product, with screenshots, session details and survey prompts, routed into issue trackers.
Build me in-product feedback that replaces Usersnap: bug reports with the environment attached, survey prompts, and a loop back to the person who reported it. STACK - Node 20+ with Fastify - SQLite through better-sqlite3, WAL mode - One embeddable widget under 40KB gzipped, from my own domain - Caddy in front THE DATA MODEL - projects: id, name, allowed_origins_json, widget_secret, is_active - feedback: id, project_id, kind, title, body, priority, status, page_url, reporter_external_id, reporter_email, reporter_name, assignee_id, created_at, resolved_at — kind is bug, idea, question, or a survey response - screenshots, annotations, environment, console_events, network_events — as in any visual bug reporter, and the environment is the half reporters never provide - comments: id, feedback_id, author_kind, body_md, is_internal, created_at — internal notes rendered so differently they cannot be mistaken for a reply - external_links: id, feedback_id, tracker, external_id, url, last_synced_at, external_status - surveys: id, project_id, kind, definition_json, targeting_json, frequency_json, is_active - displays and responses, as in any survey tool - events: id, feedback_id, kind, actor, at — append-only THE LOOP BACK, WHICH IS WHAT THIS PRODUCT IS FOR - A bug reported and never acknowledged teaches somebody not to report the next one - So: an automatic acknowledgement immediately, with a reference; a notification when the status changes; and a notification when it is fixed - Two-way sync with the issue tracker is what makes that automatic. Push the report in, store the external identifier, poll or receive webhooks for status changes, and map them back - The mapping between tracker statuses and reporter-facing states is configured once and deliberately: 'in progress' and 'in review' are both 'we are working on it' to the person who reported it - Never expose the tracker's internal comments to the reporter. The internal note and the reply are different things, and confusing them is the failure that costs you a customer WHAT IS CAPTURED WITHOUT ASKING - Browser, version, operating system, device, screen and viewport, pixel ratio, language, time zone - Console output and failed network requests from the last N seconds. This is the most useful thing in the report and nobody ever attaches it manually - The page URL, the referrer, and traits my application passed in through a signed token — plan, account, role, tenure. 'Which customers hit this' is then a filter rather than an investigation - A screenshot, annotated by the reporter - All of it captured from a real person's screen, so mask by default: never a password field, never a payment field, and redaction by selector for anything else THE WIDGET - A launcher, or triggered from my own code at the moment it is relevant - Three steps: capture, annotate, describe. Every extra step loses reports - Shadow DOM, my accent, dark and light, keyboard operable, focus trapped, Escape closes - Works on a phone - Identified from a signed token where the user is known, so no one types their own email address, and anonymous where they are not SURVEYS ALONGSIDE - The same widget asks a question when it is useful: after a flow completes, on a page, or triggered by an event my code sends - Targeting by trait and by behaviour, evaluated on the server so the audience list never reaches the browser - Frequency rules first and defaulted conservatively: not within N days of anything else, once per person, never in the first session. A product that asks constantly is a product people mute - Partial responses kept, because two answers out of five is still information TRIAGE - An inbox with thumbnails, filters by project, status, priority, page, browser and any trait - Grouping by page and by browser, which is how one bug is seen behind eleven reports - Merge duplicates, keeping every reporter attached so all of them are notified when it is fixed. That single behaviour is worth more than any dashboard - Assign, prioritise, comment internally, reply to the reporter PRIVACY - A stated retention with a sweeper that actually deletes - Deletion by reporter identifier in one command - Everything sent to my own domain only; no third-party request from the widget, ever OPERATIONS - .env: DATABASE_PATH, STORAGE_PATH, BASE_URL, WIDGET_JWT_SECRET, SESSION_SECRET, HASH_SALT, TRACKER credentials, RETENTION_DAYS - Migrations on boot, each once - Tracker credentials encrypted at rest, sync incremental with a cursor, idempotent by external id - Nightly backup off the machine, restore script - Health endpoint reporting sync lag per tracker WHAT MATTERS MOST Automatic environment capture and the notification when it is fixed. The first turns a vague report into a fixable one; the second is the only reason anybody reports a second bug. Build both before the annotation tools are pretty. Give me the repository, the widget, migrations, .env.example, one tracker integration with two-way status mapping, and a README with deploy steps behind Caddy.
What you lose
- Session and environment detail captured without the reporter doing anything
- Two-way sync with issue trackers, so a closed ticket notifies the reporter
- Survey prompts and bug reports through one widget
If you would rather not build
- A labelled issue template, which is free
What it costs
as published on their pricing page
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $69/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
html2canvas
$0Screenshot the page from inside the browser with no permission prompt.
niklasvh/html2canvasfree · open source
Formbricks
$0Self-hosted feedback collection with an API to route responses.
formbricks/formbricksfree · open source
Why this verdict
our own opinion · changed only by a person
78/100
Verdict yes at 78. Telling the reporter when their bug is fixed is the feature that keeps reports coming, and it is one webhook.
History
tracked since 10 Aug 2026 · nothing is ever overwritten
Questions about Usersnap
answered from the record above
Is Usersnap free?
No — the plan we track is $69 a month. Basic from around $69/month billed monthly, cheaper annually.
Can you replace Usersnap by building your own?
YES. Replaceable in one session with an AI coding agent. Replacement score 78 out of 100, build time one session. Read what you lose before you decide.
How much does Usersnap cost?
$69 a month on Basic — $828 a year. Recorded 10 Aug 2026.
What do you lose by replacing Usersnap?
Session and environment detail captured without the reporter doing anything; Two-way sync with issue trackers, so a closed ticket notifies the reporter; Survey prompts and bug reports through one widget. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Usersnap?
Yes: html2canvas, Formbricks. 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

