signup_completed → profile_filled → first_project_created → invited_teammate → activated. You emit those steps from your code with step() and define the same list in the dashboard. Events are matched to the funnel by name, and each stage shows its conversion rate, drop-off, and time to complete.
How it works
A funnel has two sides, joined by name:- In your code: you call
step(name)at each point where a user reaches a milestone. Names are plain strings of 1 to 100 characters, with no schema and no predefined vocabulary. - In the dashboard: you create the funnel and put those step names in order.
step() call has to match them character for character, or the step stays empty.
Each step() call records one event with a timestamp, the identified user if there is one, and any properties you attach. The server orders those events per user and builds the funnel from them.
You don’t need to call steps in order, and you don’t need to call every step. Users who skip steps show up as drop-offs in the funnel between the last step they hit and the next one they didn’t.
Traits vs properties
You attach metadata to events in two places, and the distinction matters for how you analyze your funnel later.- Traits go on the user via
identify(). Use them for things that are true about the user across all events: plan, acquisition source, email, name. Traits ride on every event that follows until you callidentify()again orreset(). Eachidentify()call replaces the identity and traits wholesale; nothing is merged. - Properties go on a single event via the second argument to
step(). Use them for things specific to that one moment: which plan the user selected at this step, the button variant they clicked, a referrer from the current page.
step() call, it belongs in identify().
A typical onboarding funnel
Here’s what a five-step onboarding funnel looks like when instrumented across a real application. Each call happens in the context where the milestone actually occurs, not all in one block.Naming best practices
Consistent names make funnels easier to read and compare over time.- Use
snake_case.signup_completed, notSignupCompletedorsignup-completed. - Use past-tense verbs. Events describe something that already happened.
profile_filled, notfill_profile. - Be specific.
first_project_createdis more useful thanproject_eventwhen you want to segment later. - Keep names stable. Renaming a step in your code without updating the funnel in your dashboard will break the match. Treat step names like API contracts.
FAQ
Do I have to create the funnel in the dashboard before I start tracking?
Do I have to create the funnel in the dashboard before I start tracking?
No. You can send
step() events first and create the funnel afterward; every event is stored regardless. You just won’t see conversion numbers until the funnel and its step order exist in the dashboard.What if a user skips a step?
What if a user skips a step?
Steps are independent events. Order is not enforced and no step is required. If a user never reaches
invited_teammate, no event is recorded for it, and the funnel shows the drop-off between the last step they hit and this one.Can I track the same step multiple times?
Can I track the same step multiple times?
Yes. Each
step() call creates a new event with its own timestamp. If a user completes first_project_created twice, two events are recorded. The funnel counts each user once per step, using their first occurrence by default.How do I track anonymous users?
How do I track anonymous users?
You can call
step() before identify(). Events are recorded with userId: null and the current session ID. Once you call identify(), later events belong to that user, and the session’s earlier anonymous events are linked to them at query time, so the funnel counts the whole journey as one person. Anonymous events stay anonymous only when nobody identifies in that session.Can I use the same step name in multiple funnels?
Can I use the same step name in multiple funnels?
Yes. Step names are strings; they have no owning funnel. If
signup_completed is the first step in your onboarding funnel and also appears in a separate “trial-to-paid” funnel, a single step('signup_completed') call feeds both.What’s next
Identity and sessions
How
identify(), reset(), and sessions tie events to users.API reference: step()
Full reference for the
step() method, including property constraints.