Funnel Definition
Defining a funnel as an ordered sequence of steps with time bounds —so the drop-off rate between steps is measurable and comparable.
Why
A funnel is not just 'a series of pages'. It is a precisely defined sequence of user actions, with an order, a time window, and a definition of what counts as 'completing' each step. Without this precision, the funnel conversion rate is whatever the query happens to compute, and it changes every time someone edits the SQL. The definition matters because the funnel is the primary diagnostic tool: when conversion drops, the team asks 'where in the funnel?', and if the funnel steps are ambiguous (does 'viewed pricing' count if the user scrolled past without clicking?), the answer is meaningless. A well-defined funnel names each step as an event, specifies the order, sets a time window per step (and a max total time), and defines the entry cohort. This makes the drop-off rates stable, comparable across time periods, and actionable —you can point at step 3 and say '40% of users drop here, and it started on Tuesday'.
When
When you have a multi-step user journey (signup, activation, checkout) and need to measure where users drop off. Define before measuring.
How
1. List the user actions in order: step 1 = signup_submit, step 2 = email_verify, step 3 = first_project_create, step 4 = first_deploy 2. Define each step as a specific event with properties, not a page view —"visited /pricing" is ambiguous; "clicked 'Start trial' on /pricing" is precise 3. Set a time window per step: step 2 must occur within 24h of step 1; step 3 within 7d of step 2; step 4 within 1h of step 3 4. Set a max total funnel time: the entire funnel must complete within 14 days of step 1 —users who take longer are not in the funnel 5. Define the entry cohort: users who completed step 1 in the analysis window, excluding test/bot accounts 6. Define the completion semantics: a user "completes" step N if the step N event fires within the time bound after step N-1. A user who fires step N+1 without step N is counted as dropped at step N (not as completing the funnel via a shortcut) 7. Write the SQL or event query, pin it in the metrics dictionary, and add a unit test on a fixture 8. Compute the funnel: for each step, count users who reached it, and the drop-off rate = 1 - (reached step N+1) / (reached step N)
Example
# Funnel: Signup to First Deploy Owner: @growth-lead Version: 1.3 Steps: 4 Step 1: signup_submit (entry cohort) Step 2: email_verified within 24h of step 1 Step 3: first_project_created within 7d of step 2 Step 4: first_deploy within 1h of step 3 Max total: 14d from step 1 Cohort: users with signup_submit in 2026-09-01..2026-09-30, excluding test Results (n=12,400 entered): Step 1 (signup): 12,400 (100%) Step 2 (email verify): 9,920 (80.0%) drop: 20.0% Step 3 (project create):6,448 (52.0%) drop: 35.0% Step 4 (first deploy): 3,224 (26.0%) drop: 50.0% Overall conversion: 26.0% Biggest drop: step 3->4 (50% of project creators never deploy) SQL pinned at: metrics/funnel_signup_to_deploy.sql Unit test: fixtures/funnel.sql asserts 26.0% on Sep cohort
Common Problems
- ⚠Defining steps as page views instead of actions —'visited /checkout' counts users who loaded the page and bounced, inflating the step's count and understating the drop-off to the next step; actions are precise, page views are ambiguous.
- ⚠No time window between steps —a user who signs up and deploys 6 months later is counted in the funnel, diluting the conversion rate with users who were not really in a continuous journey.
- ⚠Counting users who skip steps as completions —a user who deploys without creating a project (via a template) is counted as completing the funnel, but they skipped step 3, and the funnel no longer measures the intended journey.
- ⚠Changing the funnel definition without versioning —the team adds a step, the conversion rate drops, and the dashboard shows a 'regression' that is actually a definition change; without versioning, historical comparisons are meaningless.
Best Practices
- ✓Define each step as a specific event with properties, not a page view —'clicked Purchase on /checkout' is a step; 'visited /checkout' is a page view that includes bounces, and the distinction is what makes the funnel measurable.
- ✓Set a time window per step and a max total funnel time —without bounds, the funnel includes users who wandered off and came back months later, diluting the conversion rate with non-journey behavior.
- ✓Version the funnel definition and pin the SQL —when a step is added or a window changed, the version increments, and historical funnels are recomputed with the old definition so comparisons are valid.
- ✓Add a unit test on a fixture dataset that asserts the funnel rates —this catches SQL regressions that would silently change the numbers on the dashboard, and it documents the expected behavior.