@@ -6,57 +6,75 @@ export const SummaryBuilders: Record<
66 SimpleQueryConfig < typeof Analytics . events >
77> = {
88 summary_metrics : {
9- customSql : ( websiteId : string , startDate : string , endDate : string ) => {
9+ customSql : (
10+ websiteId : string ,
11+ startDate : string ,
12+ endDate : string ,
13+ _filters ?: Filter [ ] ,
14+ _granularity ?: TimeUnit ,
15+ _limit ?: number ,
16+ _offset ?: number ,
17+ timezone ?: string
18+ ) => {
19+ const tz = timezone || 'UTC' ;
1020 return {
1121 sql : `
12- WITH session_metrics AS (
22+ WITH base_events AS (
1323 SELECT
1424 session_id,
15- countIf(event_name = 'screen_view') as page_count
25+ anonymous_id,
26+ event_name,
27+ toTimeZone(time, {timezone:String}) as normalized_time
1628 FROM analytics.events
1729 WHERE
1830 client_id = {websiteId:String}
1931 AND time >= parseDateTimeBestEffort({startDate:String})
2032 AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
33+ AND session_id != ''
34+ ),
35+ session_metrics AS (
36+ SELECT
37+ session_id,
38+ countIf(event_name = 'screen_view') as page_count
39+ FROM base_events
2140 GROUP BY session_id
2241 ),
2342 session_durations AS (
2443 SELECT
2544 session_id,
26- dateDiff('second', MIN(time), MAX(time)) as duration
27- FROM analytics.events
28- WHERE
29- client_id = {websiteId:String}
30- AND time >= parseDateTimeBestEffort({startDate:String})
31- AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
45+ dateDiff('second', MIN(normalized_time), MAX(normalized_time)) as duration
46+ FROM base_events
3247 GROUP BY session_id
33- HAVING duration > 0
48+ HAVING duration >= 0
3449 ),
3550 unique_visitors AS (
3651 SELECT
3752 countDistinct(anonymous_id) as unique_visitors
38- FROM analytics.events
39- WHERE
40- client_id = {websiteId:String}
41- AND time >= parseDateTimeBestEffort({startDate:String})
42- AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
43- AND event_name = 'screen_view'
53+ FROM base_events
54+ WHERE event_name = 'screen_view'
4455 ),
4556 all_events AS (
4657 SELECT
47- count() as total_events
48- FROM analytics.events
49- WHERE
50- client_id = {websiteId:String}
51- AND time >= parseDateTimeBestEffort({startDate:String})
52- AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
58+ count() as total_events,
59+ countIf(event_name = 'screen_view') as total_screen_views
60+ FROM base_events
61+ ),
62+ bounce_sessions AS (
63+ SELECT
64+ countIf(page_count = 1) as bounced_sessions,
65+ count() as total_sessions
66+ FROM session_metrics
5367 )
5468 SELECT
5569 sum(page_count) as pageviews,
5670 (SELECT unique_visitors FROM unique_visitors) as unique_visitors,
57- count(session_metrics.session_id) as sessions,
58- ROUND((COALESCE(countIf(page_count = 1), 0) / COALESCE(COUNT(*), 0)) * 100, 2) as bounce_rate,
59- ROUND(AVG(sd.duration), 2) as avg_session_duration,
71+ (SELECT total_sessions FROM bounce_sessions) as sessions,
72+ ROUND(CASE
73+ WHEN (SELECT total_sessions FROM bounce_sessions) > 0
74+ THEN ((SELECT bounced_sessions FROM bounce_sessions) / (SELECT total_sessions FROM bounce_sessions)) * 100
75+ ELSE 0
76+ END, 2) as bounce_rate,
77+ ROUND(median(sd.duration), 2) as avg_session_duration,
6078 (SELECT total_events FROM all_events) as total_events
6179 FROM session_metrics
6280 LEFT JOIN session_durations as sd ON session_metrics.session_id = sd.session_id
@@ -65,6 +83,7 @@ export const SummaryBuilders: Record<
6583 websiteId,
6684 startDate,
6785 endDate,
86+ timezone : tz ,
6887 } ,
6988 } ;
7089 } ,
@@ -98,10 +117,10 @@ export const SummaryBuilders: Record<
98117 websiteId : string ,
99118 startDate : string ,
100119 endDate : string ,
101- filters ?: Filter [ ] ,
120+ _filters ?: Filter [ ] ,
102121 granularity ?: TimeUnit ,
103- limit ?: number ,
104- offset ?: number ,
122+ _limit ?: number ,
123+ _offset ?: number ,
105124 timezone ?: string
106125 ) => {
107126 const tz = timezone || 'UTC' ;
@@ -110,7 +129,20 @@ export const SummaryBuilders: Record<
110129 if ( isHourly ) {
111130 return {
112131 sql : `
113- WITH hour_range AS (
132+ WITH base_events AS (
133+ SELECT
134+ session_id,
135+ anonymous_id,
136+ event_name,
137+ toTimeZone(time, {timezone:String}) as normalized_time
138+ FROM analytics.events
139+ WHERE
140+ client_id = {websiteId:String}
141+ AND time >= parseDateTimeBestEffort({startDate:String})
142+ AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
143+ AND session_id != ''
144+ ),
145+ hour_range AS (
114146 SELECT arrayJoin(arrayMap(
115147 h -> toDateTime(concat({startDate:String}, ' 00:00:00')) + (h * 3600),
116148 range(toUInt32(dateDiff('hour', toDateTime(concat({startDate:String}, ' 00:00:00')), toDateTime(concat({endDate:String}, ' 23:59:59'))) + 1))
@@ -119,35 +151,27 @@ export const SummaryBuilders: Record<
119151 session_details AS (
120152 SELECT
121153 session_id,
122- toStartOfHour(toTimeZone( MIN(time), {timezone:String} )) as session_start_hour,
154+ toStartOfHour(MIN(normalized_time )) as session_start_hour,
123155 countIf(event_name = 'screen_view') as page_count,
124- dateDiff('second', MIN(time), MAX(time)) as duration
125- FROM analytics.events
126- WHERE
127- client_id = {websiteId:String}
128- AND time >= parseDateTimeBestEffort({startDate:String})
129- AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
156+ dateDiff('second', MIN(normalized_time), MAX(normalized_time)) as duration
157+ FROM base_events
130158 GROUP BY session_id
131159 ),
132160 hourly_session_metrics AS (
133161 SELECT
134162 session_start_hour as event_hour,
135163 count(session_id) as sessions,
136164 countIf(page_count = 1) as bounced_sessions,
137- avgIf (duration, duration > 0) as avg_session_duration
165+ medianIf (duration, duration >= 0) as median_session_duration
138166 FROM session_details
139167 GROUP BY session_start_hour
140168 ),
141169 hourly_event_metrics AS (
142170 SELECT
143- toStartOfHour(toTimeZone(time, {timezone:String}) ) as event_hour,
171+ toStartOfHour(normalized_time ) as event_hour,
144172 countIf(event_name = 'screen_view') as pageviews,
145173 count(distinct anonymous_id) as unique_visitors
146- FROM analytics.events
147- WHERE
148- client_id = {websiteId:String}
149- AND time >= parseDateTimeBestEffort({startDate:String})
150- AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
174+ FROM base_events
151175 GROUP BY event_hour
152176 )
153177 SELECT
@@ -160,7 +184,7 @@ export const SummaryBuilders: Record<
160184 THEN (COALESCE(hsm.bounced_sessions, 0) / hsm.sessions) * 100
161185 ELSE 0
162186 END, 2) as bounce_rate,
163- ROUND(COALESCE(hsm.avg_session_duration , 0), 2) as avg_session_duration,
187+ ROUND(COALESCE(hsm.median_session_duration , 0), 2) as avg_session_duration,
164188 ROUND(CASE
165189 WHEN COALESCE(hsm.sessions, 0) > 0
166190 THEN COALESCE(hem.pageviews, 0) / COALESCE(hsm.sessions, 0)
@@ -182,7 +206,20 @@ export const SummaryBuilders: Record<
182206
183207 return {
184208 sql : `
185- WITH date_range AS (
209+ WITH base_events AS (
210+ SELECT
211+ session_id,
212+ anonymous_id,
213+ event_name,
214+ toTimeZone(time, {timezone:String}) as normalized_time
215+ FROM analytics.events
216+ WHERE
217+ client_id = {websiteId:String}
218+ AND time >= parseDateTimeBestEffort({startDate:String})
219+ AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
220+ AND session_id != ''
221+ ),
222+ date_range AS (
186223 SELECT arrayJoin(arrayMap(
187224 d -> toDate({startDate:String}) + d,
188225 range(toUInt32(dateDiff('day', toDate({startDate:String}), toDate({endDate:String})) + 1))
@@ -191,35 +228,27 @@ export const SummaryBuilders: Record<
191228 session_details AS (
192229 SELECT
193230 session_id,
194- toDate(toTimeZone( MIN(time), {timezone:String} )) as session_start_date,
231+ toDate(MIN(normalized_time )) as session_start_date,
195232 countIf(event_name = 'screen_view') as page_count,
196- dateDiff('second', MIN(time), MAX(time)) as duration
197- FROM analytics.events
198- WHERE
199- client_id = {websiteId:String}
200- AND time >= parseDateTimeBestEffort({startDate:String})
201- AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
233+ dateDiff('second', MIN(normalized_time), MAX(normalized_time)) as duration
234+ FROM base_events
202235 GROUP BY session_id
203236 ),
204237 daily_session_metrics AS (
205238 SELECT
206239 session_start_date,
207240 count(session_id) as sessions,
208241 countIf(page_count = 1) as bounced_sessions,
209- avgIf (duration, duration > 0) as avg_session_duration
242+ medianIf (duration, duration >= 0) as median_session_duration
210243 FROM session_details
211244 GROUP BY session_start_date
212245 ),
213246 daily_event_metrics AS (
214247 SELECT
215- toDate(toTimeZone(time, {timezone:String}) ) as event_date,
248+ toDate(normalized_time ) as event_date,
216249 countIf(event_name = 'screen_view') as pageviews,
217250 count(distinct anonymous_id) as unique_visitors
218- FROM analytics.events
219- WHERE
220- client_id = {websiteId:String}
221- AND time >= parseDateTimeBestEffort({startDate:String})
222- AND time <= parseDateTimeBestEffort(concat({endDate:String}, ' 23:59:59'))
251+ FROM base_events
223252 GROUP BY event_date
224253 )
225254 SELECT
@@ -232,7 +261,7 @@ export const SummaryBuilders: Record<
232261 THEN (COALESCE(dsm.bounced_sessions, 0) / dsm.sessions) * 100
233262 ELSE 0
234263 END, 2) as bounce_rate,
235- ROUND(COALESCE(dsm.avg_session_duration , 0), 2) as avg_session_duration,
264+ ROUND(COALESCE(dsm.median_session_duration , 0), 2) as avg_session_duration,
236265 ROUND(CASE
237266 WHEN COALESCE(dsm.sessions, 0) > 0
238267 THEN COALESCE(dem.pageviews, 0) / COALESCE(dsm.sessions, 0)
@@ -273,6 +302,7 @@ export const SummaryBuilders: Record<
273302 FROM analytics.events
274303 WHERE event_name = 'screen_view'
275304 AND client_id = {websiteId:String}
305+ AND session_id != ''
276306 AND ${ timeCondition }
277307 ` ,
278308 params : {
0 commit comments