Event contract
Fields the query expects
| Field | Type | Why it exists |
|---|---|---|
| timestamp_utc | Timestamp | When the product event occurred. |
| user_id | Utf8 | Stable user identifier. |
| event_name | Utf8 | Stable snake_case milestone name. |
| source | Utf8 | Acquisition or campaign source. |
Copy the query
WITH user_funnel AS (
SELECT
user_id,
MIN(CASE WHEN event_name = 'signup_completed'
THEN timestamp_utc END) AS signed_up_at,
MIN(CASE WHEN event_name = 'onboarding_completed'
THEN timestamp_utc END) AS onboarded_at,
MIN(CASE WHEN event_name = 'integration_connected'
THEN timestamp_utc END) AS integrated_at,
MIN(CASE WHEN event_name = 'first_value_completed'
THEN timestamp_utc END) AS activated_at
FROM product_events
WHERE timestamp_utc >= now() - INTERVAL '30 days'
GROUP BY user_id
),
stage_counts AS (
SELECT 1 AS step_order, 'Signed up' AS step, COUNT(*) AS users
FROM user_funnel
WHERE signed_up_at IS NOT NULL
UNION ALL
SELECT 2, 'Onboarded', COUNT(*)
FROM user_funnel
WHERE onboarded_at >= signed_up_at
UNION ALL
SELECT 3, 'Integrated', COUNT(*)
FROM user_funnel
WHERE integrated_at >= onboarded_at
UNION ALL
SELECT 4, 'Activated', COUNT(*)
FROM user_funnel
WHERE activated_at >= integrated_at
)
SELECT
step_order,
step,
users,
100.0 * users
/ NULLIF(MAX(CASE WHEN step_order = 1 THEN users END) OVER (), 0)
AS conversion_from_signup_pct,
100.0 * users
/ NULLIF(LAG(users) OVER (ORDER BY step_order), 0)
AS conversion_from_previous_pct
FROM stage_counts
ORDER BY step_order;This read-only query is planned and executed against an empty typed table with Apache DataFusion 45.2.0. The deterministic sample output is synthetic and reviewed separately; validate field types, thresholds, and business definitions against your own data. Read the testing methodology.
Query result
Signup-to-activation funnel
The largest absolute loss occurs before onboarding completion, while integration remains the strongest later bottleneck.
| step_order | step | users | conversion_from_signup_pct | conversion_from_previous_pct |
|---|---|---|---|---|
| 1 | Signed up | 8 | 100 | — |
| 2 | Onboarded | 6 | 75 | 75 |
| 3 | Integrated | 4 | 50 | 66.67 |
| 4 | Activated | 3 | 37.5 | 75 |
Synthetic example output. Run the query against your own event schema and thresholds before using it for operational decisions.
Reproduce the example
Download the public fixture
The JSON bundle includes the typed event contract, reproducible input rows, exact SQL, expected output, review notes, and engine version. The CSV contains the displayed result.
How the SQL works
- 1The user_funnel CTE collapses repeated events into the first timestamp for each milestone.
- 2Timestamp comparisons enforce the intended order, so an out-of-sequence event cannot inflate a later step.
- 3The query reports both conversion from signup and conversion from the previous step, making total performance and the largest transition loss visible together.
- 4The event names should represent completed milestones, not page views or button clicks that do not prove the user achieved the step.
Edge cases to decide
- Use a cohort window based on signup time and allow enough time for recent signups to activate.
- Events that arrive late can temporarily move users backward in a recently calculated funnel.
- Segment by acquisition source only after the total funnel has enough volume.
Recommended dashboard
- Funnel bars: users by step
- Line chart: activation rate by signup week
- Table: conversion by source, plan, or persona
Alert guidance
Use a low-urgency alert when activation for a mature signup cohort falls materially below its recent baseline.
Read alert setupPut the recipe to work
Related instrumentation and guides
Define the source data
Event schemas for this analysis
user_signed_up
A durable account-entry event with acquisition and plan context. Keep identity pseudonymous and capture marketing attribution only after privacy review.
Review schemaproduct_milestone_completed
A generic milestone envelope for stable product outcomes such as connecting a source, running a first query, or publishing a dashboard.
Review schemaContinue the analysis
Calculate Weekly Cohort Retention
Group users by first activity week and measure the percentage returning in later weeks.
Open recipeFind Features Used Before Upgrade
Join feature events to upgrade events and rank behaviors that occur before paid conversion.
Open recipeCalculate DAU, WAU, and Product Stickiness
Measure daily and weekly active users together and calculate DAU-to-WAU stickiness from a consistent activity definition.
Open recipeRun it on real events
Create a table, adapt the fields, and save the result
Start free, send structured events, and use the query result as a chart, shared dashboard widget, or alert input.