Usetiful

usetiful.comcontributed by Samuele Ongaro

YES

Replaceable in one session with an AI coding agent.

Product tours and onboarding checklists added to an application without changing its code, using a script and a point-and-click editor.

Promptfree, for everyone, and the only version there is
Build me a product tour tool that replaces Usetiful: a few guided steps inside my own app, shown once, to the right people, without a third-party script watching everything.

STACK
- Node 20+ with Fastify and SQLite for the admin and the payload
- One embeddable script, vanilla, under 12KB gzipped, served from my own domain
- Server-rendered admin, no client framework
- Caddy in front

THE DATA MODEL
- tours: id, name, status, kind, priority, created_at
- steps: id, tour_id, position, selector, fallback_selector, placement, title, body_md, media_path, advance_on, wait_for_selector
- targeting: id, tour_id, rule_kind, operator, value — url pattern, user attribute, event fired, first seen within N days, viewport width
- progress: id, tour_id, user_key_hash, step_reached, started_at, completed_at, dismissed_at, snoozed_until
- checklists: id, name, items_json — a persistent list, separate from a linear tour
- hotspots: id, tour_id, selector, body_md — the small pulsing dot that explains one control
- Kinds: tour, checklist, hotspot, announcement. Each renders differently; the kind is a column

FINDING THE ELEMENT, WHICH IS WHERE THESE BREAK
- A step points at a CSS selector, plus a fallback, plus a timeout
- If neither selector resolves within the timeout, the step is skipped and the skip is recorded — never show a tooltip pinned to the top-left corner of the page because the target was not there
- Wait for the element rather than assuming it exists: applications render late
- Re-anchor on scroll and resize, and on DOM changes within the target's parent
- The admin has a picker: open your own app with a query parameter, click the element, get the selector, and it prefers a data attribute over a fragile CSS path — and says so when the selector it produced is fragile

SHOWING IT, AND STOPPING
- One tour at a time, chosen by priority. Never two tooltips on a screen
- Never restart a completed tour. Snooze means snooze: a dismissed tour does not come back for N days, and a dismissed-twice tour does not come back at all
- A tour can require an event before it starts, so it fires when somebody reaches the feature rather than on their first page
- Everything is skippable from the first step, and the skip is one click, not a menu
- Progress is stored server-side against the user key the host app supplies, so it survives a new browser

THE OVERLAY
- Highlight the target by cutting a hole in a dim layer, and let clicks through to the target when the step advances on interaction
- Keyboard: Escape skips, arrows move, focus is placed on the tooltip when it opens and returned when it closes
- Never block scrolling entirely; never move the page under the reader
- Respects prefers-reduced-motion and prefers-color-scheme, and takes colour and radius from a config
- Renders from a single JSON payload fetched once per session

CHECKLISTS
- A persistent widget with items that complete when an event arrives, not when somebody ticks a box
- Progress bar, dismissible, and it remembers being dismissed
- Each item can open a tour, a link, or a page

MEASURING
- Per tour: started, completed, dismissed, average step reached, and the step where most people leave
- Per step: shown, advanced, skipped, and how many times the selector was not found — that last number is the health of the tour
- Filter by any attribute the host app sent
- No session replay, no heatmaps, no autocapture

PRIVACY
- The user key comes from the host application; without one, a session-scoped hash is used and nothing persists across browsers
- No cookie, no IP stored, no third-party request
- The script talks to your domain only

THE INTERFACE
- Build a tour with the steps on the left and a preview of the tooltip on the right
- Targeting rules read as sentences
- Dark and light, one accent

OPERATIONS
- .env: DATABASE_PATH, BASE_URL, ADMIN_PASSWORD_HASH, HASH_SALT, ALLOWED_ORIGINS
- Migrations on boot, each once
- The payload endpoint is served from memory with an ETag: every page view of the host app hits it
- Nightly backup off the machine, restore script
- Health endpoint

WHAT MATTERS MOST
Element resolution and the do-not-repeat rules are the product. Build the script, the selector waiting and the skip memory first, then put a three-step tour into a real application and reload it twenty times. If it appears twice, or points at nothing once, nothing else matters.

Give me the repository, the embeddable script, migrations, .env.example, a seed tour of three steps, and a README with deploy steps behind Caddy.

What you lose

  • An editor that lets a non-developer point at an element and write a step
  • Selectors that survive a front-end change, which is the fragile part
  • Progress tracked per user across sessions

If you would rather not build

  • Intro.js, long-established
  • A dismissible banner, which is often enough

What it costs

as published on their pricing page

PlanBilled monthlyBilled yearlyLast 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

driver.js

$0

A tiny library for highlighting elements and stepping through a tour.

kamranahmedse/driver.jsfree · open source

Shepherd

$0

Guided tours with positioning and a step model already built.

shipshapecode/shepherdfree · open source

Why this verdict

our own opinion · changed only by a person

82/100

Verdict yes at 82. Requiring a data-tour attribute is the whole difference between a tour that lasts and one that breaks on the next deploy.

History

tracked since 10 Aug 2026 · nothing is ever overwritten

Interest · last 30 dayspeak 2/day
views01230 Aug4 Sept9 Sept14 Sept19 Sept24 Sept28 Sept
— views— prompt copies none yet— votes none yet

Questions about Usetiful

answered from the record above

Is Usetiful free?

No — the plan we track is $39 a month. Plus from around $39/month billed monthly, cheaper annually.

Can you replace Usetiful by building your own?

YES. Replaceable in one session with an AI coding agent. Replacement score 82 out of 100, build time one session. Read what you lose before you decide.

How much does Usetiful cost?

$39 a month on Plus — $468 a year. Recorded 10 Aug 2026.

What do you lose by replacing Usetiful?

An editor that lets a non-developer point at an element and write a step; Selectors that survive a front-end change, which is the fragile part; Progress tracked per user across sessions. If any of those carry weight for you, keep paying.

Is there an open-source alternative to Usetiful?

Yes: driver.js, Shepherd. The prompt on this page is for when you want it your way instead.

Related entries

same category first, most replaced first

All 29 in Customer support

Not sending yet

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

Esc