runtime
51 / 88

lesson 51 Advanced product analysis · advanced

Daily active users & engagement

Measure daily activity and user engagement.

the idea

Daily active users (DAU) counts distinct users with at least one qualifying event on each day. Derive the day from the time the event happened, and count distinct users and distinct logical events so retries do not inflate engagement.

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. Count daily active users. Run this. Each day shows how many distinct user_id values had at least one event when it happened (occurred_at), not when it was received.the pattern

    example.sql
    SELECT date(occurred_at) AS day, COUNT(DISTINCT user_id) AS active_users
    FROM events
    WHERE occurred_at >= '2025-06-01' AND occurred_at < '2025-06-08'
    GROUP BY day;
  2. See late-arriving events. Run this. Rows where received day differs from occurred day are why DAU should use occurred_at, not ingestion time.

    step-2.sql
    SELECT COUNT(*) AS late_day_shifts
    FROM events
    WHERE date(received_at) <> date(occurred_at);

common mistake

Grouping by received_at moves late events to the day they arrived instead of the day users were active.

challenge 1

For June 2025, return day (YYYY-MM-DD of occurred_at) and active_users: distinct users with any event that day.

what to return

Columns
dayactive_users 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.
Daily active users & engagement — Advanced product analysis · Runtime