Design an onboarding checklist users actually finish
Most onboarding checklists are abandoned in the first session. Six rules that keep the steps finishable — and how to see which step is losing people.
A checklist is a promise that the product can be learned in a handful of steps. Most of them break that promise in the first session: the panel opens, the user reads step one, and nothing in the interface leads them to it. The steps themselves are rarely the problem. The shape of the list is.
These are the rules that hold up in a product where the checklist is the only onboarding you get, in the order they cost you the most when you break them.
1. Three to five steps, and the first one is already doable
A checklist is a map of the shortest path to value, not a list of the product's features. If a step needs a decision the user has not made yet — pick a plan, invite a teammate, connect a data source — it belongs later, or not at all. The first step has to be something they can finish right now, in the screen they are looking at.
When a list grows past five items, the end stops being visible, and a checklist without a visible end is a to-do list. Cut until it fits on one screen without scrolling.
2. One action per step
A step that asks for two things is two steps, and the user only ever reads the first one. "Create your project and invite a teammate" finishes half the time the first half is done, and that is exactly the state a per-step funnel should not be able to report.
The test is mechanical: can a single click or a single form submission complete this step? If the answer is no, split it.
3. Every step carries a link to the place it happens
This is the step most implementations skip. A checklist row without an action URL is a sentence, and a sentence does not move anyone. Each step carries its own action_url for this reason — the widget navigates, the host app does not have to listen for anything.
- Point at the exact screen, not the dashboard root.
- Use a stable route. A step that 404s after a redesign is worse than a step that never linked.
- If the step happens outside your product — installing the script, sending an API call — say so in the step's copy and link the documentation instead of a dead end.
4. Progress is per person, and it follows them
Progress stored in localStorage disappears when the user signs in on their laptop, which is precisely when they are most likely to be finishing onboarding. Progress is server-side state keyed by your user id: the checklist should be able to answer "where was I?" on any device, in any browser, after any redeploy.
This is what the widget's user-id attribute exists for. Pass your own id, not an email address — an identifier your product already trusts, so the checklist never becomes a second place where a person has to be identified.
5. Editing the list must not reset anyone
The first week of a checklist in production is a rehearsal: the copy is wrong, one step belongs later, a step that looked obvious is not. If editing the configuration invalidates progress, nobody will dare touch it, and the list freezes in its first, worst version.
Steps are addressed by key, not by position. Adding a step, reordering the list or renaming the copy changes nothing for a user who has already finished something — only deleting a step they completed does, and that should be deliberate.
6. Measure per step, not just completion
"40% of users finish onboarding" tells you nothing you can act on. Which step loses the most people, and how long does each stay open? Those two numbers point at a specific screen.
Completion is reported per step, and the funnel is the interface: the step with a big drop between "seen" and "done" is the one whose action_url, copy, or prerequisite is wrong. Look at that step before touching the wording of any other.
The checklist is not a tour
A guided tour shows what the interface contains. A checklist says what the user has to do — and it survives the tour, the reload, the second device and the support email. If you are deciding between them, the question is what you want to be true next week: with a tour you know a user has seen the arrow; with a checklist you know which two steps they still owe.
The widget is one script tag and no dependencies:
<script src="/sdk/v1/gs.min.js" defer></script>
<getting-started endpoint="https://gettingstarted.marthaia.com"
project-key="pk_your_publishable_key"
user-id="{{ current_user.id }}"></getting-started>Configure the steps in the console and see the widget running against your own draft before you deploy anything — no key, no network: open the console. The full reference, including the server-to-server API for backends that complete a step out of band, is in the docs.