mirror of
https://github.com/umami-software/umami.git
synced 2026-02-14 09:35:36 +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
|
|
@ -24,7 +24,7 @@ export function WebsiteControls({
|
||||||
{allowDateFilter && <WebsiteDateFilter websiteId={websiteId} allowCompare={allowCompare} />}
|
{allowDateFilter && <WebsiteDateFilter websiteId={websiteId} allowCompare={allowCompare} />}
|
||||||
{allowMonthFilter && <WebsiteMonthSelect websiteId={websiteId} />}
|
{allowMonthFilter && <WebsiteMonthSelect websiteId={websiteId} />}
|
||||||
</Row>
|
</Row>
|
||||||
<FilterBar />
|
{allowFilter && <FilterBar />}
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ export function ReportsNav({ websiteId }: { websiteId: string }) {
|
||||||
key={id}
|
key={id}
|
||||||
href={renderUrl(
|
href={renderUrl(
|
||||||
`/websites/${websiteId}/reports${path}`,
|
`/websites/${websiteId}/reports${path}`,
|
||||||
path === '/retention' ? false : null,
|
path === '/retention' ? { date: undefined } : null,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<NavMenuItem isSelected={isSelected}>
|
<NavMenuItem isSelected={isSelected}>
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ export function Attribution({
|
||||||
const metrics = data
|
const metrics = data
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
value: pageviews,
|
value: visitors,
|
||||||
label: formatMessage(labels.views),
|
label: formatMessage(labels.visitors),
|
||||||
formatValue: formatLongNumber,
|
formatValue: formatLongNumber,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -58,8 +58,8 @@ export function Attribution({
|
||||||
formatValue: formatLongNumber,
|
formatValue: formatLongNumber,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: visitors,
|
value: pageviews,
|
||||||
label: formatMessage(labels.visitors),
|
label: formatMessage(labels.views),
|
||||||
formatValue: formatLongNumber,
|
formatValue: formatLongNumber,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
@ -83,60 +83,64 @@ export function Attribution({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingPanel data={data} isLoading={isLoading} error={error}>
|
<LoadingPanel data={data} isLoading={isLoading} error={error}>
|
||||||
<Column gap>
|
{data && (
|
||||||
<MetricsBar>
|
<Column gap>
|
||||||
{metrics?.map(({ label, value, formatValue }) => {
|
<MetricsBar>
|
||||||
return <MetricCard key={label} value={value} label={label} formatValue={formatValue} />;
|
{metrics?.map(({ label, value, formatValue }) => {
|
||||||
})}
|
return (
|
||||||
</MetricsBar>
|
<MetricCard key={label} value={value} label={label} formatValue={formatValue} />
|
||||||
<SectionHeader title={formatMessage(labels.sources)} />
|
);
|
||||||
<Grid columns="1fr 1fr" gap>
|
})}
|
||||||
<Panel>
|
</MetricsBar>
|
||||||
<ListTable
|
<SectionHeader title={formatMessage(labels.sources)} />
|
||||||
title={formatMessage(labels.referrer)}
|
<Grid columns="1fr 1fr" gap>
|
||||||
metric={formatMessage(currency ? labels.revenue : labels.visitors)}
|
<Panel>
|
||||||
currency={currency}
|
<ListTable
|
||||||
data={percentFilter(
|
title={formatMessage(labels.referrer)}
|
||||||
data?.['referrer']?.map(({ name, value }) => ({
|
metric={formatMessage(currency ? labels.revenue : labels.visitors)}
|
||||||
x: name,
|
currency={currency}
|
||||||
y: Number(value),
|
data={percentFilter(
|
||||||
})),
|
data?.['referrer']?.map(({ name, value }) => ({
|
||||||
)}
|
x: name,
|
||||||
/>
|
y: Number(value),
|
||||||
</Panel>
|
})),
|
||||||
<Panel>
|
)}
|
||||||
<ListTable
|
/>
|
||||||
title={formatMessage(labels.paidAds)}
|
</Panel>
|
||||||
metric={formatMessage(currency ? labels.revenue : labels.visitors)}
|
<Panel>
|
||||||
currency={currency}
|
<ListTable
|
||||||
data={percentFilter(
|
title={formatMessage(labels.paidAds)}
|
||||||
data?.['paidAds']?.map(({ name, value }) => ({
|
metric={formatMessage(currency ? labels.revenue : labels.visitors)}
|
||||||
x: name,
|
currency={currency}
|
||||||
y: Number(value),
|
data={percentFilter(
|
||||||
})),
|
data?.['paidAds']?.map(({ name, value }) => ({
|
||||||
)}
|
x: name,
|
||||||
/>
|
y: Number(value),
|
||||||
</Panel>
|
})),
|
||||||
</Grid>
|
)}
|
||||||
<SectionHeader title="UTM" />
|
/>
|
||||||
<Grid columns="1fr 1fr" gap>
|
</Panel>
|
||||||
<Panel>
|
</Grid>
|
||||||
<UTMTable data={data?.['utm_source']} title={formatMessage(labels.sources)} />
|
<SectionHeader title="UTM" />
|
||||||
</Panel>
|
<Grid columns="1fr 1fr" gap>
|
||||||
<Panel>
|
<Panel>
|
||||||
<UTMTable data={data?.['utm_medium']} title={formatMessage(labels.medium)} />
|
<UTMTable data={data?.['utm_source']} title={formatMessage(labels.sources)} />
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel>
|
<Panel>
|
||||||
<UTMTable data={data?.['utm_cmapaign']} title={formatMessage(labels.campaigns)} />
|
<UTMTable data={data?.['utm_medium']} title={formatMessage(labels.medium)} />
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel>
|
<Panel>
|
||||||
<UTMTable data={data?.['utm_content']} title={formatMessage(labels.content)} />
|
<UTMTable data={data?.['utm_cmapaign']} title={formatMessage(labels.campaigns)} />
|
||||||
</Panel>
|
</Panel>
|
||||||
<Panel>
|
<Panel>
|
||||||
<UTMTable data={data?.['utm_term']} title={formatMessage(labels.terms)} />
|
<UTMTable data={data?.['utm_content']} title={formatMessage(labels.content)} />
|
||||||
</Panel>
|
</Panel>
|
||||||
</Grid>
|
<Panel>
|
||||||
</Column>
|
<UTMTable data={data?.['utm_term']} title={formatMessage(labels.terms)} />
|
||||||
|
</Panel>
|
||||||
|
</Grid>
|
||||||
|
</Column>
|
||||||
|
)}
|
||||||
</LoadingPanel>
|
</LoadingPanel>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export function RevenuePage({ websiteId }: { websiteId: string }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Column gap>
|
<Column gap>
|
||||||
<WebsiteControls websiteId={websiteId} allowCompare={false} />
|
<WebsiteControls websiteId={websiteId} allowFilter={false} />
|
||||||
<Revenue websiteId={websiteId} startDate={startDate} endDate={endDate} />
|
<Revenue websiteId={websiteId} startDate={startDate} endDate={endDate} />
|
||||||
</Column>
|
</Column>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -26,47 +26,49 @@ export function UTM({ websiteId, startDate, endDate }: UTMProps) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoadingPanel data={data} isLoading={isLoading} error={error}>
|
<LoadingPanel data={data} isLoading={isLoading} error={error}>
|
||||||
<Column gap>
|
{data && (
|
||||||
{UTM_PARAMS.map(param => {
|
<Column gap>
|
||||||
const items = toArray(data?.[param]);
|
{UTM_PARAMS.map(param => {
|
||||||
const chartData = {
|
const items = toArray(data?.[param]);
|
||||||
labels: items.map(({ name }) => name),
|
const chartData = {
|
||||||
datasets: [
|
labels: items.map(({ name }) => name),
|
||||||
{
|
datasets: [
|
||||||
data: items.map(({ value }) => value),
|
{
|
||||||
backgroundColor: CHART_COLORS,
|
data: items.map(({ value }) => value),
|
||||||
borderWidth: 0,
|
backgroundColor: CHART_COLORS,
|
||||||
},
|
borderWidth: 0,
|
||||||
],
|
},
|
||||||
};
|
],
|
||||||
const total = items.reduce((sum, { value }) => {
|
};
|
||||||
return +sum + +value;
|
const total = items.reduce((sum, { value }) => {
|
||||||
}, 0);
|
return +sum + +value;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel key={param}>
|
<Panel key={param}>
|
||||||
<Grid columns="1fr 1fr">
|
<Grid columns="1fr 1fr">
|
||||||
<Column>
|
<Column>
|
||||||
<Heading>
|
<Heading>
|
||||||
<Text transform="capitalize">{param.replace(/^utm_/, '')}</Text>
|
<Text transform="capitalize">{param.replace(/^utm_/, '')}</Text>
|
||||||
</Heading>
|
</Heading>
|
||||||
<ListTable
|
<ListTable
|
||||||
metric={formatMessage(labels.views)}
|
metric={formatMessage(labels.views)}
|
||||||
data={items.map(({ name, value }) => ({
|
data={items.map(({ name, value }) => ({
|
||||||
x: name,
|
x: name,
|
||||||
y: value,
|
y: value,
|
||||||
z: (value / total) * 100,
|
z: (value / total) * 100,
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
</Column>
|
</Column>
|
||||||
<Column>
|
<Column>
|
||||||
<PieChart type="doughnut" chartData={chartData} />
|
<PieChart type="doughnut" chartData={chartData} />
|
||||||
</Column>
|
</Column>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Panel>
|
</Panel>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Column>
|
</Column>
|
||||||
|
)}
|
||||||
</LoadingPanel>
|
</LoadingPanel>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export async function POST(request: Request) {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate },
|
dateRange: { startDate, endDate },
|
||||||
parameters: { model, type, step, currency },
|
parameters: { model, type, step, currency },
|
||||||
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -22,6 +23,7 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getAttribution(websiteId, {
|
const data = await getAttribution(websiteId, {
|
||||||
|
...filters,
|
||||||
startDate: new Date(startDate),
|
startDate: new Date(startDate),
|
||||||
endDate: new Date(endDate),
|
endDate: new Date(endDate),
|
||||||
model,
|
model,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export async function POST(request: Request) {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate },
|
dateRange: { startDate, endDate },
|
||||||
parameters: { fields },
|
parameters: { fields },
|
||||||
filters,
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -23,9 +23,9 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getBreakdown(websiteId, fields, {
|
const data = await getBreakdown(websiteId, fields, {
|
||||||
|
...filters,
|
||||||
startDate: new Date(startDate),
|
startDate: new Date(startDate),
|
||||||
endDate: new Date(endDate),
|
endDate: new Date(endDate),
|
||||||
...filters,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return json(data);
|
return json(data);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export async function POST(request: Request) {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate },
|
dateRange: { startDate, endDate },
|
||||||
parameters: { steps, window },
|
parameters: { steps, window },
|
||||||
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -22,6 +23,7 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getFunnel(websiteId, {
|
const data = await getFunnel(websiteId, {
|
||||||
|
...filters,
|
||||||
startDate: new Date(startDate),
|
startDate: new Date(startDate),
|
||||||
endDate: new Date(endDate),
|
endDate: new Date(endDate),
|
||||||
steps,
|
steps,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export async function POST(request: Request) {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate },
|
dateRange: { startDate, endDate },
|
||||||
parameters: { type, value, property, operator },
|
parameters: { type, value, property, operator },
|
||||||
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -22,12 +23,13 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getGoal(websiteId, {
|
const data = await getGoal(websiteId, {
|
||||||
|
...filters,
|
||||||
|
startDate: new Date(startDate),
|
||||||
|
endDate: new Date(endDate),
|
||||||
type,
|
type,
|
||||||
value,
|
value,
|
||||||
property,
|
property,
|
||||||
operator,
|
operator,
|
||||||
startDate: new Date(startDate),
|
|
||||||
endDate: new Date(endDate),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return json(data);
|
return json(data);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export async function POST(request: Request) {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate },
|
dateRange: { startDate, endDate },
|
||||||
parameters: { steps, startStep, endStep },
|
parameters: { steps, startStep, endStep },
|
||||||
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -22,6 +23,7 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getJourney(websiteId, {
|
const data = await getJourney(websiteId, {
|
||||||
|
...filters,
|
||||||
startDate: new Date(startDate),
|
startDate: new Date(startDate),
|
||||||
endDate: new Date(endDate),
|
endDate: new Date(endDate),
|
||||||
steps,
|
steps,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export async function POST(request: Request) {
|
||||||
const {
|
const {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate, timezone },
|
dateRange: { startDate, endDate, timezone },
|
||||||
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -21,6 +22,7 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getRetention(websiteId, {
|
const data = await getRetention(websiteId, {
|
||||||
|
...filters,
|
||||||
startDate: new Date(startDate),
|
startDate: new Date(startDate),
|
||||||
endDate: new Date(endDate),
|
endDate: new Date(endDate),
|
||||||
timezone,
|
timezone,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export async function POST(request: Request) {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate, unit },
|
dateRange: { startDate, endDate, unit },
|
||||||
parameters: { currency },
|
parameters: { currency },
|
||||||
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -22,6 +23,7 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getRevenue(websiteId, {
|
const data = await getRevenue(websiteId, {
|
||||||
|
...filters,
|
||||||
startDate: new Date(startDate),
|
startDate: new Date(startDate),
|
||||||
endDate: new Date(endDate),
|
endDate: new Date(endDate),
|
||||||
unit,
|
unit,
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export async function POST(request: Request) {
|
||||||
const {
|
const {
|
||||||
websiteId,
|
websiteId,
|
||||||
dateRange: { startDate, endDate },
|
dateRange: { startDate, endDate },
|
||||||
|
...filters
|
||||||
} = body;
|
} = body;
|
||||||
|
|
||||||
if (!(await canViewWebsite(auth, websiteId))) {
|
if (!(await canViewWebsite(auth, websiteId))) {
|
||||||
|
|
@ -21,6 +22,7 @@ export async function POST(request: Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await getUTM(websiteId, {
|
const data = await getUTM(websiteId, {
|
||||||
|
...filters,
|
||||||
startDate: new Date(startDate),
|
startDate: new Date(startDate),
|
||||||
endDate: new Date(endDate),
|
endDate: new Date(endDate),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export function useResultQuery<T>(
|
||||||
) {
|
) {
|
||||||
const { websiteId } = params;
|
const { websiteId } = params;
|
||||||
const { post, useQuery } = useApi();
|
const { post, useQuery } = useApi();
|
||||||
const filterParams = useFilterParams(websiteId);
|
const filters = useFilterParams(websiteId);
|
||||||
|
|
||||||
return useQuery<T>({
|
return useQuery<T>({
|
||||||
queryKey: [
|
queryKey: [
|
||||||
|
|
@ -17,11 +17,11 @@ export function useResultQuery<T>(
|
||||||
{
|
{
|
||||||
type,
|
type,
|
||||||
websiteId,
|
websiteId,
|
||||||
...filterParams,
|
...filters,
|
||||||
...params,
|
...params,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
queryFn: () => post(`/reports/${type}`, { type, ...filterParams, ...params }),
|
queryFn: () => post(`/reports/${type}`, { type, ...filters, ...params }),
|
||||||
enabled: !!type,
|
enabled: !!type,
|
||||||
...options,
|
...options,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ export function useFilterParams(websiteId: string) {
|
||||||
city,
|
city,
|
||||||
event,
|
event,
|
||||||
tag,
|
tag,
|
||||||
|
hostname,
|
||||||
},
|
},
|
||||||
} = useNavigation();
|
} = useNavigation();
|
||||||
|
|
||||||
|
|
@ -42,5 +43,6 @@ export function useFilterParams(websiteId: string) {
|
||||||
city,
|
city,
|
||||||
event,
|
event,
|
||||||
tag,
|
tag,
|
||||||
|
hostname,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export function usePagedQuery<T = any>({
|
||||||
return {
|
return {
|
||||||
result: data as PageResult<T>,
|
result: data as PageResult<T>,
|
||||||
query,
|
query,
|
||||||
params,
|
filterParams: params,
|
||||||
setParams,
|
setParams,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { FloatingTooltip, Column, useTheme } from '@umami/react-zen';
|
import { FloatingTooltip, Column, useTheme, ColumnProps } from '@umami/react-zen';
|
||||||
import { useState, useMemo, HTMLAttributes } from 'react';
|
import { useState, useMemo } from 'react';
|
||||||
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
|
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { colord } from 'colord';
|
import { colord } from 'colord';
|
||||||
|
|
@ -16,16 +16,12 @@ import { percentFilter } from '@/lib/filters';
|
||||||
import styles from './WorldMap.module.css';
|
import styles from './WorldMap.module.css';
|
||||||
import { getThemeColors } from '@/lib/colors';
|
import { getThemeColors } from '@/lib/colors';
|
||||||
|
|
||||||
export function WorldMap({
|
export interface WorldMapProps extends ColumnProps {
|
||||||
websiteId,
|
|
||||||
data,
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: {
|
|
||||||
websiteId?: string;
|
websiteId?: string;
|
||||||
data?: any[];
|
data?: any[];
|
||||||
className?: string;
|
}
|
||||||
} & HTMLAttributes<HTMLDivElement>) {
|
|
||||||
|
export function WorldMap({ websiteId, data, className, ...props }: WorldMapProps) {
|
||||||
const [tooltip, setTooltipPopup] = useState();
|
const [tooltip, setTooltipPopup] = useState();
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const { colors } = getThemeColors(theme);
|
const { colors } = getThemeColors(theme);
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ async function parseFilters(websiteId: string, filters: QueryFilters = {}, optio
|
||||||
return {
|
return {
|
||||||
filterQuery: getFilterQuery(filters, options),
|
filterQuery: getFilterQuery(filters, options),
|
||||||
dateQuery: getDateQuery(filters),
|
dateQuery: getDateQuery(filters),
|
||||||
params: {
|
filterParams: {
|
||||||
...getFilterParams(filters),
|
...getFilterParams(filters),
|
||||||
websiteId,
|
websiteId,
|
||||||
startDate: maxDate(filters.startDate, new Date(website?.resetAt)),
|
startDate: maxDate(filters.startDate, new Date(website?.resetAt)),
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ async function parseFilters(
|
||||||
: '',
|
: '',
|
||||||
filterQuery: getFilterQuery(filters, options),
|
filterQuery: getFilterQuery(filters, options),
|
||||||
dateQuery: getDateQuery(filters),
|
dateQuery: getDateQuery(filters),
|
||||||
params: {
|
filterParams: {
|
||||||
...getFilterParams(filters),
|
...getFilterParams(filters),
|
||||||
websiteId,
|
websiteId,
|
||||||
startDate: maxDate(filters.startDate, website?.resetAt),
|
startDate: maxDate(filters.startDate, website?.resetAt),
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export async function getEventDataEvents(
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { event } = filters;
|
const { event } = filters;
|
||||||
const { params } = await parseFilters(websiteId, filters);
|
const { filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
|
|
@ -43,7 +43,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by website_event.event_name, event_data.data_key, event_data.data_type, event_data.string_value
|
group by website_event.event_name, event_data.data_key, event_data.data_type, event_data.string_value
|
||||||
order by 1 asc, 2 asc, 3 asc, 5 desc
|
order by 1 asc, 2 asc, 3 asc, 5 desc
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
order by 1 asc, 2 asc
|
order by 1 asc, 2 asc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,7 +73,7 @@ async function clickhouseQuery(
|
||||||
): Promise<{ eventName: string; propertyName: string; dataType: number; total: number }[]> {
|
): Promise<{ eventName: string; propertyName: string; dataType: number; total: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { event } = filters;
|
const { event } = filters;
|
||||||
const { params } = await parseFilters(websiteId, filters);
|
const { filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
|
|
@ -92,7 +92,7 @@ async function clickhouseQuery(
|
||||||
order by 1 asc, 2 asc, 3 asc, 5 desc
|
order by 1 asc, 2 asc, 3 asc, 5 desc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,6 +110,6 @@ async function clickhouseQuery(
|
||||||
order by 1 asc, 2 asc
|
order by 1 asc, 2 asc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
import prisma from '@/lib/prisma';
|
import prisma from '@/lib/prisma';
|
||||||
import clickhouse from '@/lib/clickhouse';
|
import clickhouse from '@/lib/clickhouse';
|
||||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||||
import { QueryFilters, WebsiteEventData } from '@/lib/types';
|
import { QueryFilters } from '@/lib/types';
|
||||||
|
|
||||||
export async function getEventDataFields(
|
export async function getEventDataFields(...args: [websiteId: string, filters: QueryFilters]) {
|
||||||
...args: [websiteId: string, filters: QueryFilters]
|
|
||||||
): Promise<WebsiteEventData[]> {
|
|
||||||
return runQuery({
|
return runQuery({
|
||||||
[PRISMA]: () => relationalQuery(...args),
|
[PRISMA]: () => relationalQuery(...args),
|
||||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||||
|
|
@ -14,7 +12,7 @@ export async function getEventDataFields(
|
||||||
|
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { rawQuery, parseFilters, getDateSQL } = prisma;
|
const { rawQuery, parseFilters, getDateSQL } = prisma;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -36,7 +34,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,7 +43,7 @@ async function clickhouseQuery(
|
||||||
filters: QueryFilters,
|
filters: QueryFilters,
|
||||||
): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> {
|
): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -64,6 +62,6 @@ async function clickhouseQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ async function relationalQuery(
|
||||||
filters: QueryFilters & { propertyName?: string },
|
filters: QueryFilters & { propertyName?: string },
|
||||||
) {
|
) {
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters, {
|
||||||
columns: { propertyName: 'data_key' },
|
columns: { propertyName: 'data_key' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ async function relationalQuery(
|
||||||
order by 3 desc
|
order by 3 desc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ async function clickhouseQuery(
|
||||||
filters: QueryFilters & { propertyName?: string },
|
filters: QueryFilters & { propertyName?: string },
|
||||||
): Promise<{ eventName: string; propertyName: string; total: number }[]> {
|
): Promise<{ eventName: string; propertyName: string; total: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters, {
|
||||||
columns: { propertyName: 'data_key' },
|
columns: { propertyName: 'data_key' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -63,6 +63,6 @@ async function clickhouseQuery(
|
||||||
order by 1, 3 desc
|
order by 1, 3 desc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ export async function getEventDataStats(
|
||||||
|
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -38,7 +38,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by website_event_id, data_key
|
group by website_event_id, data_key
|
||||||
) as t
|
) as t
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,7 +47,7 @@ async function clickhouseQuery(
|
||||||
filters: QueryFilters,
|
filters: QueryFilters,
|
||||||
): Promise<{ events: number; properties: number; records: number }[]> {
|
): Promise<{ events: number; properties: number; records: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -67,6 +67,6 @@ async function clickhouseQuery(
|
||||||
group by event_id, data_key
|
group by event_id, data_key
|
||||||
) as t
|
) as t
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
import prisma from '@/lib/prisma';
|
import prisma from '@/lib/prisma';
|
||||||
import clickhouse from '@/lib/clickhouse';
|
import clickhouse from '@/lib/clickhouse';
|
||||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||||
import { QueryFilters, WebsiteEventData } from '@/lib/types';
|
import { QueryFilters } from '@/lib/types';
|
||||||
|
|
||||||
|
export interface WebsiteEventData {
|
||||||
|
value: string;
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getEventDataValues(
|
export async function getEventDataValues(
|
||||||
...args: [
|
...args: [
|
||||||
|
|
@ -20,7 +25,7 @@ async function relationalQuery(
|
||||||
filters: QueryFilters & { eventName?: string; propertyName?: string },
|
filters: QueryFilters & { eventName?: string; propertyName?: string },
|
||||||
) {
|
) {
|
||||||
const { rawQuery, parseFilters, getDateSQL } = prisma;
|
const { rawQuery, parseFilters, getDateSQL } = prisma;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -42,7 +47,7 @@ async function relationalQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,7 +56,7 @@ async function clickhouseQuery(
|
||||||
filters: QueryFilters & { eventName?: string; propertyName?: string },
|
filters: QueryFilters & { eventName?: string; propertyName?: string },
|
||||||
): Promise<{ value: string; total: number }[]> {
|
): Promise<{ value: string; total: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -70,6 +75,6 @@ async function clickhouseQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ export async function getEventMetrics(
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { timezone = 'utc', unit = 'day' } = filters;
|
const { timezone = 'utc', unit = 'day' } = filters;
|
||||||
const { rawQuery, getDateSQL, parseFilters } = prisma;
|
const { rawQuery, getDateSQL, parseFilters } = prisma;
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
|
const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.customEvent,
|
eventType: EVENT_TYPE.customEvent,
|
||||||
});
|
});
|
||||||
|
|
@ -42,7 +42,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by 1, 2
|
group by 1, 2
|
||||||
order by 2
|
order by 2
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,7 +52,7 @@ async function clickhouseQuery(
|
||||||
): Promise<{ x: string; t: string; y: number }[]> {
|
): Promise<{ x: string; t: string; y: number }[]> {
|
||||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||||
const { rawQuery, getDateSQL, parseFilters } = clickhouse;
|
const { rawQuery, getDateSQL, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.customEvent,
|
eventType: EVENT_TYPE.customEvent,
|
||||||
});
|
});
|
||||||
|
|
@ -92,5 +92,5 @@ async function clickhouseQuery(
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawQuery(sql, params);
|
return rawQuery(sql, filterParams);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export function getWebsiteEvents(
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) {
|
||||||
const { pagedRawQuery, parseFilters } = prisma;
|
const { pagedRawQuery, parseFilters } = prisma;
|
||||||
const { search } = pageParams;
|
const { search } = pageParams;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -49,14 +49,14 @@ async function relationalQuery(websiteId: string, filters: QueryFilters, pagePar
|
||||||
}
|
}
|
||||||
order by created_at desc
|
order by created_at desc
|
||||||
`,
|
`,
|
||||||
{ ...params, search: `%${search}%` },
|
{ ...filterParams, search: `%${search}%` },
|
||||||
pageParams,
|
pageParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) {
|
async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) {
|
||||||
const { pagedQuery, parseFilters } = clickhouse;
|
const { pagedQuery, parseFilters } = clickhouse;
|
||||||
const { params, dateQuery, filterQuery } = await parseFilters(websiteId, filters);
|
const { filterParams, dateQuery, filterQuery } = await parseFilters(websiteId, filters);
|
||||||
const { search } = pageParams;
|
const { search } = pageParams;
|
||||||
|
|
||||||
return pagedQuery(
|
return pagedQuery(
|
||||||
|
|
@ -86,7 +86,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters, pagePar
|
||||||
}
|
}
|
||||||
order by created_at desc
|
order by created_at desc
|
||||||
`,
|
`,
|
||||||
{ ...params, search },
|
{ ...filterParams, search },
|
||||||
pageParams,
|
pageParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export async function getChannelMetrics(...args: [websiteId: string, filters?: Q
|
||||||
|
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -27,7 +27,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by 1, 2
|
group by 1, 2
|
||||||
order by visitors desc
|
order by visitors desc
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ async function clickhouseQuery(
|
||||||
filters: QueryFilters,
|
filters: QueryFilters,
|
||||||
): Promise<{ x: string; y: number }[]> {
|
): Promise<{ x: string; y: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
const sql = `
|
const sql = `
|
||||||
select
|
select
|
||||||
|
|
@ -51,5 +51,5 @@ async function clickhouseQuery(
|
||||||
order by visitors desc
|
order by visitors desc
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return rawQuery(sql, params);
|
return rawQuery(sql, filterParams);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export async function getRealtimeActivity(...args: [websiteId: string, filters:
|
||||||
|
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -35,13 +35,13 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
order by website_event.created_at desc
|
order by website_event.created_at desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promise<{ x: number }> {
|
async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promise<{ x: number }> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { params, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
const { filterParams, filterQuery, dateQuery } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -62,6 +62,6 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promis
|
||||||
order by createdAt desc
|
order by createdAt desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
{ ...filters, ...params },
|
{ ...filters, ...filterParams },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@ export async function getWebsiteDateRange(...args: [websiteId: string]) {
|
||||||
|
|
||||||
async function relationalQuery(websiteId: string) {
|
async function relationalQuery(websiteId: string) {
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { params } = await parseFilters(websiteId, { startDate: new Date(DEFAULT_RESET_DATE) });
|
const { filterParams } = await parseFilters(websiteId, {
|
||||||
|
startDate: new Date(DEFAULT_RESET_DATE),
|
||||||
|
});
|
||||||
|
|
||||||
const result = await rawQuery(
|
const result = await rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -23,7 +25,7 @@ async function relationalQuery(websiteId: string) {
|
||||||
where website_id = {{websiteId::uuid}}
|
where website_id = {{websiteId::uuid}}
|
||||||
and created_at >= {{startDate}}
|
and created_at >= {{startDate}}
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
|
|
||||||
return result[0] ?? null;
|
return result[0] ?? null;
|
||||||
|
|
@ -31,7 +33,9 @@ async function relationalQuery(websiteId: string) {
|
||||||
|
|
||||||
async function clickhouseQuery(websiteId: string) {
|
async function clickhouseQuery(websiteId: string) {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { params } = await parseFilters(websiteId, { startDate: new Date(DEFAULT_RESET_DATE) });
|
const { filterParams } = await parseFilters(websiteId, {
|
||||||
|
startDate: new Date(DEFAULT_RESET_DATE),
|
||||||
|
});
|
||||||
|
|
||||||
const result = await rawQuery(
|
const result = await rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -42,7 +46,7 @@ async function clickhouseQuery(websiteId: string) {
|
||||||
where website_id = {websiteId:UUID}
|
where website_id = {websiteId:UUID}
|
||||||
and created_at >= {startDate:DateTime64}
|
and created_at >= {startDate:DateTime64}
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
|
|
||||||
return result[0] ?? null;
|
return result[0] ?? null;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ async function relationalQuery(
|
||||||
{ pageviews: number; visitors: number; visits: number; bounces: number; totaltime: number }[]
|
{ pageviews: number; visitors: number; visits: number; bounces: number; totaltime: number }[]
|
||||||
> {
|
> {
|
||||||
const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma;
|
const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma;
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
|
const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -52,7 +52,7 @@ async function relationalQuery(
|
||||||
group by 1, 2
|
group by 1, 2
|
||||||
) as t
|
) as t
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@ async function clickhouseQuery(
|
||||||
{ pageviews: number; visitors: number; visits: number; bounces: number; totaltime: number }[]
|
{ pageviews: number; visitors: number; visits: number; bounces: number; totaltime: number }[]
|
||||||
> {
|
> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -117,5 +117,5 @@ async function clickhouseQuery(
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawQuery(sql, params).then(result => result?.[0]);
|
return rawQuery(sql, filterParams).then(result => result?.[0]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ async function relationalQuery(
|
||||||
) {
|
) {
|
||||||
const column = FILTER_COLUMNS[type] || type;
|
const column = FILTER_COLUMNS[type] || type;
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(
|
const { filterQuery, joinSession, filterParams } = await parseFilters(
|
||||||
websiteId,
|
websiteId,
|
||||||
{
|
{
|
||||||
...filters,
|
...filters,
|
||||||
|
|
@ -82,7 +82,7 @@ async function relationalQuery(
|
||||||
limit ${limit}
|
limit ${limit}
|
||||||
offset ${offset}
|
offset ${offset}
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ async function clickhouseQuery(
|
||||||
): Promise<{ x: string; y: number }[]> {
|
): Promise<{ x: string; y: number }[]> {
|
||||||
const column = FILTER_COLUMNS[type] || type;
|
const column = FILTER_COLUMNS[type] || type;
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
|
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -180,5 +180,5 @@ async function clickhouseQuery(
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawQuery(sql, params);
|
return rawQuery(sql, filterParams);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export async function getPageviewStats(...args: [websiteId: string, filters: Que
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { timezone = 'utc', unit = 'day' } = filters;
|
const { timezone = 'utc', unit = 'day' } = filters;
|
||||||
const { getDateSQL, parseFilters, rawQuery } = prisma;
|
const { getDateSQL, parseFilters, rawQuery } = prisma;
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
|
const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -33,7 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by 1
|
group by 1
|
||||||
order by 1
|
order by 1
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ async function clickhouseQuery(
|
||||||
): Promise<{ x: string; y: number }[]> {
|
): Promise<{ x: string; y: number }[]> {
|
||||||
const { timezone = 'utc', unit = 'day' } = filters;
|
const { timezone = 'utc', unit = 'day' } = filters;
|
||||||
const { parseFilters, rawQuery, getDateSQL } = clickhouse;
|
const { parseFilters, rawQuery, getDateSQL } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -88,5 +88,5 @@ async function clickhouseQuery(
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawQuery(sql, params);
|
return rawQuery(sql, filterParams);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import clickhouse from '@/lib/clickhouse';
|
import clickhouse from '@/lib/clickhouse';
|
||||||
import { EVENT_TYPE } from '@/lib/constants';
|
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';
|
import prisma from '@/lib/prisma';
|
||||||
|
|
||||||
export interface AttributionCriteria {
|
export interface AttributionCriteria {
|
||||||
|
|
@ -38,8 +38,6 @@ async function relationalQuery(
|
||||||
const { rawQuery } = prisma;
|
const { rawQuery } = prisma;
|
||||||
const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent;
|
const eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent;
|
||||||
const column = type === 'page' ? 'url_path' : 'event_name';
|
const column = type === 'page' ? 'url_path' : 'event_name';
|
||||||
const db = getDatabaseType();
|
|
||||||
const like = db === POSTGRESQL ? 'ilike' : 'like';
|
|
||||||
|
|
||||||
function getUTMQuery(utmColumn: string) {
|
function getUTMQuery(utmColumn: string) {
|
||||||
return `
|
return `
|
||||||
|
|
@ -79,7 +77,7 @@ async function relationalQuery(
|
||||||
where website_id = {{websiteId::uuid}}
|
where website_id = {{websiteId::uuid}}
|
||||||
and created_at between {{startDate}} and {{endDate}}
|
and created_at between {{startDate}} and {{endDate}}
|
||||||
and ${column} = {{conversionStep}}
|
and ${column} = {{conversionStep}}
|
||||||
and currency ${like} {{currency}}
|
and currency = {{currency}}
|
||||||
group by 1),`;
|
group by 1),`;
|
||||||
|
|
||||||
function getModelQuery(model: string) {
|
function getModelQuery(model: string) {
|
||||||
|
|
@ -243,26 +241,57 @@ async function clickhouseQuery(
|
||||||
criteria: AttributionCriteria,
|
criteria: AttributionCriteria,
|
||||||
): Promise<AttributionResult> {
|
): Promise<AttributionResult> {
|
||||||
const { startDate, endDate, model, type, step, currency } = criteria;
|
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 eventType = type === 'page' ? EVENT_TYPE.pageView : EVENT_TYPE.customEvent;
|
||||||
const column = type === 'page' ? 'url_path' : 'event_name';
|
const column = type === 'page' ? 'url_path' : 'event_name';
|
||||||
|
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||||
|
|
||||||
function getUTMQuery(utmColumn: string) {
|
function getUTMQuery(utmColumn: string) {
|
||||||
return `
|
return `
|
||||||
select
|
select
|
||||||
we.${utmColumn} name,
|
we.${utmColumn} name,
|
||||||
${currency ? 'sum(e.value)' : 'uniqExact(we.session_id)'} value
|
${currency ? 'sum(e.value)' : 'uniqExact(we.session_id)'} value
|
||||||
from model m
|
from model m
|
||||||
join website_event we
|
join website_event we
|
||||||
on we.created_at = m.created_at
|
on we.created_at = m.created_at
|
||||||
and we.session_id = m.session_id
|
and we.session_id = m.session_id
|
||||||
${currency ? 'join events e on e.session_id = m.session_id' : ''}
|
${currency ? 'join events e on e.session_id = m.session_id' : ''}
|
||||||
where we.website_id = {websiteId:UUID}
|
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}
|
and we.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
${currency ? '' : `and we.${utmColumn} != ''`}
|
${filterQuery}
|
||||||
group by 1
|
group by e.session_id)
|
||||||
order by 2 desc
|
`;
|
||||||
limit 20`;
|
}
|
||||||
|
|
||||||
|
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 (
|
const eventQuery = `WITH events AS (
|
||||||
|
|
@ -288,29 +317,6 @@ async function clickhouseQuery(
|
||||||
and currency = {currency:String}
|
and currency = {currency:String}
|
||||||
group by 1),`;
|
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<
|
const referrerRes = await rawQuery<
|
||||||
{
|
{
|
||||||
name: string;
|
name: string;
|
||||||
|
|
@ -339,7 +345,7 @@ async function clickhouseQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 20
|
limit 20
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||||
);
|
);
|
||||||
|
|
||||||
const paidAdsres = await rawQuery<
|
const paidAdsres = await rawQuery<
|
||||||
|
|
@ -370,7 +376,7 @@ async function clickhouseQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 20
|
limit 20
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||||
);
|
);
|
||||||
|
|
||||||
const sourceRes = await rawQuery<
|
const sourceRes = await rawQuery<
|
||||||
|
|
@ -384,7 +390,7 @@ async function clickhouseQuery(
|
||||||
${getModelQuery(model)}
|
${getModelQuery(model)}
|
||||||
${getUTMQuery('utm_source')}
|
${getUTMQuery('utm_source')}
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||||
);
|
);
|
||||||
|
|
||||||
const mediumRes = await rawQuery<
|
const mediumRes = await rawQuery<
|
||||||
|
|
@ -398,7 +404,7 @@ async function clickhouseQuery(
|
||||||
${getModelQuery(model)}
|
${getModelQuery(model)}
|
||||||
${getUTMQuery('utm_medium')}
|
${getUTMQuery('utm_medium')}
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||||
);
|
);
|
||||||
|
|
||||||
const campaignRes = await rawQuery<
|
const campaignRes = await rawQuery<
|
||||||
|
|
@ -412,7 +418,7 @@ async function clickhouseQuery(
|
||||||
${getModelQuery(model)}
|
${getModelQuery(model)}
|
||||||
${getUTMQuery('utm_campaign')}
|
${getUTMQuery('utm_campaign')}
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||||
);
|
);
|
||||||
|
|
||||||
const contentRes = await rawQuery<
|
const contentRes = await rawQuery<
|
||||||
|
|
@ -426,7 +432,7 @@ async function clickhouseQuery(
|
||||||
${getModelQuery(model)}
|
${getModelQuery(model)}
|
||||||
${getUTMQuery('utm_content')}
|
${getUTMQuery('utm_content')}
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
{ ...filterParams, websiteId, startDate, endDate, conversionStep: step, eventType, currency },
|
||||||
);
|
);
|
||||||
|
|
||||||
const termRes = await rawQuery<
|
const termRes = await rawQuery<
|
||||||
|
|
@ -440,7 +446,7 @@ async function clickhouseQuery(
|
||||||
${getModelQuery(model)}
|
${getModelQuery(model)}
|
||||||
${getUTMQuery('utm_term')}
|
${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 }>(
|
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 created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
and ${column} = {conversionStep:String}
|
and ${column} = {conversionStep:String}
|
||||||
and event_type = {eventType:UInt32}
|
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]);
|
).then(result => result?.[0]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ async function relationalQuery(
|
||||||
}[]
|
}[]
|
||||||
> {
|
> {
|
||||||
const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma;
|
const { getTimestampDiffSQL, parseFilters, rawQuery } = prisma;
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(
|
const { filterQuery, joinSession, filterParams } = await parseFilters(
|
||||||
websiteId,
|
websiteId,
|
||||||
{
|
{
|
||||||
...filters,
|
...filters,
|
||||||
|
|
@ -65,7 +65,7 @@ async function relationalQuery(
|
||||||
order by 1 desc, 2 desc
|
order by 1 desc, 2 desc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ async function clickhouseQuery(
|
||||||
}[]
|
}[]
|
||||||
> {
|
> {
|
||||||
const { parseFilters, rawQuery } = clickhouse;
|
const { parseFilters, rawQuery } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -114,7 +114,7 @@ async function clickhouseQuery(
|
||||||
order by 1 desc, 2 desc
|
order by 1 desc, 2 desc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,11 +121,12 @@ async function clickhouseQuery(
|
||||||
}[]
|
}[]
|
||||||
> {
|
> {
|
||||||
const { windowMinutes, startDate, endDate, steps } = criteria;
|
const { windowMinutes, startDate, endDate, steps } = criteria;
|
||||||
const { rawQuery } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { levelOneQuery, levelQuery, sumQuery, stepFilterQuery, params } = getFunnelQuery(
|
const { levelOneQuery, levelQuery, sumQuery, stepFilterQuery, params } = getFunnelQuery(
|
||||||
steps,
|
steps,
|
||||||
windowMinutes,
|
windowMinutes,
|
||||||
);
|
);
|
||||||
|
const { filterQuery, filterParams: filterParams } = await parseFilters(websiteId, criteria);
|
||||||
|
|
||||||
function getFunnelQuery(
|
function getFunnelQuery(
|
||||||
steps: { type: string; value: string }[],
|
steps: { type: string; value: string }[],
|
||||||
|
|
@ -200,6 +201,7 @@ async function clickhouseQuery(
|
||||||
where (${stepFilterQuery})
|
where (${stepFilterQuery})
|
||||||
and website_id = {websiteId:UUID}
|
and website_id = {websiteId:UUID}
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
|
${filterQuery}
|
||||||
),
|
),
|
||||||
${levelOneQuery}
|
${levelOneQuery}
|
||||||
${levelQuery}
|
${levelQuery}
|
||||||
|
|
@ -213,6 +215,7 @@ async function clickhouseQuery(
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
...params,
|
...params,
|
||||||
|
...filterParams,
|
||||||
},
|
},
|
||||||
).then(formatResults(steps));
|
).then(formatResults(steps));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ export async function getGoal(...args: [websiteId: string, criteria: GoalCriteri
|
||||||
async function relationalQuery(websiteId: string, criteria: GoalCriteria) {
|
async function relationalQuery(websiteId: string, criteria: GoalCriteria) {
|
||||||
const { type, value } = criteria;
|
const { type, value } = criteria;
|
||||||
const { rawQuery, parseFilters } = prisma;
|
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 isPage = type === 'page';
|
||||||
const column = isPage ? 'url_path' : 'event_name';
|
const column = isPage ? 'url_path' : 'event_name';
|
||||||
const eventType = isPage ? 1 : 2;
|
const eventType = isPage ? 1 : 2;
|
||||||
|
|
@ -43,14 +43,14 @@ async function relationalQuery(websiteId: string, criteria: GoalCriteria) {
|
||||||
${dateQuery}
|
${dateQuery}
|
||||||
${filterQuery}
|
${filterQuery}
|
||||||
`,
|
`,
|
||||||
{ ...params, value },
|
{ ...filterParams, value },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) {
|
async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) {
|
||||||
const { type, value } = criteria;
|
const { type, value } = criteria;
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
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 isPage = type === 'page';
|
||||||
const column = isPage ? 'url_path' : 'event_name';
|
const column = isPage ? 'url_path' : 'event_name';
|
||||||
const eventType = isPage ? 1 : 2;
|
const eventType = isPage ? 1 : 2;
|
||||||
|
|
@ -71,6 +71,6 @@ async function clickhouseQuery(websiteId: string, criteria: GoalCriteria) {
|
||||||
${dateQuery}
|
${dateQuery}
|
||||||
${filterQuery}
|
${filterQuery}
|
||||||
`,
|
`,
|
||||||
{ ...params, value },
|
{ ...filterParams, value },
|
||||||
).then(results => results?.[0]);
|
).then(results => results?.[0]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ async function relationalQuery(
|
||||||
sequenceQuery,
|
sequenceQuery,
|
||||||
startStepQuery,
|
startStepQuery,
|
||||||
endStepQuery,
|
endStepQuery,
|
||||||
params,
|
filterParams: params,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,7 +152,7 @@ async function clickhouseQuery(
|
||||||
},
|
},
|
||||||
): Promise<JourneyResult[]> {
|
): Promise<JourneyResult[]> {
|
||||||
const { startDate, endDate, steps, startStep, endStep } = filters;
|
const { startDate, endDate, steps, startStep, endStep } = filters;
|
||||||
const { rawQuery } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { sequenceQuery, startStepQuery, endStepQuery, params } = getJourneyQuery(
|
const { sequenceQuery, startStepQuery, endStepQuery, params } = getJourneyQuery(
|
||||||
steps,
|
steps,
|
||||||
startStep,
|
startStep,
|
||||||
|
|
@ -218,10 +218,12 @@ async function clickhouseQuery(
|
||||||
sequenceQuery,
|
sequenceQuery,
|
||||||
startStepQuery,
|
startStepQuery,
|
||||||
endStepQuery,
|
endStepQuery,
|
||||||
params,
|
filterParams: params,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { filterQuery, filterParams: filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
WITH events AS (
|
WITH events AS (
|
||||||
|
|
@ -231,6 +233,7 @@ async function clickhouseQuery(
|
||||||
row_number() OVER (PARTITION BY visit_id ORDER BY created_at) AS event_number
|
row_number() OVER (PARTITION BY visit_id ORDER BY created_at) AS event_number
|
||||||
from umami.website_event
|
from umami.website_event
|
||||||
where website_id = {websiteId:UUID}
|
where website_id = {websiteId:UUID}
|
||||||
|
${filterQuery}
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}),
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}),
|
||||||
${sequenceQuery}
|
${sequenceQuery}
|
||||||
select *
|
select *
|
||||||
|
|
@ -246,6 +249,7 @@ async function clickhouseQuery(
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
...params,
|
...params,
|
||||||
|
...filterParams,
|
||||||
},
|
},
|
||||||
).then(parseResult);
|
).then(parseResult);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,11 @@ async function relationalQuery(
|
||||||
criteria: RetentionCriteria,
|
criteria: RetentionCriteria,
|
||||||
): Promise<RetentionResult[]> {
|
): Promise<RetentionResult[]> {
|
||||||
const { startDate, endDate, timezone } = criteria;
|
const { startDate, endDate, timezone } = criteria;
|
||||||
const { getDateSQL, getDayDiffQuery, getCastColumnQuery, rawQuery } = prisma;
|
const { getDateSQL, getDayDiffQuery, getCastColumnQuery, rawQuery, parseFilters } = prisma;
|
||||||
const unit = 'day';
|
const unit = 'day';
|
||||||
|
|
||||||
|
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
WITH cohort_items AS (
|
WITH cohort_items AS (
|
||||||
|
|
@ -49,6 +51,7 @@ async function relationalQuery(
|
||||||
on w.session_id = c.session_id
|
on w.session_id = c.session_id
|
||||||
where website_id = {{websiteId::uuid}}
|
where website_id = {{websiteId::uuid}}
|
||||||
and created_at between {{startDate}} and {{endDate}}
|
and created_at between {{startDate}} and {{endDate}}
|
||||||
|
${filterQuery}
|
||||||
),
|
),
|
||||||
cohort_size as (
|
cohort_size as (
|
||||||
select cohort_date,
|
select cohort_date,
|
||||||
|
|
@ -82,6 +85,7 @@ async function relationalQuery(
|
||||||
websiteId,
|
websiteId,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
|
...filterParams,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -91,9 +95,11 @@ async function clickhouseQuery(
|
||||||
criteria: RetentionCriteria,
|
criteria: RetentionCriteria,
|
||||||
): Promise<RetentionResult[]> {
|
): Promise<RetentionResult[]> {
|
||||||
const { startDate, endDate, timezone } = criteria;
|
const { startDate, endDate, timezone } = criteria;
|
||||||
const { getDateSQL, rawQuery } = clickhouse;
|
const { getDateSQL, rawQuery, parseFilters } = clickhouse;
|
||||||
const unit = 'day';
|
const unit = 'day';
|
||||||
|
|
||||||
|
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
WITH cohort_items AS (
|
WITH cohort_items AS (
|
||||||
|
|
@ -114,6 +120,7 @@ async function clickhouseQuery(
|
||||||
on w.session_id = c.session_id
|
on w.session_id = c.session_id
|
||||||
where website_id = {websiteId:UUID}
|
where website_id = {websiteId:UUID}
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
|
${filterQuery}
|
||||||
),
|
),
|
||||||
cohort_size as (
|
cohort_size as (
|
||||||
select cohort_date,
|
select cohort_date,
|
||||||
|
|
@ -147,6 +154,7 @@ async function clickhouseQuery(
|
||||||
websiteId,
|
websiteId,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
|
...filterParams,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ export async function getUTM(...args: [websiteId: string, criteria: UTMCriteria]
|
||||||
|
|
||||||
async function relationalQuery(websiteId: string, criteria: UTMCriteria) {
|
async function relationalQuery(websiteId: string, criteria: UTMCriteria) {
|
||||||
const { startDate, endDate } = criteria;
|
const { startDate, endDate } = criteria;
|
||||||
const { rawQuery } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
|
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -26,9 +27,11 @@ async function relationalQuery(websiteId: string, criteria: UTMCriteria) {
|
||||||
and created_at between {{startDate}} and {{endDate}}
|
and created_at between {{startDate}} and {{endDate}}
|
||||||
and coalesce(url_query, '') != ''
|
and coalesce(url_query, '') != ''
|
||||||
and event_type = 1
|
and event_type = 1
|
||||||
|
${filterQuery}
|
||||||
group by 1
|
group by 1
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
|
...filterParams,
|
||||||
websiteId,
|
websiteId,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
|
|
@ -38,7 +41,8 @@ async function relationalQuery(websiteId: string, criteria: UTMCriteria) {
|
||||||
|
|
||||||
async function clickhouseQuery(websiteId: string, criteria: UTMCriteria) {
|
async function clickhouseQuery(websiteId: string, criteria: UTMCriteria) {
|
||||||
const { startDate, endDate } = criteria;
|
const { startDate, endDate } = criteria;
|
||||||
const { rawQuery } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
|
const { filterQuery, filterParams } = await parseFilters(websiteId, criteria);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -48,9 +52,11 @@ async function clickhouseQuery(websiteId: string, criteria: UTMCriteria) {
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
and url_query != ''
|
and url_query != ''
|
||||||
and event_type = 1
|
and event_type = 1
|
||||||
|
${filterQuery}
|
||||||
group by 1
|
group by 1
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
|
...filterParams,
|
||||||
websiteId,
|
websiteId,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import prisma from '@/lib/prisma';
|
import prisma from '@/lib/prisma';
|
||||||
import clickhouse from '@/lib/clickhouse';
|
import clickhouse from '@/lib/clickhouse';
|
||||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||||
import { QueryFilters, WebsiteEventData } from '@/lib/types';
|
import { QueryFilters } from '@/lib/types';
|
||||||
|
|
||||||
export async function getSessionDataProperties(
|
export async function getSessionDataProperties(
|
||||||
...args: [websiteId: string, filters: QueryFilters & { propertyName?: string }]
|
...args: [websiteId: string, filters: QueryFilters & { propertyName?: string }]
|
||||||
): Promise<WebsiteEventData[]> {
|
) {
|
||||||
return runQuery({
|
return runQuery({
|
||||||
[PRISMA]: () => relationalQuery(...args),
|
[PRISMA]: () => relationalQuery(...args),
|
||||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||||
|
|
@ -17,7 +17,7 @@ async function relationalQuery(
|
||||||
filters: QueryFilters & { propertyName?: string },
|
filters: QueryFilters & { propertyName?: string },
|
||||||
) {
|
) {
|
||||||
const { rawQuery, parseFilters } = prisma;
|
const { rawQuery, parseFilters } = prisma;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters, {
|
||||||
columns: { propertyName: 'data_key' },
|
columns: { propertyName: 'data_key' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ async function relationalQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,7 +45,7 @@ async function clickhouseQuery(
|
||||||
filters: QueryFilters & { propertyName?: string },
|
filters: QueryFilters & { propertyName?: string },
|
||||||
): Promise<{ propertyName: string; total: number }[]> {
|
): Promise<{ propertyName: string; total: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters, {
|
||||||
columns: { propertyName: 'data_key' },
|
columns: { propertyName: 'data_key' },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -65,6 +65,6 @@ async function clickhouseQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 500
|
limit 500
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ async function relationalQuery(
|
||||||
filters: QueryFilters & { propertyName?: string },
|
filters: QueryFilters & { propertyName?: string },
|
||||||
) {
|
) {
|
||||||
const { rawQuery, parseFilters, getDateSQL } = prisma;
|
const { rawQuery, parseFilters, getDateSQL } = prisma;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -39,7 +39,7 @@ async function relationalQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ async function clickhouseQuery(
|
||||||
filters: QueryFilters & { propertyName?: string },
|
filters: QueryFilters & { propertyName?: string },
|
||||||
): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> {
|
): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, filters);
|
const { filterQuery, filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -68,6 +68,6 @@ async function clickhouseQuery(
|
||||||
order by 2 desc
|
order by 2 desc
|
||||||
limit 100
|
limit 100
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ async function relationalQuery(
|
||||||
) {
|
) {
|
||||||
const column = FILTER_COLUMNS[type] || type;
|
const column = FILTER_COLUMNS[type] || type;
|
||||||
const { parseFilters, rawQuery } = prisma;
|
const { parseFilters, rawQuery } = prisma;
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(
|
const { filterQuery, joinSession, filterParams } = await parseFilters(
|
||||||
websiteId,
|
websiteId,
|
||||||
{
|
{
|
||||||
...filters,
|
...filters,
|
||||||
|
|
@ -58,7 +58,7 @@ async function relationalQuery(
|
||||||
limit ${limit}
|
limit ${limit}
|
||||||
offset ${offset}
|
offset ${offset}
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ async function clickhouseQuery(
|
||||||
): Promise<{ x: string; y: number }[]> {
|
): Promise<{ x: string; y: number }[]> {
|
||||||
const column = FILTER_COLUMNS[type] || type;
|
const column = FILTER_COLUMNS[type] || type;
|
||||||
const { parseFilters, rawQuery } = clickhouse;
|
const { parseFilters, rawQuery } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -115,5 +115,5 @@ async function clickhouseQuery(
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawQuery(sql, params);
|
return rawQuery(sql, filterParams);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export async function getSessionStats(...args: [websiteId: string, filters: Quer
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { timezone = 'utc', unit = 'day' } = filters;
|
const { timezone = 'utc', unit = 'day' } = filters;
|
||||||
const { getDateSQL, parseFilters, rawQuery } = prisma;
|
const { getDateSQL, parseFilters, rawQuery } = prisma;
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
|
const { filterQuery, joinSession, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -33,7 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by 1
|
group by 1
|
||||||
order by 1
|
order by 1
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ async function clickhouseQuery(
|
||||||
): Promise<{ x: string; y: number }[]> {
|
): Promise<{ x: string; y: number }[]> {
|
||||||
const { timezone = 'utc', unit = 'day' } = filters;
|
const { timezone = 'utc', unit = 'day' } = filters;
|
||||||
const { parseFilters, rawQuery, getDateSQL } = clickhouse;
|
const { parseFilters, rawQuery, getDateSQL } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
eventType: EVENT_TYPE.pageView,
|
eventType: EVENT_TYPE.pageView,
|
||||||
});
|
});
|
||||||
|
|
@ -88,5 +88,5 @@ async function clickhouseQuery(
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rawQuery(sql, params);
|
return rawQuery(sql, filterParams);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ async function relationalQuery(
|
||||||
{ pageviews: number; visitors: number; visits: number; countries: number; events: number }[]
|
{ pageviews: number; visitors: number; visits: number; countries: number; events: number }[]
|
||||||
> {
|
> {
|
||||||
const { parseFilters, rawQuery } = prisma;
|
const { parseFilters, rawQuery } = prisma;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -39,7 +39,7 @@ async function relationalQuery(
|
||||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||||
${filterQuery}
|
${filterQuery}
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ async function clickhouseQuery(
|
||||||
{ pageviews: number; visitors: number; visits: number; countries: number; events: number }[]
|
{ pageviews: number; visitors: number; visits: number; countries: number; events: number }[]
|
||||||
> {
|
> {
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -67,6 +67,6 @@ async function clickhouseQuery(
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
${filterQuery}
|
${filterQuery}
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export async function getWebsiteSessions(
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters, pageParams: PageParams) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters, pageParams: PageParams) {
|
||||||
const { pagedRawQuery, parseFilters } = prisma;
|
const { pagedRawQuery, parseFilters } = prisma;
|
||||||
const { search } = pageParams;
|
const { search } = pageParams;
|
||||||
const { filterQuery, params } = await parseFilters(websiteId, {
|
const { filterQuery, filterParams } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -68,14 +68,14 @@ async function relationalQuery(websiteId: string, filters: QueryFilters, pagePar
|
||||||
session.city
|
session.city
|
||||||
order by max(website_event.created_at) desc
|
order by max(website_event.created_at) desc
|
||||||
`,
|
`,
|
||||||
{ ...params, search: `%${search}%` },
|
{ ...filterParams, search: `%${search}%` },
|
||||||
pageParams,
|
pageParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) {
|
async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) {
|
||||||
const { pagedQuery, parseFilters, getDateStringSQL } = clickhouse;
|
const { pagedQuery, parseFilters, getDateStringSQL } = clickhouse;
|
||||||
const { params, dateQuery, filterQuery } = await parseFilters(websiteId, filters);
|
const { filterParams, dateQuery, filterQuery } = await parseFilters(websiteId, filters);
|
||||||
const { search } = pageParams;
|
const { search } = pageParams;
|
||||||
|
|
||||||
return pagedQuery(
|
return pagedQuery(
|
||||||
|
|
@ -113,7 +113,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters, pagePar
|
||||||
group by session_id, website_id, hostname, browser, os, device, screen, language, country, region, city
|
group by session_id, website_id, hostname, browser, os, device, screen, language, country, region, city
|
||||||
order by lastAt desc
|
order by lastAt desc
|
||||||
`,
|
`,
|
||||||
{ ...params, search },
|
{ ...filterParams, search },
|
||||||
pageParams,
|
pageParams,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export async function getWebsiteSessionsWeekly(
|
||||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { timezone = 'utc' } = filters;
|
const { timezone = 'utc' } = filters;
|
||||||
const { rawQuery, getDateWeeklySQL, parseFilters } = prisma;
|
const { rawQuery, getDateWeeklySQL, parseFilters } = prisma;
|
||||||
const { params } = await parseFilters(websiteId, filters);
|
const { filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -28,14 +28,14 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by time
|
group by time
|
||||||
order by 2
|
order by 2
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
).then(formatResults);
|
).then(formatResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
|
async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
|
||||||
const { timezone = 'utc' } = filters;
|
const { timezone = 'utc' } = filters;
|
||||||
const { rawQuery, parseFilters } = clickhouse;
|
const { rawQuery, parseFilters } = clickhouse;
|
||||||
const { params } = await parseFilters(websiteId, filters);
|
const { filterParams } = await parseFilters(websiteId, filters);
|
||||||
|
|
||||||
return rawQuery(
|
return rawQuery(
|
||||||
`
|
`
|
||||||
|
|
@ -48,7 +48,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
|
||||||
group by time
|
group by time
|
||||||
order by time
|
order by time
|
||||||
`,
|
`,
|
||||||
params,
|
filterParams,
|
||||||
).then(formatResults);
|
).then(formatResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue