user_pseudo_id is not a session id. It´s a unique ID "by app install". So as long as a user uses the same App-Instance ("Installation") without reinstalling it, the user_pseudo_id stays the same. It also don´t change on App update. But it will change if you uninstall and reinstall the app.
-- query all event where event_name is session_start or add_to_cart.
-- also fetch user_pseduo_id and event_timestamp columns
SELECT event_name, user_pseudo_id , event_timestamp
FROM `firebase-public-project.analytics_153293282.events_20200308`
WHERE (event_name = "session_start" OR event_name = "level_start")
ORDER BY 2,3;
next step for the funnel events
SELECT event_name, user_pseudo_id , event_timestamp,
-- add “next_event” -
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event
FROM `firebase-public-project.analytics_153293282.events_20200308`
WHERE (event_name = "session_start" OR event_name = "level_start")
ORDER BY 2,3;
-- define funnel_1 funnel_2. 1 if counted as funnel step, 0 otherwise
SELECT
IF (event_name = "session_start", 1, 0) AS funnel_1,
IF (event_name = "session_start" AND next_event = "level_start", 1, 0) AS funnel_2
FROM (
SELECT event_name, user_pseudo_id , event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event
FROM `firebase-public-project.analytics_153293282.events_20200308`
WHERE (event_name = "session_start" OR event_name = "level_start")
ORDER BY 2,3
)
--sum funnel_1, funnel_2
SELECT
SUM (IF (event_name = "session_start", 1, 0)) AS funnel_1_total,
SUM (IF (event_name = "session_start" AND next_event = "level_start", 1, 0)) AS funnel_2_total
FROM (
SELECT event_name, user_pseudo_id , event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event
FROM `firebase-public-project.analytics_153293282.events_20200308`
WHERE (event_name = "session_start" OR event_name = "level_start")
ORDER BY 2,3
)
-- sum -> count distinct
SELECT
count(distinct funnel_1) as funnel_1_total,
count(distinct funnel_2) as funnel_2_total from
(
SELECT
-- If true: 1, false: 0 -> If true: user_pseudo_id, false: NULL
IF (event_name = "session_start", user_pseudo_id, NULL) AS funnel_1,
IF (event_name = "session_start" AND next_event = "level_start", user_pseudo_id, NULL) AS funnel_2
FROM
(
SELECT event_name, user_pseudo_id , event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event
FROM `firebase-public-project.analytics_153293282.events_20200308`
WHERE (event_name = "session_start" OR event_name = "level_start")
ORDER BY 2,3
)
)
SELECT count(distinct funnel_1) as funnel_1_total, count(distinct funnel_2) as funnel_2_total from (
SELECT
IF (event_name = "session_start", user_pseudo_id, NULL) AS funnel_1,
-- 5 minutes between 2 events. time_stemp is in microseconds
IF (event_name = "session_start" AND next_event = "level_start"
AND next_timestamp - event_timestamp < 5 * 60 * 1000 * 1000, user_pseudo_id, NULL) AS funnel_2
FROM (
SELECT event_name, user_pseudo_id , event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event,
-- add next_timestemp
LEAD(event_timestamp, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_timestamp
FROM `firebase-public-project.analytics_153293282.events_20200308`
WHERE (event_name = "session_start" OR event_name = "level_start")
ORDER BY 2,3
)
)
SELECT count(distinct funnel_1) as funnel_1_total, count(distinct funnel_2) as funnel_2_total from (
SELECT
IF (event_name = "session_start", user_pseudo_id, NULL) AS funnel_1,
IF (event_name = "session_start" AND next_event = "level_start" AND next_timestamp - event_timestamp < 5 * 60 * 1000 * 1000, user_pseudo_id, NULL) AS funnel_2
FROM (
SELECT event_name, user_pseudo_id , event_timestamp,
LEAD(event_name, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_event,
LEAD(event_timestamp, 1) OVER (PARTITION BY user_pseudo_id ORDER BY event_timestamp) AS next_timestamp
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE ((event_name = "session_start" OR event_name = "level_start") AND
-- add interval
_TABLE_SUFFIX BETWEEN FORMAT_DATE("%Y%m%d", DATE_SUB(CURRENT_DATE(), INTERVAL 360 DAY))
AND FORMAT_DATE("%Y%m%d", CURRENT_DATE()))
ORDER BY 2,3
)
)
This might be better, say daylight time saving? I am not sure actually.
TIMESTAMP("2019-12-28 00:00:00", "Asia/Shanghai")
以周留存为例,调整时间即可变成日留存或者月留存
WITH analytics_data AS (
SELECT user_pseudo_id, event_timestamp, event_name,
UNIX_MICROS(TIMESTAMP("2019-12-01 00:00:00", "+8:00")) AS start_day,
3600*1000*1000*24*7 AS one_week_micros
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191130' AND '20191229'
)
SELECT week_0_cohort / week_0_cohort AS week_0_pct,
week_1_cohort / week_0_cohort AS week_1_pct,
week_2_cohort / week_0_cohort AS week_2_pct,
week_3_cohort / week_0_cohort AS week_3_pct
FROM (
WITH week_3_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(3*one_week_micros) AND start_day+(4*one_week_micros)
),
week_2_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(2*one_week_micros) AND start_day+(3*one_week_micros)
),
week_1_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(1*one_week_micros) AND start_day+(2*one_week_micros)
),
week_0_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_name = 'first_open'
AND event_timestamp BETWEEN start_day AND start_day+(1*one_week_micros)
)
SELECT
(SELECT count(*)
FROM week_0_users) AS week_0_cohort,
(SELECT count(*)
FROM week_1_users
JOIN week_0_users USING (user_pseudo_id)) AS week_1_cohort,
(SELECT count(*)
FROM week_2_users
JOIN week_0_users USING (user_pseudo_id)) AS week_2_cohort,
(SELECT count(*)
FROM week_3_users
JOIN week_0_users USING (user_pseudo_id)) AS week_3_cohort
)
Something Firebase cannot do
This is a bit tricky since we only limited the user for week_0 to deal with upgrades. Adjust according to your business, let's only get the idea :)
WITH analytics_data AS (
SELECT user_pseudo_id, event_timestamp, event_name,
app_info.version AS app_version, -- This is new!
UNIX_MICROS(TIMESTAMP("2019-12-01 00:00:00", "+8:00")) AS start_day,
3600*1000*1000*24*7 AS one_week_micros
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191130' AND '20191229'
)
SELECT week_0_cohort / week_0_cohort AS week_0_pct,
week_1_cohort / week_0_cohort AS week_1_pct,
week_2_cohort / week_0_cohort AS week_2_pct,
week_3_cohort / week_0_cohort AS week_3_pct
FROM (
WITH week_3_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(3*one_week_micros) AND start_day+(4*one_week_micros)
),
week_2_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(2*one_week_micros) AND start_day+(3*one_week_micros)
),
week_1_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(1*one_week_micros) AND start_day+(2*one_week_micros)
),
week_0_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_name = 'first_open'
AND app_version = "2.62" -- This bit is new, too!
AND event_timestamp BETWEEN start_day AND start_day+(1*one_week_micros)
)
SELECT
(SELECT count(*)
FROM week_0_users) AS week_0_cohort,
(SELECT count(*)
FROM week_1_users
JOIN week_0_users USING (user_pseudo_id)) AS week_1_cohort,
(SELECT count(*)
FROM week_2_users
JOIN week_0_users USING (user_pseudo_id)) AS week_2_cohort,
(SELECT count(*)
FROM week_3_users
JOIN week_0_users USING (user_pseudo_id)) AS week_3_cohort
)
WITH analytics_data AS (
SELECT user_pseudo_id, event_timestamp, event_name,
device.mobile_model_name, -- This parameter is new
UNIX_MICROS(TIMESTAMP("2019-12-01 00:00:00", "+8:00")) AS start_day,
3600*1000*1000*24*7 AS one_week_micros
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191130' AND '20191229'
AND device.mobile_model_name LIKE "iPad Pro%" -- This is also new
)
-- Rest of the query goes here
WITH analytics_data AS (
SELECT user_pseudo_id, event_timestamp, event_name, device.mobile_model_name,
UNIX_MICROS(TIMESTAMP("2019-12-01 00:00:00", "+8:00")) AS start_day,
3600*1000*1000*24 AS one_day_micros -- new time period
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191130' AND '20191229'
)
-- rest of the query goes here
WITH analytics_data AS (
SELECT user_pseudo_id, event_timestamp, event_name,
UNIX_MICROS(TIMESTAMP("2019-12-01 00:00:00", "+8:00")) AS start_day,
3600*1000*1000*24*7 AS one_week_micros
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191131' AND '20191229'
AND user_pseudo_id IN (
-- Anybody who received 20 initial extra steps
SELECT DISTINCT(user_pseudo_id) FROM
(SELECT user_pseudo_id,
(SELECT value.string_value FROM UNNEST(user_properties) WHERE key = "initial_extra_steps") AS initial_steps
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191131' AND '20191229'
)
WHERE initial_steps = "20"
)
)
Full version
WITH analytics_data AS (
SELECT user_pseudo_id, event_timestamp, event_name,
UNIX_MICROS(TIMESTAMP("2019-12-01 00:00:00", "+8:00")) AS start_day,
3600*1000*1000*24*7 AS one_week_micros
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191131' AND '20191229'
AND user_pseudo_id IN (
SELECT DISTINCT(user_pseudo_id) FROM
(SELECT user_pseudo_id,
(SELECT value.string_value FROM UNNEST(user_properties) WHERE key = "initial_extra_steps") AS initial_steps
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191131' AND '20191229'
)
WHERE initial_steps = "20"
)
)
SELECT week_0_cohort / week_0_cohort AS week_0_pct,
week_1_cohort / week_0_cohort AS week_1_pct,
week_2_cohort / week_0_cohort AS week_2_pct,
week_3_cohort / week_0_cohort AS week_3_pct
FROM (
WITH week_3_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(3*one_week_micros) AND start_day+(4*one_week_micros)
),
week_2_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(2*one_week_micros) AND start_day+(3*one_week_micros)
),
week_1_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_timestamp BETWEEN start_day+(1*one_week_micros) AND start_day+(2*one_week_micros)
),
week_0_users AS (
SELECT DISTINCT user_pseudo_id
FROM analytics_data
WHERE event_name = 'first_open'
AND event_timestamp BETWEEN start_day AND start_day+(1*one_week_micros)
)
SELECT
(SELECT count(*)
FROM week_0_users) AS week_0_cohort,
(SELECT count(*)
FROM week_1_users
JOIN week_0_users USING (user_pseudo_id)) AS week_1_cohort,
(SELECT count(*)
FROM week_2_users
JOIN week_0_users USING (user_pseudo_id)) AS week_2_cohort,
(SELECT count(*)
FROM week_3_users
JOIN week_0_users USING (user_pseudo_id)) AS week_3_cohort
)
WITH analytics_data AS (
SELECT user_pseudo_id, event_timestamp, event_name,
UNIX_MICROS(TIMESTAMP("2019-12-01 00:00:00", "+8:00")) AS start_day,
3600*1000*1000*24*7 AS one_week_micros
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191131' AND '20191229'
AND user_pseudo_id IN (
-- Anybody who's ever encountered a level_retry_quickplay event!
SELECT DISTINCT(user_pseudo_id) FROM
(SELECT user_pseudo_id, event_name
FROM `firebase-public-project.analytics_153293282.events_*`
WHERE _table_suffix BETWEEN '20191131' AND '20191229'
)
WHERE event_name = "level_retry_quickplay"
)
)
-- rest of the query goes here
And more ...
还可以有更多的,比如事件属性,结合各种属性和指标的分析。这里就不一一列举了。
此处有宝藏