mirror of
https://github.com/umami-software/umami.git
synced 2026-02-08 22:57:12 +01:00
Made filters work for all reports.
This commit is contained in:
parent
ea83afbc13
commit
8b64029409
46 changed files with 328 additions and 275 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import { EVENT_TYPE } from '@/lib/constants';
|
||||
import { CLICKHOUSE, getDatabaseType, POSTGRESQL, PRISMA, runQuery } from '@/lib/db';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
|
||||
export interface AttributionCriteria {
|
||||
|
|
@ -38,8 +38,6 @@ async function relationalQuery(
|
|||
const { rawQuery } = prisma;
|
||||
const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent;
|
||||
const column = type === 'page' ? 'url_path' : 'event_name';
|
||||
const db = getDatabaseType();
|
||||
const like = db === POSTGRESQL ? 'ilike' : 'like';
|
||||
|
||||
function getUTMQuery(utmColumn: string) {
|
||||
return `
|
||||
|
|
@ -79,7 +77,7 @@ async function relationalQuery(
|
|||
where website_id = {{websiteId::uuid}}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
and ${column} = {{conversionStep}}
|
||||
and currency ${like} {{currency}}
|
||||
and currency = {{currency}}
|
||||
group by 1),`;
|
||||
|
||||
function getModelQuery(model: string) {
|
||||
|
|
@ -243,26 +241,57 @@ async function clickhouseQuery(
|
|||
criteria: AttributionCriteria,
|
||||
): Promise<AttributionResult> {
|
||||
const { startDate, endDate, model, type, step, currency } = criteria;
|
||||
const { rawQuery } = clickhouse;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent;
|
||||
const column = type === 'page' ? 'url_path' : 'event_name';
|
||||
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||
|
||||
function getUTMQuery(utmColumn: string) {
|
||||
return `
|
||||
select
|
||||
we.${utmColumn} name,
|
||||
${currency ? 'sum(e.value)' : 'uniqExact(we.session_id)'} value
|
||||
from model m
|
||||
join website_event we
|
||||
on we.created_at = m.created_at
|
||||
and we.session_id = m.session_id
|
||||
${currency ? 'join events e on e.session_id = m.session_id' : ''}
|
||||
where we.website_id = {websiteId:UUID}
|
||||
select
|
||||
we.${utmColumn} name,
|
||||
${currency ? 'sum(e.value)' : 'uniqExact(we.session_id)'} value
|
||||
from model m
|
||||
join website_event we
|
||||
on we.created_at = m.created_at
|
||||
and we.session_id = m.session_id
|
||||
${currency ? 'join events e on e.session_id = m.session_id' : ''}
|
||||
where we.website_id = {websiteId:UUID}
|
||||
and we.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${currency ? '' : `and we.${utmColumn} != ''`}
|
||||
group by 1
|
||||
order by 2 desc
|
||||
limit 20
|
||||
`;
|
||||
}
|
||||
|
||||
function getModelQuery(model: string) {
|
||||
if (model === 'first-click') {
|
||||
return `
|
||||
model AS (select e.session_id,
|
||||
min(we.created_at) created_at
|
||||
from events e
|
||||
join website_event we
|
||||
on we.session_id = e.session_id
|
||||
where we.website_id = {websiteId:UUID}
|
||||
and we.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${currency ? '' : `and we.${utmColumn} != ''`}
|
||||
group by 1
|
||||
order by 2 desc
|
||||
limit 20`;
|
||||
${filterQuery}
|
||||
group by e.session_id)
|
||||
`;
|
||||
}
|
||||
|
||||
return `
|
||||
model AS (select e.session_id,
|
||||
max(we.created_at) created_at
|
||||
from events e
|
||||
join website_event we
|
||||
on we.session_id = e.session_id
|
||||
where we.website_id = {websiteId:UUID}
|
||||
and we.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and we.created_at < e.max_dt
|
||||
${filterQuery}
|
||||
group by e.session_id)
|
||||
`;
|
||||
}
|
||||
|
||||
const eventQuery = `WITH events AS (
|
||||
|
|
@ -288,29 +317,6 @@ async function clickhouseQuery(
|
|||
and currency = {currency:String}
|
||||
group by 1),`;
|
||||
|
||||
function getModelQuery(model: string) {
|
||||
return model === 'first-click'
|
||||
? `\n
|
||||
model AS (select e.session_id,
|
||||
min(we.created_at) created_at
|
||||
from events e
|
||||
join website_event we
|
||||
on we.session_id = e.session_id
|
||||
where we.website_id = {websiteId:UUID}
|
||||
and we.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
group by e.session_id)`
|
||||
: `\n
|
||||
model AS (select e.session_id,
|
||||
max(we.created_at) created_at
|
||||
from events e
|
||||
join website_event we
|
||||
on we.session_id = e.session_id
|
||||
where we.website_id = {websiteId:UUID}
|
||||
and we.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and we.created_at < e.max_dt
|
||||
group by e.session_id)`;
|
||||
}
|
||||
|
||||
const referrerRes = await rawQuery<
|
||||
{
|
||||
name: string;
|
||||
|
|
@ -339,7 +345,7 @@ async function clickhouseQuery(
|
|||
order by 2 desc
|
||||
limit 20
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
);
|
||||
|
||||
const paidAdsres = await rawQuery<
|
||||
|
|
@ -370,7 +376,7 @@ async function clickhouseQuery(
|
|||
order by 2 desc
|
||||
limit 20
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
);
|
||||
|
||||
const sourceRes = await rawQuery<
|
||||
|
|
@ -384,7 +390,7 @@ async function clickhouseQuery(
|
|||
${getModelQuery(model)}
|
||||
${getUTMQuery('utm_source')}
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
);
|
||||
|
||||
const mediumRes = await rawQuery<
|
||||
|
|
@ -398,7 +404,7 @@ async function clickhouseQuery(
|
|||
${getModelQuery(model)}
|
||||
${getUTMQuery('utm_medium')}
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
);
|
||||
|
||||
const campaignRes = await rawQuery<
|
||||
|
|
@ -412,7 +418,7 @@ async function clickhouseQuery(
|
|||
${getModelQuery(model)}
|
||||
${getUTMQuery('utm_campaign')}
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
);
|
||||
|
||||
const contentRes = await rawQuery<
|
||||
|
|
@ -426,7 +432,7 @@ async function clickhouseQuery(
|
|||
${getModelQuery(model)}
|
||||
${getUTMQuery('utm_content')}
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
);
|
||||
|
||||
const termRes = await rawQuery<
|
||||
|
|
@ -440,7 +446,7 @@ async function clickhouseQuery(
|
|||
${getModelQuery(model)}
|
||||
${getUTMQuery('utm_term')}
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
);
|
||||
|
||||
const totalRes = await rawQuery<{ pageviews: number; visitors: number; visits: number }>(
|
||||
|
|
@ -454,8 +460,9 @@ async function clickhouseQuery(
|
|||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and ${column} = {conversionStep:String}
|
||||
and event_type = {eventType:UInt32}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||
).then(result => result?.[0]);
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ async function relationalQuery(
|
|||
}[]
|
||||
> {
|
||||
const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma;
|
||||
const { filterQuery, joinSession, params } = await parseFilters(
|
||||
const { filterQuery, joinSession, filterParams } = await parseFilters(
|
||||
websiteId,
|
||||
{
|
||||
...filters,
|
||||
|
|
@ -65,7 +65,7 @@ async function relationalQuery(
|
|||
order by 1 desc, 2 desc
|
||||
limit 500
|
||||
`,
|
||||
params,
|
||||
filterParams,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +80,7 @@ async function clickhouseQuery(
|
|||
}[]
|
||||
> {
|
||||
const { parseFilters, rawQuery } = clickhouse;
|
||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
||||
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||
...filters,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
|
@ -114,7 +114,7 @@ async function clickhouseQuery(
|
|||
order by 1 desc, 2 desc
|
||||
limit 500
|
||||
`,
|
||||
params,
|
||||
filterParams,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,11 +121,12 @@ async function clickhouseQuery(
|
|||
}[]
|
||||
> {
|
||||
const { windowMinutes, startDate, endDate, steps } = criteria;
|
||||
const { rawQuery } = clickhouse;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { levelOneQuery, levelQuery, sumQuery, stepFilterQuery, params } = getFunnelQuery(
|
||||
steps,
|
||||
windowMinutes,
|
||||
);
|
||||
const { filterQuery, filterParams: filterParams } = await parseFilters(websiteId, criteria);
|
||||
|
||||
function getFunnelQuery(
|
||||
steps: { type: string; value: string }[],
|
||||
|
|
@ -200,6 +201,7 @@ async function clickhouseQuery(
|
|||
where (${stepFilterQuery})
|
||||
and website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
),
|
||||
${levelOneQuery}
|
||||
${levelQuery}
|
||||
|
|
@ -213,6 +215,7 @@ async function clickhouseQuery(
|
|||
startDate,
|
||||
endDate,
|
||||
...params,
|
||||
...filterParams,
|
||||
},
|
||||
).then(formatResults(steps));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export async function getGoal(...args: [websiteId: string, criteria: GoalCriteri
|
|||
async function relationalQuery(websiteId: string, criteria: GoalCriteria) {
|
||||
const { type, value } = criteria;
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, dateQuery, params } = await parseFilters(websiteId, criteria);
|
||||
const { filterQuery, dateQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||
const isPage = type === 'page';
|
||||
const column = isPage ? 'url_path' : 'event_name';
|
||||
const eventType = isPage ? 1 : 2;
|
||||
|
|
@ -43,14 +43,14 @@ async function relationalQuery(websiteId: string, criteria: GoalCriteria) {
|
|||
${dateQuery}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ ...params, value },
|
||||
{ ...filterParams, value },
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) {
|
||||
const { type, value } = criteria;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, dateQuery, params } = await parseFilters(websiteId, criteria);
|
||||
const { filterQuery, dateQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||
const isPage = type === 'page';
|
||||
const column = isPage ? 'url_path' : 'event_name';
|
||||
const eventType = isPage ? 1 : 2;
|
||||
|
|
@ -71,6 +71,6 @@ async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) {
|
|||
${dateQuery}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ ...params, value },
|
||||
{ ...filterParams, value },
|
||||
).then(results => results?.[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ async function relationalQuery(
|
|||
sequenceQuery,
|
||||
startStepQuery,
|
||||
endStepQuery,
|
||||
params,
|
||||
filterParams: params,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -152,7 +152,7 @@ async function clickhouseQuery(
|
|||
},
|
||||
): Promise<JourneyResult[]> {
|
||||
const { startDate, endDate, steps, startStep, endStep } = filters;
|
||||
const { rawQuery } = clickhouse;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { sequenceQuery, startStepQuery, endStepQuery, params } = getJourneyQuery(
|
||||
steps,
|
||||
startStep,
|
||||
|
|
@ -218,10 +218,12 @@ async function clickhouseQuery(
|
|||
sequenceQuery,
|
||||
startStepQuery,
|
||||
endStepQuery,
|
||||
params,
|
||||
filterParams: params,
|
||||
};
|
||||
}
|
||||
|
||||
const { filterQuery, filterParams: filterParams } = await parseFilters(websiteId, filters);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
WITH events AS (
|
||||
|
|
@ -231,6 +233,7 @@ async function clickhouseQuery(
|
|||
row_number() OVER (PARTITION BY visit_id ORDER BY created_at) AS event_number
|
||||
from umami.website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
${filterQuery}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}),
|
||||
${sequenceQuery}
|
||||
select *
|
||||
|
|
@ -246,6 +249,7 @@ async function clickhouseQuery(
|
|||
startDate,
|
||||
endDate,
|
||||
...params,
|
||||
...filterParams,
|
||||
},
|
||||
).then(parseResult);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,11 @@ async function relationalQuery(
|
|||
criteria: RetentionCriteria,
|
||||
): Promise<RetentionResult[]> {
|
||||
const { startDate, endDate, timezone } = criteria;
|
||||
const { getDateSQL, getDayDiffQuery, getCastColumnQuery, rawQuery } = prisma;
|
||||
const { getDateSQL, getDayDiffQuery, getCastColumnQuery, rawQuery, parseFilters } = prisma;
|
||||
const unit = 'day';
|
||||
|
||||
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
WITH cohort_items AS (
|
||||
|
|
@ -49,6 +51,7 @@ async function relationalQuery(
|
|||
on w.session_id = c.session_id
|
||||
where website_id = {{websiteId::uuid}}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
),
|
||||
cohort_size as (
|
||||
select cohort_date,
|
||||
|
|
@ -82,6 +85,7 @@ async function relationalQuery(
|
|||
websiteId,
|
||||
startDate,
|
||||
endDate,
|
||||
...filterParams,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -91,9 +95,11 @@ async function clickhouseQuery(
|
|||
criteria: RetentionCriteria,
|
||||
): Promise<RetentionResult[]> {
|
||||
const { startDate, endDate, timezone } = criteria;
|
||||
const { getDateSQL, rawQuery } = clickhouse;
|
||||
const { getDateSQL, rawQuery, parseFilters } = clickhouse;
|
||||
const unit = 'day';
|
||||
|
||||
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
WITH cohort_items AS (
|
||||
|
|
@ -114,6 +120,7 @@ async function clickhouseQuery(
|
|||
on w.session_id = c.session_id
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
),
|
||||
cohort_size as (
|
||||
select cohort_date,
|
||||
|
|
@ -147,6 +154,7 @@ async function clickhouseQuery(
|
|||
websiteId,
|
||||
startDate,
|
||||
endDate,
|
||||
...filterParams,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ export async function getUTM(...args: [websiteId: string, criteria: UTMCriteria]
|
|||
|
||||
async function relationalQuery(websiteId: string, criteria: UTMCriteria) {
|
||||
const { startDate, endDate } = criteria;
|
||||
const { rawQuery } = prisma;
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -26,9 +27,11 @@ async function relationalQuery(websiteId: string, criteria: UTMCriteria) {
|
|||
and created_at between {{startDate}} and {{endDate}}
|
||||
and coalesce(url_query, '') != ''
|
||||
and event_type = 1
|
||||
${filterQuery}
|
||||
group by 1
|
||||
`,
|
||||
{
|
||||
...filterParams,
|
||||
websiteId,
|
||||
startDate,
|
||||
endDate,
|
||||
|
|
@ -38,7 +41,8 @@ async function relationalQuery(websiteId: string, criteria: UTMCriteria) {
|
|||
|
||||
async function clickhouseQuery(websiteId: string, criteria: UTMCriteria) {
|
||||
const { startDate, endDate } = criteria;
|
||||
const { rawQuery } = clickhouse;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
|
|
@ -48,9 +52,11 @@ async function clickhouseQuery(websiteId: string, criteria: UTMCriteria) {
|
|||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and url_query != ''
|
||||
and event_type = 1
|
||||
${filterQuery}
|
||||
group by 1
|
||||
`,
|
||||
{
|
||||
...filterParams,
|
||||
websiteId,
|
||||
startDate,
|
||||
endDate,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue