mirror of
https://github.com/umami-software/umami.git
synced 2026-02-19 03:55:37 +01:00
Compare commits
7 commits
8e05921227
...
ec81cd665f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec81cd665f | ||
|
|
1809959b99 | ||
|
|
cd6ad0add2 | ||
|
|
8ca73268ba | ||
|
|
98bdc82239 | ||
|
|
f86c21b25b | ||
|
|
a8b4ddd054 |
16 changed files with 52 additions and 67 deletions
|
|
@ -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 * 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 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 defaultHeaders = [
|
||||
{
|
||||
|
|
@ -30,10 +30,7 @@ const defaultHeaders = [
|
|||
},
|
||||
{
|
||||
key: 'Content-Security-Policy',
|
||||
value: contentSecurityPolicy
|
||||
.join(';')
|
||||
.replace(/\s{2,}/g, ' ')
|
||||
.trim(),
|
||||
value: contentSecurityPolicy.replace(/\s{2,}/g, ' ').trim(),
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -23,12 +23,5 @@ if (!process.env.SKIP_DB_CHECK && !process.env.DATABASE_TYPE) {
|
|||
}
|
||||
|
||||
if (process.env.CLOUD_URL) {
|
||||
checkMissing([
|
||||
'CLOUD_URL',
|
||||
'CLICKHOUSE_URL',
|
||||
'REDIS_URL',
|
||||
'KAFKA_BROKER',
|
||||
'KAFKA_URL',
|
||||
'KAFKA_SASL_MECHANISM',
|
||||
]);
|
||||
checkMissing(['CLOUD_URL', 'CLICKHOUSE_URL', 'REDIS_URL']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { PixelPage } from './PixelPage';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default function ({ params }: { params: { pixelId: string } }) {
|
||||
const { pixelId } = params;
|
||||
export default async function ({ params }: { params: { pixelId: string } }) {
|
||||
const { pixelId } = await params;
|
||||
|
||||
return <PixelPage pixelId={pixelId} />;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { canViewWebsite } from '@/permissions';
|
||||
import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
|
||||
import { EVENT_COLUMNS, EVENT_TYPE, 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,13 +50,8 @@ export async function GET(
|
|||
}
|
||||
|
||||
if (EVENT_COLUMNS.includes(type)) {
|
||||
const column = FILTER_COLUMNS[type] || type;
|
||||
|
||||
if (column === 'event_name') {
|
||||
filters.eventType = EVENT_TYPE.customEvent;
|
||||
}
|
||||
|
||||
if (type === 'event') {
|
||||
filters.eventType = EVENT_TYPE.customEvent;
|
||||
return json(await getEventExpandedMetrics(websiteId, { type, limit, offset }, filters));
|
||||
} else {
|
||||
return json(await getPageviewExpandedMetrics(websiteId, { type, limit, offset }, filters));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { canViewWebsite } from '@/permissions';
|
||||
import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
|
||||
import { EVENT_COLUMNS, EVENT_TYPE, 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,
|
||||
|
|
@ -9,7 +10,6 @@ import {
|
|||
getSessionMetrics,
|
||||
} from '@/queries/sql';
|
||||
import { z } from 'zod';
|
||||
import { dateRangeParams, filterParams, searchParams } from '@/lib/schema';
|
||||
|
||||
export async function GET(
|
||||
request: Request,
|
||||
|
|
@ -50,13 +50,8 @@ export async function GET(
|
|||
}
|
||||
|
||||
if (EVENT_COLUMNS.includes(type)) {
|
||||
const column = FILTER_COLUMNS[type] || type;
|
||||
|
||||
if (column === 'event_name') {
|
||||
filters.eventType = EVENT_TYPE.customEvent;
|
||||
}
|
||||
|
||||
if (type === 'event') {
|
||||
filters.eventType = EVENT_TYPE.customEvent;
|
||||
return json(await getEventMetrics(websiteId, { type, limit, offset }, filters));
|
||||
} else {
|
||||
return json(await getPageviewMetrics(websiteId, { type, limit, offset }, filters));
|
||||
|
|
|
|||
|
|
@ -122,9 +122,8 @@ export function parseDateValue(value: string) {
|
|||
if (!match) return null;
|
||||
|
||||
const { num, unit } = match.groups;
|
||||
const formattedNum = +num > 0 ? +num - 1 : +num;
|
||||
|
||||
return { num: formattedNum, unit };
|
||||
return { num: +num, unit };
|
||||
}
|
||||
|
||||
export function parseDateRange(value: string, locale = 'en-US'): DateRange {
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ async function clickhouseQuery(
|
|||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.customEvent,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import {
|
||||
EMAIL_DOMAINS,
|
||||
EVENT_TYPE,
|
||||
PAID_AD_PARAMS,
|
||||
SEARCH_DOMAINS,
|
||||
SHOPPING_DOMAINS,
|
||||
|
|
@ -45,7 +44,6 @@ async function relationalQuery(
|
|||
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
|
|
@ -68,7 +66,8 @@ async function relationalQuery(
|
|||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_id = {{websiteId::uuid}}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type != 2
|
||||
${dateQuery}
|
||||
${filterQuery}
|
||||
group by 1, 2
|
||||
|
|
@ -93,7 +92,6 @@ async function clickhouseQuery(
|
|||
const { queryParams, filterQuery, cohortQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
|
|
@ -140,6 +138,7 @@ 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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import {
|
||||
EMAIL_DOMAINS,
|
||||
EVENT_TYPE,
|
||||
PAID_AD_PARAMS,
|
||||
SEARCH_DOMAINS,
|
||||
SHOPPING_DOMAINS,
|
||||
|
|
@ -26,7 +25,6 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
const { queryParams, filterQuery, joinSessionQuery, cohortQuery, dateQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
|
|
@ -49,7 +47,8 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_id = {{websiteId::uuid}}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type != 2
|
||||
${dateQuery}
|
||||
${filterQuery}
|
||||
group by 1, 2
|
||||
|
|
@ -74,7 +73,6 @@ async function clickhouseQuery(
|
|||
const { queryParams, filterQuery, cohortQuery, dateQuery } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
const sql = `
|
||||
|
|
@ -108,6 +106,7 @@ async function clickhouseQuery(
|
|||
from website_event
|
||||
${cohortQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and event_type != 2
|
||||
${dateQuery}
|
||||
${filterQuery}
|
||||
group by 1, 2
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import { EVENT_TYPE } from '@/lib/constants';
|
||||
import { EVENT_COLUMNS } 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;
|
||||
|
|
@ -30,7 +29,6 @@ async function relationalQuery(
|
|||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
|
|
@ -53,6 +51,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
|
||||
${filterQuery}
|
||||
group by 1, 2
|
||||
) as t
|
||||
|
|
@ -69,7 +68,6 @@ async function clickhouseQuery(
|
|||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
let sql = '';
|
||||
|
|
@ -93,6 +91,7 @@ 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;
|
||||
|
|
@ -115,6 +114,7 @@ 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;
|
||||
|
|
|
|||
|
|
@ -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 event_type = {{eventType}}
|
||||
and website_event.event_type != 2
|
||||
group by visit_id
|
||||
) x
|
||||
on x.visit_id = website_event.visit_id
|
||||
|
|
@ -82,6 +82,7 @@ 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
|
||||
|
|
@ -127,7 +128,7 @@ async function clickhouseQuery(
|
|||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type = {eventType:UInt32}
|
||||
and event_type != 2
|
||||
group by visit_id) x
|
||||
ON x.visit_id = website_event.visit_id`;
|
||||
}
|
||||
|
|
@ -154,6 +155,7 @@ 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}
|
||||
|
|
|
|||
|
|
@ -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 event_type = {{eventType}}
|
||||
and website_event.event_type != 2
|
||||
order by visit_id, created_at ${order}
|
||||
) x
|
||||
on x.visit_id = website_event.visit_id
|
||||
|
|
@ -79,6 +79,7 @@ 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
|
||||
|
|
@ -124,7 +125,7 @@ async function clickhouseQuery(
|
|||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type = {eventType:UInt32}
|
||||
and event_type != 2
|
||||
group by visit_id) x
|
||||
ON x.visit_id = website_event.visit_id`;
|
||||
}
|
||||
|
|
@ -137,6 +138,7 @@ 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
|
||||
|
|
@ -174,6 +176,7 @@ 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
|
||||
|
|
|
|||
|
|
@ -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,7 +17,6 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
|
|
@ -30,6 +29,7 @@ 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,7 +47,6 @@ async function clickhouseQuery(
|
|||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
let sql = '';
|
||||
|
|
@ -65,6 +64,7 @@ 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,6 +83,7 @@ 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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import { EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
|
||||
import { 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,7 +40,6 @@ async function relationalQuery(
|
|||
{
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
},
|
||||
{
|
||||
joinSession: SESSION_COLUMNS.includes(type),
|
||||
|
|
@ -63,6 +62,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
|
||||
${filterQuery}
|
||||
group by 1
|
||||
${includeCountry ? ', 3' : ''}
|
||||
|
|
@ -85,7 +85,6 @@ async function clickhouseQuery(
|
|||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
const includeCountry = column === 'city' || column === 'region';
|
||||
|
||||
|
|
@ -116,6 +115,7 @@ 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
|
||||
|
|
|
|||
|
|
@ -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 event_type != 2
|
||||
and website_event.event_type != 2
|
||||
${filterQuery}
|
||||
group by 1
|
||||
${includeCountry ? ', 3' : ''}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import clickhouse from '@/lib/clickhouse';
|
||||
import { EVENT_COLUMNS, EVENT_TYPE } from '@/lib/constants';
|
||||
import { EVENT_COLUMNS } from '@/lib/constants';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import { QueryFilters } from '@/lib/types';
|
||||
|
|
@ -17,7 +17,6 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
|||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
|
|
@ -30,6 +29,7 @@ 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,7 +47,6 @@ async function clickhouseQuery(
|
|||
const { filterQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
eventType: EVENT_TYPE.pageView,
|
||||
});
|
||||
|
||||
let sql = '';
|
||||
|
|
@ -65,6 +64,7 @@ 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,6 +83,7 @@ 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue