runtime
52 / 88

lesson 52 Advanced product analysis · advanced

Ordered conversion funnels

Count users who complete events in the required order.

the idea

An ordered funnel counts users who complete steps in sequence: each step must happen at or after the previous step. Find each user’s earliest qualifying time for step 1, then the earliest step-2 time at or after it, and so on. Users who skip a step stop there.

Dataset: Product / SaaS Analytics

The tables the challenges use, with their first 6 rows. Under each column name: the kind of value it holds, and which table it links to.

events8 columns · 135,428 rows
delivery_idnumber · unique idevent_idtextuser_idnumber · links to usersaccount_idnumber · links to accountssession_idnumber · links to sessionsevent_nametextoccurred_atdate & timereceived_atdate & time
1evt_0000001111user_signed_up2024-01-14 18:52:142024-01-14 18:52:33
2evt_0000002111onboarding_started2024-01-14 18:52:512024-01-14 18:53:06
3evt_00000846232user_signed_up2024-01-15 13:21:522024-01-15 13:22:00
4evt_00000856232onboarding_started2024-01-15 13:22:052024-01-15 13:22:16
5evt_00000866232onboarding_completed2024-01-15 13:23:522024-01-15 13:24:12
6evt_0000019119search_performed2024-01-17 20:56:552024-01-17 20:56:59
delivery_idnumber · unique id
1
event_idtext
evt_0000001
user_idnumber · links to users
1
account_idnumber · links to accounts
1
session_idnumber · links to sessions
1
event_nametext
user_signed_up
occurred_atdate & time
2024-01-14 18:52:14
received_atdate & time
2024-01-14 18:52:33
delivery_idnumber · unique id
2
event_idtext
evt_0000002
user_idnumber · links to users
1
account_idnumber · links to accounts
1
session_idnumber · links to sessions
1
event_nametext
onboarding_started
occurred_atdate & time
2024-01-14 18:52:51
received_atdate & time
2024-01-14 18:53:06
delivery_idnumber · unique id
3
event_idtext
evt_0000084
user_idnumber · links to users
6
account_idnumber · links to accounts
2
session_idnumber · links to sessions
32
event_nametext
user_signed_up
occurred_atdate & time
2024-01-15 13:21:52
received_atdate & time
2024-01-15 13:22:00
delivery_idnumber · unique id
4
event_idtext
evt_0000085
user_idnumber · links to users
6
account_idnumber · links to accounts
2
session_idnumber · links to sessions
32
event_nametext
onboarding_started
occurred_atdate & time
2024-01-15 13:22:05
received_atdate & time
2024-01-15 13:22:16
delivery_idnumber · unique id
5
event_idtext
evt_0000086
user_idnumber · links to users
6
account_idnumber · links to accounts
2
session_idnumber · links to sessions
32
event_nametext
onboarding_completed
occurred_atdate & time
2024-01-15 13:23:52
received_atdate & time
2024-01-15 13:24:12
delivery_idnumber · unique id
6
event_idtext
evt_0000019
user_idnumber · links to users
1
account_idnumber · links to accounts
1
session_idnumber · links to sessions
9
event_nametext
search_performed
occurred_atdate & time
2024-01-17 20:56:55
received_atdate & time
2024-01-17 20:56:59

first 6 of 135,428 rows · your queries use all of them

worked example

Run these steps in order to see the idea before you write your own query. The step marked “the pattern” is what the challenges ask for. Running the example does not count toward progress.

  1. Compare naive step counts. Run this. These totals count anyone who ever hit each step—they ignore whether onboarding came before the first project.the pattern

    example.sql
    SELECT event_name, COUNT(DISTINCT user_id) AS users
    FROM events
    WHERE event_name IN ('user_signed_up', 'onboarding_completed', 'project_created')
    GROUP BY event_name;
  2. Walk one user’s timeline. Run this. User 100’s funnel events in time order—use this picture when you enforce signup → onboarding → project.

    step-2.sql
    SELECT user_id, event_name, occurred_at
    FROM events
    WHERE user_id = 100
      AND event_name IN ('user_signed_up', 'onboarding_completed', 'project_created')
    ORDER BY occurred_at;
  3. Pivot first time per step. Run this. CASE inside MIN gives each user’s earliest timestamp per event name; you still must require each step to come after the previous one.

    step-3.sql
    SELECT
      user_id,
      MIN(CASE
        WHEN event_name = 'user_signed_up' THEN occurred_at
      END) AS signed_up,
      MIN(CASE
        WHEN event_name = 'onboarding_completed' THEN occurred_at
      END) AS first_onboarding,
      MIN(CASE
        WHEN event_name = 'project_created' THEN occurred_at
      END) AS first_project
    FROM events
    WHERE user_id BETWEEN 100 AND 110
    GROUP BY user_id;

common mistake

Counting users who ever did each event ignores order: a project created before onboarding would wrongly count as a completed funnel.

challenge 1

For users who signed up (user_signed_up) in the first quarter of 2025, return one row with signed_up, onboarded and created_project: users reaching each step in order, where onboarding_completed happens at or after signup and project_created at or after the user’s onboarding completion.

what to return

Columns
signed_uponboardedcreated_project in this order
Rows
any order
challenge-1.sql
 
To master this lesson, solve both challenges without hints and pass the concept check. 3 of 3 to go.
Ordered conversion funnels — Advanced product analysis · Runtime