mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 12:47:13 +01:00
This commit is contained in:
parent
4a3190b2da
commit
ee698b636a
21 changed files with 189 additions and 69 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import { Column, Grid, Row } from '@umami/react-zen';
|
||||
import { BounceFilter } from '@/components/input/BounceFilter';
|
||||
import { ExportButton } from '@/components/input/ExportButton';
|
||||
import { FilterBar } from '@/components/input/FilterBar';
|
||||
import { MonthFilter } from '@/components/input/MonthFilter';
|
||||
|
|
@ -8,6 +9,7 @@ import { WebsiteFilterButton } from '@/components/input/WebsiteFilterButton';
|
|||
export function WebsiteControls({
|
||||
websiteId,
|
||||
allowFilter = true,
|
||||
allowBounceFilter = false,
|
||||
allowDateFilter = true,
|
||||
allowMonthFilter,
|
||||
allowDownload = false,
|
||||
|
|
@ -15,6 +17,7 @@ export function WebsiteControls({
|
|||
}: {
|
||||
websiteId: string;
|
||||
allowFilter?: boolean;
|
||||
allowBounceFilter?: boolean;
|
||||
allowDateFilter?: boolean;
|
||||
allowMonthFilter?: boolean;
|
||||
allowDownload?: boolean;
|
||||
|
|
@ -23,8 +26,9 @@ export function WebsiteControls({
|
|||
return (
|
||||
<Column gap>
|
||||
<Grid columns={{ xs: '1fr', md: 'auto 1fr' }} gap>
|
||||
<Row alignItems="center" justifyContent="flex-start">
|
||||
{allowFilter ? <WebsiteFilterButton websiteId={websiteId} /> : <div />}
|
||||
<Row alignItems="center" justifyContent="flex-start" gap="4">
|
||||
{allowFilter && <WebsiteFilterButton websiteId={websiteId} />}
|
||||
{allowBounceFilter && <BounceFilter />}
|
||||
</Row>
|
||||
<Row alignItems="center" justifyContent={{ xs: 'flex-start', md: 'flex-end' }}>
|
||||
{allowDateFilter && (
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export function WebsiteNav({
|
|||
compare: undefined,
|
||||
view: undefined,
|
||||
unit: undefined,
|
||||
excludeBounce: undefined,
|
||||
});
|
||||
|
||||
const items = [
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { WebsitePanels } from './WebsitePanels';
|
|||
export function WebsitePage({ websiteId }: { websiteId: string }) {
|
||||
return (
|
||||
<Column gap>
|
||||
<WebsiteControls websiteId={websiteId} />
|
||||
<WebsiteControls websiteId={websiteId} allowBounceFilter={true} />
|
||||
<WebsiteMetricsBar websiteId={websiteId} showChange={true} />
|
||||
<Panel minHeight="520px">
|
||||
<Row justifyContent="end">
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export function useFilterParameters() {
|
|||
search,
|
||||
segment,
|
||||
cohort,
|
||||
excludeBounce,
|
||||
},
|
||||
} = useNavigation();
|
||||
|
||||
|
|
@ -47,6 +48,7 @@ export function useFilterParameters() {
|
|||
search,
|
||||
segment,
|
||||
cohort,
|
||||
excludeBounce,
|
||||
};
|
||||
}, [
|
||||
path,
|
||||
|
|
@ -69,5 +71,6 @@ export function useFilterParameters() {
|
|||
search,
|
||||
segment,
|
||||
cohort,
|
||||
excludeBounce,
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
26
src/components/input/BounceFilter.tsx
Normal file
26
src/components/input/BounceFilter.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
'use client';
|
||||
import { Checkbox, Row } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks/useMessages';
|
||||
import { useNavigation } from '@/components/hooks/useNavigation';
|
||||
|
||||
export function BounceFilter() {
|
||||
const { router, query, updateParams } = useNavigation();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const isSelected = query.excludeBounce === 'true';
|
||||
|
||||
const handleChange = (value: boolean) => {
|
||||
if (value) {
|
||||
router.push(updateParams({ excludeBounce: 'true' }));
|
||||
} else {
|
||||
router.push(updateParams({ excludeBounce: undefined }));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Row alignItems="center" gap>
|
||||
<Checkbox isSelected={isSelected} onChange={handleChange}>
|
||||
{formatMessage(labels.excludeBounce)}
|
||||
</Checkbox>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
@ -111,6 +111,7 @@ export const labels = defineMessages({
|
|||
event: { id: 'label.event', defaultMessage: 'Event' },
|
||||
events: { id: 'label.events', defaultMessage: 'Events' },
|
||||
eventName: { id: 'label.event-name', defaultMessage: 'Event name' },
|
||||
excludeBounce: { id: 'label.exclude-bounce', defaultMessage: 'Exclude bounces' },
|
||||
query: { id: 'label.query', defaultMessage: 'Query' },
|
||||
queryParameters: { id: 'label.query-parameters', defaultMessage: 'Query parameters' },
|
||||
back: { id: 'label.back', defaultMessage: 'Back' },
|
||||
|
|
|
|||
|
|
@ -131,6 +131,25 @@ function getCohortQuery(filters: Record<string, any>) {
|
|||
`;
|
||||
}
|
||||
|
||||
function getExcludeBounceQuery(filters: Record<string, any>) {
|
||||
if (!filters.excludeBounce === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return `join
|
||||
(select distinct session_id, visit_id
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type = 1
|
||||
group by session_id, visit_id
|
||||
having count(*) > 1
|
||||
) excludeBounce
|
||||
on excludeBounce.session_id = website_event.session_id
|
||||
and excludeBounce.visit_id = website_event.visit_id
|
||||
`;
|
||||
}
|
||||
|
||||
function getDateQuery(filters: Record<string, any>) {
|
||||
const { startDate, endDate, timezone } = filters;
|
||||
|
||||
|
|
@ -174,6 +193,7 @@ function parseFilters(filters: Record<string, any>, options?: QueryOptions) {
|
|||
dateQuery: getDateQuery(filters),
|
||||
queryParams: getQueryParams(filters),
|
||||
cohortQuery: getCohortQuery(cohortFilters),
|
||||
excludeBounceQuery: getExcludeBounceQuery(filters),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,25 @@ function getCohortQuery(filters: QueryFilters = {}) {
|
|||
`;
|
||||
}
|
||||
|
||||
function getExcludeBounceQuery(filters: Record<string, any>) {
|
||||
if (!filters.excludeBounce === true) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return `join
|
||||
(select distinct session_id, visit_id
|
||||
from website_event
|
||||
where website_id = {{websiteId}}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
and event_type = 1
|
||||
group by session_id, visit_id
|
||||
having count(*) > 1
|
||||
) excludeBounce
|
||||
on excludeBounce.session_id = website_event.session_id
|
||||
and excludeBounce.visit_id = website_event.visit_id
|
||||
`;
|
||||
}
|
||||
|
||||
function getDateQuery(filters: Record<string, any>) {
|
||||
const { startDate, endDate } = filters;
|
||||
|
||||
|
|
@ -186,6 +205,7 @@ function parseFilters(filters: Record<string, any>, options?: QueryOptions) {
|
|||
filterQuery: getFilterQuery(filters, options),
|
||||
queryParams: getQueryParams(filters),
|
||||
cohortQuery: getCohortQuery(cohortFilters),
|
||||
excludeBounceQuery: getExcludeBounceQuery(filters),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,10 @@ export async function getQueryFilters(
|
|||
cohort_endDate: endDate,
|
||||
});
|
||||
}
|
||||
|
||||
if (params.excludeBounce) {
|
||||
Object.assign(filters, { excludeBounce: true });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ export const filterParams = {
|
|||
segment: z.uuid().optional(),
|
||||
cohort: z.uuid().optional(),
|
||||
eventType: z.coerce.number().int().positive().optional(),
|
||||
excludeBounce: z.string().optional(),
|
||||
};
|
||||
|
||||
export const searchParams = {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ export interface FilterParams {
|
|||
segment?: string;
|
||||
cohort?: string;
|
||||
compare?: string;
|
||||
excludeBounce?: boolean;
|
||||
}
|
||||
|
||||
export interface SortParams {
|
||||
|
|
|
|||
|
|
@ -41,10 +41,11 @@ async function relationalQuery(
|
|||
filters: QueryFilters,
|
||||
): Promise<ChannelExpandedMetricsData[]> {
|
||||
const { rawQuery, parseFilters, getTimestampDiffSQL } = prisma;
|
||||
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, dateQuery } =
|
||||
parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -64,6 +65,7 @@ async function relationalQuery(
|
|||
max(website_event.created_at) max_time
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type != 2
|
||||
|
|
@ -119,7 +121,7 @@ async function clickhouseQuery(
|
|||
filters: QueryFilters,
|
||||
): Promise<ChannelExpandedMetricsData[]> {
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { queryParams, filterQuery, cohortQuery } = parseFilters({
|
||||
const { queryParams, filterQuery, cohortQuery, excludeBounceQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -166,6 +168,7 @@ async function clickhouseQuery(
|
|||
max(created_at) max_time
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@ export async function getChannelMetrics(...args: [websiteId: string, filters?: Q
|
|||
|
||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, dateQuery } =
|
||||
parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -41,6 +42,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type != 2
|
||||
|
|
@ -81,7 +83,7 @@ async function clickhouseQuery(
|
|||
filters: QueryFilters,
|
||||
): Promise<{ x: string; y: number }[]> {
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({
|
||||
const { queryParams, filterQuery, cohortQuery, excludeBounceQuery, dateQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -116,6 +118,7 @@ async function clickhouseQuery(
|
|||
count(distinct session_id) y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and event_type != 2
|
||||
${dateQuery}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,11 @@ async function relationalQuery(
|
|||
filters: QueryFilters,
|
||||
): Promise<WebsiteStatsData[]> {
|
||||
const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -50,12 +51,14 @@ async function relationalQuery(
|
|||
max(website_event.created_at) as "max_time"
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
${filterQuery}
|
||||
group by 1, 2
|
||||
|
||||
) as t
|
||||
`,
|
||||
queryParams,
|
||||
|
|
@ -68,7 +71,7 @@ async function clickhouseQuery(
|
|||
filters: QueryFilters,
|
||||
): Promise<WebsiteStatsData[]> {
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -92,6 +95,7 @@ async function clickhouseQuery(
|
|||
max(created_at) max_time
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
@ -115,6 +119,7 @@ async function clickhouseQuery(
|
|||
max(max_time) max_time
|
||||
from website_event_stats_hourly "website_event"
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ export async function getWeeklyTraffic(...args: [websiteId: string, filters: Que
|
|||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, getDateWeeklySQL, parseFilters } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -28,6 +29,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
count(distinct website_event.session_id) as value
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
|
|
@ -43,7 +45,10 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = await parseFilters({ ...filters, websiteId });
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = await parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
let sql = '';
|
||||
|
||||
|
|
@ -67,6 +72,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
|
|||
count(distinct session_id) as value
|
||||
from website_event_stats_hourly website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
|
|
|
|||
|
|
@ -38,13 +38,14 @@ async function relationalQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { rawQuery, parseFilters, getTimestampDiffSQL } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{ joinSession: SESSION_COLUMNS.includes(type) },
|
||||
);
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{ joinSession: SESSION_COLUMNS.includes(type) },
|
||||
);
|
||||
|
||||
let entryExitQuery = '';
|
||||
let excludeDomain = '';
|
||||
|
|
@ -94,6 +95,7 @@ async function relationalQuery(
|
|||
max(website_event.created_at) as "max_time"
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
${entryExitQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
|
|
@ -122,7 +124,7 @@ async function clickhouseQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -171,6 +173,7 @@ async function clickhouseQuery(
|
|||
max(created_at) max_time
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${entryExitQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,14 @@ async function relationalQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{ joinSession: SESSION_COLUMNS.includes(type) },
|
||||
);
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{ joinSession: SESSION_COLUMNS.includes(type) },
|
||||
);
|
||||
|
||||
let entryExitQuery = '';
|
||||
let excludeDomain = '';
|
||||
|
|
@ -75,6 +76,7 @@ async function relationalQuery(
|
|||
count(distinct website_event.session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
${entryExitQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
|
|
@ -100,7 +102,7 @@ async function clickhouseQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -135,6 +137,7 @@ async function clickhouseQuery(
|
|||
uniq(website_event.session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${entryExitQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
|
|
@ -174,6 +177,7 @@ async function clickhouseQuery(
|
|||
${columnQuery} as t
|
||||
from website_event_stats_hourly as website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ export async function getPageviewStats(...args: [websiteId: string, filters: Que
|
|||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { getDateSQL, parseFilters, rawQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, joinSessionQuery, queryParams } =
|
||||
parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -28,6 +29,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
count(*) y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
|
|
@ -47,7 +49,7 @@ async function clickhouseQuery(
|
|||
): Promise<{ x: string; y: number }[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { parseFilters, rawQuery, getDateSQL } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -65,6 +67,7 @@ async function clickhouseQuery(
|
|||
count(*) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
@ -84,6 +87,7 @@ async function clickhouseQuery(
|
|||
sum(views) as y
|
||||
from website_event_stats_hourly as website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
|
|||
|
|
@ -38,15 +38,16 @@ async function relationalQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { parseFilters, rawQuery, getTimestampDiffSQL } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{
|
||||
joinSession: SESSION_COLUMNS.includes(type),
|
||||
},
|
||||
);
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{
|
||||
joinSession: SESSION_COLUMNS.includes(type),
|
||||
},
|
||||
);
|
||||
const includeCountry = column === 'city' || column === 'region';
|
||||
|
||||
if (type === 'language') {
|
||||
|
|
@ -74,6 +75,7 @@ async function relationalQuery(
|
|||
max(website_event.created_at) as "max_time"
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
|
|
@ -102,7 +104,7 @@ async function clickhouseQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { parseFilters, rawQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -133,6 +135,7 @@ async function clickhouseQuery(
|
|||
max(created_at) max_time
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
|
|||
|
|
@ -29,15 +29,16 @@ async function relationalQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { parseFilters, rawQuery } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{
|
||||
joinSession: SESSION_COLUMNS.includes(type),
|
||||
},
|
||||
);
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters(
|
||||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
},
|
||||
{
|
||||
joinSession: SESSION_COLUMNS.includes(type),
|
||||
},
|
||||
);
|
||||
const includeCountry = column === 'city' || column === 'region';
|
||||
|
||||
if (type === 'language') {
|
||||
|
|
@ -52,6 +53,7 @@ async function relationalQuery(
|
|||
${includeCountry ? ', country' : ''}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
|
|
@ -76,7 +78,7 @@ async function clickhouseQuery(
|
|||
const { type, limit = 500, offset = 0 } = parameters;
|
||||
let column = FILTER_COLUMNS[type] || type;
|
||||
const { parseFilters, rawQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -96,6 +98,7 @@ async function clickhouseQuery(
|
|||
${includeCountry ? ', country' : ''}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
@ -114,6 +117,7 @@ async function clickhouseQuery(
|
|||
${includeCountry ? ', country' : ''}
|
||||
from website_event_stats_hourly as website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
|
|||
|
|
@ -16,10 +16,11 @@ export async function getSessionStats(...args: [websiteId: string, filters: Quer
|
|||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { getDateSQL, parseFilters, rawQuery } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, excludeBounceQuery, queryParams } =
|
||||
parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -28,6 +29,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
count(distinct website_event.session_id) y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
|
|
@ -47,7 +49,7 @@ async function clickhouseQuery(
|
|||
): Promise<{ x: string; y: number }[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { parseFilters, rawQuery, getDateSQL } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
const { filterQuery, cohortQuery, excludeBounceQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
|
@ -65,6 +67,7 @@ async function clickhouseQuery(
|
|||
count(distinct session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
@ -84,6 +87,7 @@ async function clickhouseQuery(
|
|||
uniq(session_id) as y
|
||||
from website_event_stats_hourly as website_event
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue