Compare commits

..

No commits in common. "ec81cd665fcc53514c68f4814f5f0dbae93af816" and "8e059212276e18e22095c72302d257a5780b7723" have entirely different histories.

16 changed files with 67 additions and 52 deletions

View file

@ -14,14 +14,14 @@ const frameAncestors = process.env.ALLOWED_FRAME_URLS || '';
const trackerScriptName = process.env.TRACKER_SCRIPT_NAME || '';
const trackerScriptURL = process.env.TRACKER_SCRIPT_URL || '';
const contentSecurityPolicy = `
default-src 'self';
img-src 'self' https: data:;
script-src 'self' 'unsafe-eval' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
connect-src *;
frame-ancestors 'self' ${frameAncestors};
`;
const contentSecurityPolicy = [
`default-src 'self'`,
`img-src * data:`,
`script-src 'self' 'unsafe-eval' 'unsafe-inline'`,
`style-src 'self' 'unsafe-inline'`,
`connect-src 'self' api.umami.is cloud.umami.is`,
`frame-ancestors 'self' ${frameAncestors}`,
];
const defaultHeaders = [
{
@ -30,7 +30,10 @@ const defaultHeaders = [
},
{
key: 'Content-Security-Policy',
value: contentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
value: contentSecurityPolicy
.join(';')
.replace(/\s{2,}/g, ' ')
.trim(),
},
];

View file

@ -23,5 +23,12 @@ if (!process.env.SKIP_DB_CHECK && !process.env.DATABASE_TYPE) {
}
if (process.env.CLOUD_URL) {
checkMissing(['CLOUD_URL', 'CLICKHOUSE_URL', 'REDIS_URL']);
checkMissing([
'CLOUD_URL',
'CLICKHOUSE_URL',
'REDIS_URL',
'KAFKA_BROKER',
'KAFKA_URL',
'KAFKA_SASL_MECHANISM',
]);
}

View file

@ -1,8 +1,8 @@
import { PixelPage } from './PixelPage';
import { Metadata } from 'next';
export default async function ({ params }: { params: { pixelId: string } }) {
const { pixelId } = await params;
export default function ({ params }: { params: { pixelId: string } }) {
const { pixelId } = params;
return <PixelPage pixelId={pixelId} />;
}

View file

@ -1,8 +1,8 @@
import { EVENT_COLUMNS, EVENT_TYPE, SESSION_COLUMNS } from '@/lib/constants';
import { canViewWebsite } from '@/permissions';
import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import { getQueryFilters, parseRequest } from '@/lib/request';
import { badRequest, json, unauthorized } from '@/lib/response';
import { dateRangeParams, filterParams, searchParams } from '@/lib/schema';
import { canViewWebsite } from '@/permissions';
import {
getChannelExpandedMetrics,
getEventExpandedMetrics,
@ -50,8 +50,13 @@ export async function GET(
}
if (EVENT_COLUMNS.includes(type)) {
if (type === 'event') {
const column = FILTER_COLUMNS[type] || type;
if (column === 'event_name') {
filters.eventType = EVENT_TYPE.customEvent;
}
if (type === 'event') {
return json(await getEventExpandedMetrics(websiteId, { type, limit, offset }, filters));
} else {
return json(await getPageviewExpandedMetrics(websiteId, { type, limit, offset }, filters));

View file

@ -1,8 +1,7 @@
import { EVENT_COLUMNS, EVENT_TYPE, SESSION_COLUMNS } from '@/lib/constants';
import { canViewWebsite } from '@/permissions';
import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import { getQueryFilters, parseRequest } from '@/lib/request';
import { badRequest, json, unauthorized } from '@/lib/response';
import { dateRangeParams, filterParams, searchParams } from '@/lib/schema';
import { canViewWebsite } from '@/permissions';
import {
getChannelMetrics,
getEventMetrics,
@ -10,6 +9,7 @@ import {
getSessionMetrics,
} from '@/queries/sql';
import { z } from 'zod';
import { dateRangeParams, filterParams, searchParams } from '@/lib/schema';
export async function GET(
request: Request,
@ -50,8 +50,13 @@ export async function GET(
}
if (EVENT_COLUMNS.includes(type)) {
if (type === 'event') {
const column = FILTER_COLUMNS[type] || type;
if (column === 'event_name') {
filters.eventType = EVENT_TYPE.customEvent;
}
if (type === 'event') {
return json(await getEventMetrics(websiteId, { type, limit, offset }, filters));
} else {
return json(await getPageviewMetrics(websiteId, { type, limit, offset }, filters));

View file

@ -122,8 +122,9 @@ export function parseDateValue(value: string) {
if (!match) return null;
const { num, unit } = match.groups;
const formattedNum = +num > 0 ? +num - 1 : +num;
return { num: +num, unit };
return { num: formattedNum, unit };
}
export function parseDateRange(value: string, locale = 'en-US'): DateRange {

View file

@ -75,7 +75,6 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.customEvent,
});
return rawQuery(

View file

@ -1,6 +1,7 @@
import clickhouse from '@/lib/clickhouse';
import {
EMAIL_DOMAINS,
EVENT_TYPE,
PAID_AD_PARAMS,
SEARCH_DOMAINS,
SHOPPING_DOMAINS,
@ -44,6 +45,7 @@ async function relationalQuery(
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
@ -66,8 +68,7 @@ async function relationalQuery(
from website_event
${cohortQuery}
${joinSessionQuery}
where website_event.website_id = {{websiteId::uuid}}
and website_event.event_type != 2
where website_id = {{websiteId::uuid}}
${dateQuery}
${filterQuery}
group by 1, 2
@ -92,6 +93,7 @@ async function clickhouseQuery(
const { queryParams, filterQuery, cohortQuery } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
@ -138,7 +140,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
and name != ''
${filterQuery}
group by prefix, name, session_id, visit_id

View file

@ -1,6 +1,7 @@
import clickhouse from '@/lib/clickhouse';
import {
EMAIL_DOMAINS,
EVENT_TYPE,
PAID_AD_PARAMS,
SEARCH_DOMAINS,
SHOPPING_DOMAINS,
@ -25,6 +26,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
@ -47,8 +49,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
from website_event
${cohortQuery}
${joinSessionQuery}
where website_event.website_id = {{websiteId::uuid}}
and website_event.event_type != 2
where website_id = {{websiteId::uuid}}
${dateQuery}
${filterQuery}
group by 1, 2
@ -73,6 +74,7 @@ async function clickhouseQuery(
const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
const sql = `
@ -106,7 +108,6 @@ async function clickhouseQuery(
from website_event
${cohortQuery}
where website_id = {websiteId:UUID}
and event_type != 2
${dateQuery}
${filterQuery}
group by 1, 2

View file

@ -1,8 +1,9 @@
import clickhouse from '@/lib/clickhouse';
import { EVENT_COLUMNS } from '@/lib/constants';
import { EVENT_TYPE } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types';
import { EVENT_COLUMNS } from '@/lib/constants';
export interface WebsiteStatsData {
pageviews: number;
@ -29,6 +30,7 @@ async function relationalQuery(
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
@ -51,7 +53,6 @@ async function relationalQuery(
${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
@ -68,6 +69,7 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
let sql = '';
@ -91,7 +93,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${filterQuery}
group by session_id, visit_id
) as t;
@ -114,7 +115,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${filterQuery}
group by session_id, visit_id
) as t;

View file

@ -64,7 +64,7 @@ async function relationalQuery(
from website_event
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and website_event.event_type != 2
and event_type = {{eventType}}
group by visit_id
) x
on x.visit_id = website_event.visit_id
@ -82,7 +82,6 @@ async function relationalQuery(
${entryExitQuery}
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and website_event.event_type != 2
${excludeDomain}
${filterQuery}
group by 1
@ -128,7 +127,7 @@ async function clickhouseQuery(
from website_event
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
and event_type = {eventType:UInt32}
group by visit_id) x
ON x.visit_id = website_event.visit_id`;
}
@ -155,7 +154,6 @@ async function clickhouseQuery(
${entryExitQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
and name != ''
${excludeDomain}
${filterQuery}

View file

@ -62,7 +62,7 @@ async function relationalQuery(
from website_event
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and website_event.event_type != 2
and event_type = {{eventType}}
order by visit_id, created_at ${order}
) x
on x.visit_id = website_event.visit_id
@ -79,7 +79,6 @@ async function relationalQuery(
${entryExitQuery}
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and website_event.event_type != 2
${excludeDomain}
${filterQuery}
group by 1
@ -125,7 +124,7 @@ async function clickhouseQuery(
from website_event
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
and event_type = {eventType:UInt32}
group by visit_id) x
ON x.visit_id = website_event.visit_id`;
}
@ -138,7 +137,6 @@ async function clickhouseQuery(
${entryExitQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${excludeDomain}
${filterQuery}
group by x
@ -176,7 +174,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${excludeDomain}
${filterQuery}
${groupByQuery}) as g

View file

@ -1,7 +1,7 @@
import clickhouse from '@/lib/clickhouse';
import { EVENT_COLUMNS } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma';
import { EVENT_COLUMNS, EVENT_TYPE } from '@/lib/constants';
import { QueryFilters } from '@/lib/types';
export async function getPageviewStats(...args: [websiteId: string, filters: QueryFilters]) {
@ -17,6 +17,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
@ -29,7 +30,6 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
${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
order by 1
@ -47,6 +47,7 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
let sql = '';
@ -64,7 +65,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${filterQuery}
group by t
) as g
@ -83,7 +83,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${filterQuery}
group by t
) as g

View file

@ -1,5 +1,5 @@
import clickhouse from '@/lib/clickhouse';
import { FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types';
@ -40,6 +40,7 @@ async function relationalQuery(
{
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
},
{
joinSession: SESSION_COLUMNS.includes(type),
@ -62,7 +63,6 @@ async function relationalQuery(
${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
${includeCountry ? ', 3' : ''}
@ -85,6 +85,7 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
const includeCountry = column === 'city' || column === 'region';
@ -115,7 +116,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
and name != ''
${filterQuery}
group by name, session_id, visit_id

View file

@ -55,7 +55,7 @@ async function relationalQuery(
${joinSessionQuery}
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and website_event.event_type != 2
and event_type != 2
${filterQuery}
group by 1
${includeCountry ? ', 3' : ''}

View file

@ -1,5 +1,5 @@
import clickhouse from '@/lib/clickhouse';
import { EVENT_COLUMNS } from '@/lib/constants';
import { EVENT_COLUMNS, EVENT_TYPE } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types';
@ -17,6 +17,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
@ -29,7 +30,6 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
${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
order by 1
@ -47,6 +47,7 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.pageView,
});
let sql = '';
@ -64,7 +65,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${filterQuery}
group by t
) as g
@ -83,7 +83,6 @@ async function clickhouseQuery(
${cohortQuery}
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type != 2
${filterQuery}
group by t
) as g