Use case · Onboarding

Onboard users without a single ticket.

Why one team stopped shipping onboarding through the deploy pipeline, and started building tours that trigger themselves.

Nadia had shipped the product. What she couldn’t ship was the part where a brand-new user, alone in an empty account at 9pm, figured out what to do first. That part kept landing on the engineering backlog, and the engineering backlog kept winning.

Every onboarding tweak she wanted, a reworded tooltip, one more step, a nudge for users who stalled, was a ticket. The tour lived in the codebase, so changing it meant a pull request, a review, and a deploy. A one-word copy fix took three days and two other people.

The empty room

New users signed up and hit a blank slate. A meaningful share never came back. The team knew the shape of the problem, activation, but the fix always felt like real work: design the flow, get eng to build it, wait for the release train. So the empty room stayed empty, quarter after quarter.

The uncomfortable truth was that onboarding is content, not infrastructure. It changes weekly. It should never have been coupled to the deploy pipeline in the first place.

Onboarding that needs a deploy

Hand-built tours rot in a specific way. Someone renames a CSS class or moves a button, and the tour that pointed at it silently breaks. Nobody notices until a user reports a tooltip floating in empty space. The tour that was supposed to reduce support load quietly became a source of it.

And because every change was a deploy, iteration died. Nadia had a list of onboarding experiments she wanted to run. She ran none of them, because each one cost an engineer a day.

Flows that trigger themselves

She moved onboarding out of the codebase. A guided flow now lives in the dashboard as its own thing: it fires on its own when the trigger matches, a URL like /app/*, a tracked event like project.created, or a manual call from her own code. No update to attach it to, no deploy to change it.

Each flow carries its own audience and its own frequency. Show the welcome tour to new users only, once. Show the “you have not tried this yet” nudge to returning users who never fired the event. The rules that used to be scattered across custom code now sit next to the copy they govern.

Every step of the tour is a step in the funnel.

Bind once, don’t break

The refactor problem got solved once, at the source. Instead of pointing steps at brittle CSS selectors, the flow points at named elements the app registers: signalpad.registerElement("invite-btn", ref). Move the button, restyle it, wrap it in three new divs. As long as the ref is still registered, the tour still lands. The binding survives the rewrite.

What you doHand-builtSignalpad
Change the copyShip a deploy Edit in the dashboard
Target by plan or segmentCustom code Built in
Trigger on a page or eventCustom code Built in
Survive a UI refactorUsually breaks Bound to registered elements
Measure completionA separate tool Built-in funnel

The activation curve

Because the same system runs the tour and watches the events, every flow has a funnel: started, each step, completed. When a step bleeds users, Nadia can see exactly which one, and fix the copy that afternoon without asking anyone. Onboarding finally moved at the speed of the person who owns it.

“The tour used to be a quarterly project. Now it’s a Tuesday.”

That is the whole shift. Onboarding stopped being something engineering builds and started being something the product team runs, changes, and measures on its own.

Ship onboarding without shipping code.

Build a self-triggering tour in the dashboard, live in minutes. Free for up to 1,000 tracked users.