umami/src/queries/analytics/reports/getUTM.ts

120 lines
2.4 KiB
TypeScript
Raw Normal View History

2024-03-14 09:45:00 +00:00
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
2024-03-21 23:30:03 +00:00
import { safeDecodeURIComponent } from 'next-basics';
2024-03-14 09:45:00 +00:00
export async function getUTM(
...args: [
websiteId: string,
filters: {
startDate: Date;
endDate: Date;
timezone?: string;
},
]
) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(
websiteId: string,
filters: {
startDate: Date;
endDate: Date;
timezone?: string;
},
): Promise<
{
date: string;
day: number;
visitors: number;
returnVisitors: number;
percentage: number;
}[]
> {
const { startDate, endDate } = filters;
const { rawQuery } = prisma;
return rawQuery(
`
select url_query, count(*) as "num"
from website_event
where website_id = {{websiteId::uuid}}
and created_at between {{startDate}} and {{endDate}}
and url_query is not null
group by 1
`,
{
websiteId,
startDate,
endDate,
},
).then(results => {
return results;
});
}
async function clickhouseQuery(
websiteId: string,
filters: {
startDate: Date;
endDate: Date;
timezone?: string;
},
): Promise<
{
date: string;
day: number;
visitors: number;
returnVisitors: number;
percentage: number;
}[]
> {
const { startDate, endDate } = filters;
const { rawQuery } = clickhouse;
return rawQuery(
`
select url_query, count(*) as "num"
from website_event
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and url_query != ''
group by 1
`,
{
websiteId,
startDate,
endDate,
},
).then(result => parseParameters(result as any[]));
}
2024-03-21 02:52:07 +00:00
function parseParameters(data: any[]) {
return data.reduce((obj, { url_query, num }) => {
try {
const searchParams = new URLSearchParams(url_query);
2024-03-14 09:45:00 +00:00
2024-03-21 02:52:07 +00:00
for (const [key, value] of searchParams) {
if (key.match(/^utm_(\w+)$/)) {
2024-03-21 23:30:03 +00:00
const name = safeDecodeURIComponent(value);
2024-03-21 02:52:07 +00:00
if (!obj[key]) {
2024-03-21 20:33:48 +00:00
obj[key] = { [name]: +num };
} else if (!obj[key][name]) {
obj[key][name] = +num;
2024-03-21 02:52:07 +00:00
} else {
2024-03-21 20:33:48 +00:00
obj[key][name] += +num;
2024-03-21 02:52:07 +00:00
}
2024-03-14 09:45:00 +00:00
}
}
2024-03-21 02:52:07 +00:00
} catch {
// Ignore
2024-03-14 09:45:00 +00:00
}
2024-03-21 02:52:07 +00:00
return obj;
2024-03-14 09:45:00 +00:00
}, {});
}