diff --git a/src/queries/sql/events/getEventExpandedMetrics.ts b/src/queries/sql/events/getEventExpandedMetrics.ts index 86bda8509..0e4840a11 100644 --- a/src/queries/sql/events/getEventExpandedMetrics.ts +++ b/src/queries/sql/events/getEventExpandedMetrics.ts @@ -1,5 +1,5 @@ import clickhouse from '@/lib/clickhouse'; -import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { BOUNCE_THRESHOLD, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -54,7 +54,7 @@ async function relationalQuery( sum(t.c) as "pageviews", count(distinct t.session_id) as "visitors", count(distinct t.visit_id) as "visits", - sum(case when t.c = 1 then 1 else 0 end) as "bounces", + sum(case when t.c = 1 and (t.events_count - t.c) < ${BOUNCE_THRESHOLD} then 1 else 0 end) as "bounces", sum(${getTimestampDiffSQL('t.min_time', 't.max_time')}) as "totaltime" from ( select @@ -63,10 +63,19 @@ async function relationalQuery( website_event.visit_id, count(*) as "c", min(website_event.created_at) as "min_time", - max(website_event.created_at) as "max_time" + max(website_event.created_at) as "max_time", + max(( + select count(*) + from website_event we2 + where we2.website_id = website_event.website_id + and we2.session_id = website_event.session_id + and we2.visit_id = website_event.visit_id + and we2.created_at between {{startDate}} and {{endDate}} + and we2.event_type = ${EVENT_TYPE.customEvent} + )) as "events_count" from website_event ${cohortQuery} - ${joinSessionQuery} + ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} ${filterQuery} @@ -104,7 +113,7 @@ async function clickhouseQuery( sum(t.c) as "pageviews", uniq(t.session_id) as "visitors", uniq(t.visit_id) as "visits", - sum(if(t.c = 1, 1, 0)) as "bounces", + sumIf(1, t.c = 1 and (toInt64(ifNull(e.events_count, 0)) - toInt64(t.c)) < ${BOUNCE_THRESHOLD}) as "bounces", sum(max_time-min_time) as "totaltime" from ( select @@ -122,7 +131,15 @@ async function clickhouseQuery( ${filterQuery} group by name, session_id, visit_id ) as t - group by name + left join ( + select session_id, visit_id, toUInt32(count()) as events_count + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = ${EVENT_TYPE.customEvent} + group by session_id, visit_id + ) as e using (session_id, visit_id) + group by name order by visitors desc, visits desc limit ${limit} offset ${offset} diff --git a/src/queries/sql/getChannelExpandedMetrics.ts b/src/queries/sql/getChannelExpandedMetrics.ts index 6f225f9eb..6d9eee301 100644 --- a/src/queries/sql/getChannelExpandedMetrics.ts +++ b/src/queries/sql/getChannelExpandedMetrics.ts @@ -1,6 +1,8 @@ import clickhouse from '@/lib/clickhouse'; import { + BOUNCE_THRESHOLD, EMAIL_DOMAINS, + EVENT_TYPE, LLM_DOMAINS, PAID_AD_PARAMS, SEARCH_DOMAINS, @@ -120,20 +122,34 @@ async function relationalQuery( min(created_at) as min_time, max(created_at) as max_time from prefix + group by session_id, visit_id), + + visit_events as ( + select + session_id, + visit_id, + count(*) as events_count + from website_event + where website_id = {{websiteId::uuid}} + and created_at between {{startDate}} and {{endDate}} + and event_type = ${EVENT_TYPE.customEvent} group by session_id, visit_id) - + select visit_channels.name, sum(visit_stats.c) as "pageviews", count(distinct visit_stats.session_id) as "visitors", count(distinct visit_stats.visit_id) as "visits", - sum(case when visit_stats.c = 1 then 1 else 0 end) as "bounces", + sum(case when visit_stats.c = 1 and coalesce(visit_events.events_count, 0) < ${BOUNCE_THRESHOLD} then 1 else 0 end) as "bounces", sum(${getTimestampDiffSQL('visit_stats.min_time', 'visit_stats.max_time')}) as "totaltime" from visit_stats join visit_channels on visit_channels.session_id = visit_stats.session_id and visit_channels.visit_id = visit_stats.visit_id - group by visit_channels.name + left join visit_events + on visit_events.session_id = visit_stats.session_id + and visit_events.visit_id = visit_stats.visit_id + group by visit_channels.name order by visitors desc, visits desc `, queryParams, @@ -158,7 +174,7 @@ async function clickhouseQuery( sum(t.c) as "pageviews", uniq(t.session_id) as "visitors", uniq(t.visit_id) as "visits", - sum(if(t.c = 1, 1, 0)) as "bounces", + sumIf(1, t.c = 1 and ifNull(e.events_count, 0) < ${BOUNCE_THRESHOLD}) as "bounces", sum(max_time-min_time) as "totaltime" from ( select @@ -213,7 +229,15 @@ async function clickhouseQuery( ) group by session_id, visit_id ) as t - group by name + left join ( + select session_id, visit_id, toUInt32(count()) as events_count + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = ${EVENT_TYPE.customEvent} + group by session_id, visit_id + ) as e using (session_id, visit_id) + group by name order by visitors desc, visits desc; `, queryParams, diff --git a/src/queries/sql/getWebsiteStats.ts b/src/queries/sql/getWebsiteStats.ts index 527b9c152..0f74bc373 100644 --- a/src/queries/sql/getWebsiteStats.ts +++ b/src/queries/sql/getWebsiteStats.ts @@ -1,5 +1,5 @@ import clickhouse from '@/lib/clickhouse'; -import { EVENT_COLUMNS } from '@/lib/constants'; +import { BOUNCE_THRESHOLD, EVENT_COLUMNS, EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -35,7 +35,9 @@ async function relationalQuery( }); const { excludeBounce } = filters; - const bounceQuery = excludeBounce ? '0' : 'coalesce(sum(case when t.c = 1 then 1 else 0 end), 0)'; + const bounceQuery = excludeBounce + ? '0' + : `coalesce(sum(case when t.c = 1 and t.events_count < ${BOUNCE_THRESHOLD} then 1 else 0 end), 0)`; return rawQuery( ` @@ -51,11 +53,20 @@ async function relationalQuery( website_event.visit_id, count(*) as "c", min(website_event.created_at) as "min_time", - max(website_event.created_at) as "max_time" + max(website_event.created_at) as "max_time", + max(( + select count(*) + from website_event we2 + where we2.website_id = website_event.website_id + and we2.session_id = website_event.session_id + and we2.visit_id = website_event.visit_id + and we2.created_at between {{startDate}} and {{endDate}} + and we2.event_type = ${EVENT_TYPE.customEvent} + )) as "events_count" from website_event ${cohortQuery} ${excludeBounceQuery} - ${joinSessionQuery} + ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} and website_event.event_type NOT IN (2, 5) @@ -81,7 +92,9 @@ async function clickhouseQuery( let sql = ''; const { excludeBounce } = filters; - const bounceQuery = excludeBounce ? '0' : 'sumIf(1, t.c = 1)'; + const bounceQuery = excludeBounce + ? '0' + : `sumIf(1, t.c = 1 and ifNull(e.events_count, 0) < ${BOUNCE_THRESHOLD})`; if (EVENT_COLUMNS.some(item => Object.keys(filters).includes(item))) { sql = ` @@ -106,7 +119,15 @@ async function clickhouseQuery( and event_type NOT IN (2, 5) ${filterQuery} group by session_id, visit_id - ) as t; + ) as t + left join ( + select session_id, visit_id, toUInt32(count()) as events_count + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = ${EVENT_TYPE.customEvent} + group by session_id, visit_id + ) as e using (session_id, visit_id); `; } else { sql = ` @@ -130,7 +151,14 @@ async function clickhouseQuery( and event_type NOT IN (2, 5) ${filterQuery} group by session_id, visit_id - ) as t; + ) as t + left join ( + select session_id, visit_id, toUInt32(sumIf(views, event_type = ${EVENT_TYPE.customEvent})) as events_count + from website_event_stats_hourly + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + group by session_id, visit_id + ) as e using (session_id, visit_id); `; } diff --git a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts index e25a0242c..153086584 100644 --- a/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts +++ b/src/queries/sql/pageviews/getPageviewExpandedMetrics.ts @@ -1,5 +1,5 @@ import clickhouse from '@/lib/clickhouse'; -import { FILTER_COLUMNS, GROUPED_DOMAINS, SESSION_COLUMNS } from '@/lib/constants'; +import { BOUNCE_THRESHOLD, EVENT_TYPE, FILTER_COLUMNS, GROUPED_DOMAINS, SESSION_COLUMNS } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -96,7 +96,7 @@ async function relationalQuery( sum(t.c) as "pageviews", count(distinct t.session_id) as "visitors", count(distinct t.visit_id) as "visits", - sum(case when t.c = 1 then 1 else 0 end) as "bounces", + sum(case when t.c = 1 and t.events_count < ${BOUNCE_THRESHOLD} then 1 else 0 end) as "bounces", sum(${getTimestampDiffSQL('t.min_time', 't.max_time')}) as "totaltime" from ( select @@ -105,12 +105,21 @@ async function relationalQuery( website_event.visit_id, count(*) as "c", min(website_event.created_at) as "min_time", - max(website_event.created_at) as "max_time" + max(website_event.created_at) as "max_time", + max(( + select count(*) + from website_event we2 + where we2.website_id = website_event.website_id + and we2.session_id = website_event.session_id + and we2.visit_id = website_event.visit_id + and we2.created_at between {{startDate}} and {{endDate}} + and we2.event_type = ${EVENT_TYPE.customEvent} + )) as "events_count" from website_event ${cohortQuery} ${excludeBounceQuery} - ${joinSessionQuery} - ${entryExitQuery} + ${joinSessionQuery} + ${entryExitQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} and website_event.event_type NOT IN (2, 5) @@ -188,7 +197,7 @@ async function clickhouseQuery( sum(t.c) as "pageviews", uniq(t.session_id) as "visitors", uniq(t.visit_id) as "visits", - sum(if(t.c = 1, 1, 0)) as "bounces", + sumIf(1, t.c = 1 and ifNull(e.events_count, 0) < ${BOUNCE_THRESHOLD}) as "bounces", sum(max_time-min_time) as "totaltime" from ( select @@ -211,6 +220,14 @@ async function clickhouseQuery( ${filterQuery} group by name, session_id, visit_id ) as t + left join ( + select session_id, visit_id, toUInt32(count()) as events_count + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = ${EVENT_TYPE.customEvent} + group by session_id, visit_id + ) as e using (session_id, visit_id) group by name order by visitors desc, visits desc limit ${limit} diff --git a/src/queries/sql/reports/getBreakdown.ts b/src/queries/sql/reports/getBreakdown.ts index 3d1e92a44..13dcccf17 100644 --- a/src/queries/sql/reports/getBreakdown.ts +++ b/src/queries/sql/reports/getBreakdown.ts @@ -1,5 +1,5 @@ import clickhouse from '@/lib/clickhouse'; -import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { BOUNCE_THRESHOLD, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -50,7 +50,7 @@ async function relationalQuery( sum(t.c) as "views", count(distinct t.session_id) as "visitors", count(distinct t.visit_id) as "visits", - sum(case when t.c = 1 then 1 else 0 end) as "bounces", + sum(case when t.c = 1 and t.events_count < ${BOUNCE_THRESHOLD} then 1 else 0 end) as "bounces", sum(${getTimestampDiffSQL('t.min_time', 't.max_time')}) as "totaltime", ${parseFieldsByName(fields)} from ( @@ -60,14 +60,23 @@ async function relationalQuery( website_event.visit_id, count(*) as "c", min(website_event.created_at) as "min_time", - max(website_event.created_at) as "max_time" + max(website_event.created_at) as "max_time", + max(( + select count(*) + from website_event we2 + where we2.website_id = website_event.website_id + and we2.session_id = website_event.session_id + and we2.visit_id = website_event.visit_id + and we2.created_at between {{startDate}} and {{endDate}} + and we2.event_type = ${EVENT_TYPE.customEvent} + )) as "events_count" from website_event - ${cohortQuery} + ${cohortQuery} ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} ${filterQuery} - group by ${parseFieldsByName(fields)}, + group by ${parseFieldsByName(fields)}, website_event.session_id, website_event.visit_id ) as t group by ${parseFieldsByName(fields)} @@ -99,7 +108,7 @@ async function clickhouseQuery( sum(t.c) as "views", count(distinct t.session_id) as "visitors", count(distinct t.visit_id) as "visits", - sum(if(t.c = 1, 1, 0)) as "bounces", + sumIf(1, t.c = 1 and ifNull(e.events_count, 0) < ${BOUNCE_THRESHOLD}) as "bounces", sum(max_time-min_time) as "totaltime", ${parseFieldsByName(fields)} from ( @@ -115,9 +124,17 @@ async function clickhouseQuery( where website_id = {websiteId:UUID} and created_at between {startDate:DateTime64} and {endDate:DateTime64} ${filterQuery} - group by ${parseFieldsByName(fields)}, + group by ${parseFieldsByName(fields)}, session_id, visit_id ) as t + left join ( + select session_id, visit_id, toUInt32(count()) as events_count + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = ${EVENT_TYPE.customEvent} + group by session_id, visit_id + ) as e using (session_id, visit_id) group by ${parseFieldsByName(fields)} order by 2 desc, 1 desc limit 500 diff --git a/src/queries/sql/sessions/getSessionExpandedMetrics.ts b/src/queries/sql/sessions/getSessionExpandedMetrics.ts index f81acc769..c917a40f9 100644 --- a/src/queries/sql/sessions/getSessionExpandedMetrics.ts +++ b/src/queries/sql/sessions/getSessionExpandedMetrics.ts @@ -1,5 +1,5 @@ import clickhouse from '@/lib/clickhouse'; -import { FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; +import { BOUNCE_THRESHOLD, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -62,7 +62,7 @@ async function relationalQuery( sum(t.c) as "pageviews", count(distinct t.session_id) as "visitors", count(distinct t.visit_id) as "visits", - sum(case when t.c = 1 then 1 else 0 end) as "bounces", + sum(case when t.c = 1 and t.events_count < ${BOUNCE_THRESHOLD} then 1 else 0 end) as "bounces", sum(${getTimestampDiffSQL('t.min_time', 't.max_time')}) as "totaltime" from ( select @@ -72,11 +72,20 @@ async function relationalQuery( website_event.visit_id, count(*) as "c", min(website_event.created_at) as "min_time", - max(website_event.created_at) as "max_time" + max(website_event.created_at) as "max_time", + max(( + select count(*) + from website_event we2 + where we2.website_id = website_event.website_id + and we2.session_id = website_event.session_id + and we2.visit_id = website_event.visit_id + and we2.created_at between {{startDate}} and {{endDate}} + and we2.event_type = ${EVENT_TYPE.customEvent} + )) as "events_count" from website_event ${cohortQuery} ${excludeBounceQuery} - ${joinSessionQuery} + ${joinSessionQuery} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} and website_event.event_type NOT IN (2, 5) @@ -122,7 +131,7 @@ async function clickhouseQuery( sum(t.c) as "pageviews", uniq(t.session_id) as "visitors", uniq(t.visit_id) as "visits", - sum(if(t.c = 1, 1, 0)) as "bounces", + sumIf(1, t.c = 1 and ifNull(e.events_count, 0) < ${BOUNCE_THRESHOLD}) as "bounces", sum(max_time-min_time) as "totaltime" from ( select @@ -144,7 +153,15 @@ async function clickhouseQuery( group by name, session_id, visit_id ${includeCountry ? ', country' : ''} ) as t - group by name + left join ( + select session_id, visit_id, toUInt32(count()) as events_count + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + and event_type = ${EVENT_TYPE.customEvent} + group by session_id, visit_id + ) as e using (session_id, visit_id) + group by name ${includeCountry ? ', country' : ''} order by visitors desc, visits desc limit ${limit}