Updated pixel/link endpoints. Added name to rawQuery.

This commit is contained in:
Mike Cao 2025-09-30 16:11:21 -07:00
parent b9fbbc6453
commit 8a977b0164
18 changed files with 913 additions and 810 deletions

View file

@ -74,18 +74,18 @@
"@date-fns/utc": "^1.2.0", "@date-fns/utc": "^1.2.0",
"@dicebear/collection": "^9.2.3", "@dicebear/collection": "^9.2.3",
"@dicebear/core": "^9.2.3", "@dicebear/core": "^9.2.3",
"@fontsource/inter": "^5.2.6", "@fontsource/inter": "^5.2.8",
"@hello-pangea/dnd": "^17.0.0", "@hello-pangea/dnd": "^17.0.0",
"@prisma/adapter-pg": "^6.16.0", "@prisma/adapter-pg": "^6.16.3",
"@prisma/client": "^6.16.0", "@prisma/client": "^6.16.3",
"@prisma/extension-read-replicas": "^0.4.1", "@prisma/extension-read-replicas": "^0.4.1",
"@react-spring/web": "^10.0.1", "@react-spring/web": "^10.0.3",
"@svgr/cli": "^8.1.0", "@svgr/cli": "^8.1.0",
"@tanstack/react-query": "^5.85.5", "@tanstack/react-query": "^5.90.2",
"@umami/react-zen": "^0.187.0", "@umami/react-zen": "^0.187.0",
"@umami/redis-client": "^0.29.0", "@umami/redis-client": "^0.29.0",
"bcryptjs": "^3.0.2", "bcryptjs": "^3.0.2",
"chalk": "^5.6.0", "chalk": "^5.6.2",
"chart.js": "^4.5.0", "chart.js": "^4.5.0",
"chartjs-adapter-date-fns": "^3.0.0", "chartjs-adapter-date-fns": "^3.0.0",
"classnames": "^2.3.1", "classnames": "^2.3.1",
@ -94,19 +94,19 @@
"cross-spawn": "^7.0.3", "cross-spawn": "^7.0.3",
"date-fns": "^2.23.0", "date-fns": "^2.23.0",
"date-fns-tz": "^1.1.4", "date-fns-tz": "^1.1.4",
"debug": "^4.3.4", "debug": "^4.4.3",
"del": "^6.0.0", "del": "^6.0.0",
"detect-browser": "^5.2.0", "detect-browser": "^5.2.0",
"dotenv": "^17.2.1", "dotenv": "^17.2.3",
"esbuild": "^0.25.9", "esbuild": "^0.25.10",
"eslint-plugin-promise": "^6.1.1", "eslint-plugin-promise": "^6.1.1",
"fs-extra": "^11.3.1", "fs-extra": "^11.3.2",
"immer": "^10.1.1", "immer": "^10.1.3",
"ipaddr.js": "^2.0.1", "ipaddr.js": "^2.0.1",
"is-ci": "^3.0.1", "is-ci": "^3.0.1",
"is-docker": "^3.0.0", "is-docker": "^3.0.0",
"is-localhost-ip": "^2.0.0", "is-localhost-ip": "^2.0.0",
"isbot": "^5.1.30", "isbot": "^5.1.31",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"jszip": "^3.10.1", "jszip": "^3.10.1",
"kafkajs": "^2.1.0", "kafkajs": "^2.1.0",
@ -132,12 +132,12 @@
"thenby": "^1.3.4", "thenby": "^1.3.4",
"ua-parser-js": "^2.0.5", "ua-parser-js": "^2.0.5",
"uuid": "^11.1.0", "uuid": "^11.1.0",
"zod": "^4.1.5", "zod": "^4.1.11",
"zustand": "^5.0.8" "zustand": "^5.0.8"
}, },
"devDependencies": { "devDependencies": {
"@formatjs/cli": "^4.2.29", "@formatjs/cli": "^4.2.29",
"@netlify/plugin-nextjs": "^5.12.1", "@netlify/plugin-nextjs": "^5.13.3",
"@rollup/plugin-alias": "^5.0.0", "@rollup/plugin-alias": "^5.0.0",
"@rollup/plugin-commonjs": "^25.0.4", "@rollup/plugin-commonjs": "^25.0.4",
"@rollup/plugin-json": "^6.0.0", "@rollup/plugin-json": "^6.0.0",
@ -146,18 +146,18 @@
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^12.1.4", "@rollup/plugin-typescript": "^12.1.4",
"@types/jest": "^30.0.0", "@types/jest": "^30.0.0",
"@types/node": "^24.3.0", "@types/node": "^24.6.0",
"@types/react": "^19.1.12", "@types/react": "^19.1.16",
"@types/react-dom": "^19.1.8", "@types/react-dom": "^19.1.9",
"@types/react-window": "^1.8.8", "@types/react-window": "^1.8.8",
"@typescript-eslint/eslint-plugin": "^8.41.0", "@typescript-eslint/eslint-plugin": "^8.45.0",
"@typescript-eslint/parser": "^8.41.0", "@typescript-eslint/parser": "^8.45.0",
"@umami/prisma-client": "^0.20.0", "@umami/prisma-client": "^0.20.0",
"babel-plugin-react-compiler": "19.1.0-rc.2", "babel-plugin-react-compiler": "19.1.0-rc.2",
"cross-env": "^10.0.0", "cross-env": "^10.1.0",
"cypress": "^13.6.6", "cypress": "^13.6.6",
"eslint": "^8.33.0", "eslint": "^8.33.0",
"eslint-config-next": "^14.2.32", "eslint-config-next": "^14.2.33",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-css-modules": "^2.12.0", "eslint-plugin-css-modules": "^2.12.0",
@ -168,18 +168,18 @@
"extract-react-intl-messages": "^4.1.1", "extract-react-intl-messages": "^4.1.1",
"husky": "^9.1.7", "husky": "^9.1.7",
"jest": "^29.7.0", "jest": "^29.7.0",
"lint-staged": "^16.1.5", "lint-staged": "^16.2.3",
"postcss": "^8.5.6", "postcss": "^8.5.6",
"postcss-flexbugs-fixes": "^5.0.2", "postcss-flexbugs-fixes": "^5.0.2",
"postcss-import": "^15.1.0", "postcss-import": "^15.1.0",
"postcss-preset-env": "7.8.3", "postcss-preset-env": "7.8.3",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"prompts": "2.4.2", "prompts": "2.4.2",
"rollup": "^4.49.0", "rollup": "^4.52.3",
"rollup-plugin-copy": "^3.4.0", "rollup-plugin-copy": "^3.4.0",
"rollup-plugin-delete": "^3.0.1", "rollup-plugin-delete": "^3.0.1",
"rollup-plugin-dts": "^6.2.3", "rollup-plugin-dts": "^6.2.3",
"rollup-plugin-node-externals": "^8.1.0", "rollup-plugin-node-externals": "^8.1.1",
"rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "^4.0.2", "rollup-plugin-postcss": "^4.0.2",
"stylelint": "^15.10.1", "stylelint": "^15.10.1",
@ -190,6 +190,6 @@
"ts-jest": "^29.4.0", "ts-jest": "^29.4.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tsup": "^8.5.0", "tsup": "^8.5.0",
"typescript": "^5.9.2" "typescript": "^5.9.3"
} }
} }

1465
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,10 @@
export const dynamic = 'force-dynamic';
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import { notFound } from '@/lib/response'; import { notFound } from '@/lib/response';
import redis from '@/lib/redis';
import { findPixel } from '@/queries/prisma'; import { findPixel } from '@/queries/prisma';
import { Pixel } from '@/generated/prisma/client';
import { POST } from '@/app/api/send/route'; import { POST } from '@/app/api/send/route';
const image = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw', 'base64'); const image = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw', 'base64');
@ -8,14 +12,34 @@ const image = Buffer.from('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICR
export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) { export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params; const { slug } = await params;
const pixel = await findPixel({ let pixel: Pixel;
where: {
slug,
},
});
if (!pixel) { if (redis.enabled) {
return notFound(); pixel = await redis.client.fetch(
`pixel:${slug}`,
async () => {
return findPixel({
where: {
slug,
},
});
},
86400,
);
if (!pixel) {
return notFound();
}
} else {
pixel = await findPixel({
where: {
slug,
},
});
if (!pixel) {
return notFound();
}
} }
const payload = { const payload = {
@ -23,7 +47,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug
payload: { payload: {
pixel: pixel.id, pixel: pixel.id,
url: request.url, url: request.url,
referrer: request.referrer, referrer: request.headers.get('referer'),
}, },
}; };
@ -33,13 +57,12 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug
body: JSON.stringify(payload), body: JSON.stringify(payload),
}); });
const res = await POST(req); await POST(req);
return new NextResponse(image, { return new NextResponse(image, {
headers: { headers: {
'Content-Type': 'image/gif', 'Content-Type': 'image/gif',
'Content-Length': image.length.toString(), 'Content-Length': image.length.toString(),
'x-umami-collect': JSON.stringify(res),
}, },
}); });
} }

View file

@ -1,19 +1,43 @@
export const dynamic = 'force-dynamic';
import { NextResponse } from 'next/server'; import { NextResponse } from 'next/server';
import { notFound } from '@/lib/response'; import { notFound } from '@/lib/response';
import { findLink } from '@/queries/prisma'; import { findLink } from '@/queries/prisma';
import { POST } from '@/app/api/send/route'; import { POST } from '@/app/api/send/route';
import { Link } from '@/generated/prisma/client';
import redis from '@/lib/redis';
export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) { export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params; const { slug } = await params;
const link = await findLink({ let link: Link;
where: {
slug,
},
});
if (!link) { if (redis.enabled) {
return notFound(); link = await redis.client.fetch(
`link:${slug}`,
async () => {
return findLink({
where: {
slug,
},
});
},
86400,
);
if (!link) {
return notFound();
}
} else {
link = await findLink({
where: {
slug,
},
});
if (!link) {
return notFound();
}
} }
const payload = { const payload = {
@ -21,7 +45,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug
payload: { payload: {
link: link.id, link: link.id,
url: request.url, url: request.url,
referrer: request.referrer, referrer: request.headers.get('referer'),
}, },
}; };

View file

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

View file

@ -1,5 +1,5 @@
import { canViewWebsite } from '@/permissions'; import { canViewWebsite } from '@/permissions';
import { EVENT_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import { getQueryFilters, parseRequest } from '@/lib/request'; import { getQueryFilters, parseRequest } from '@/lib/request';
import { badRequest, json, unauthorized } from '@/lib/response'; import { badRequest, json, unauthorized } from '@/lib/response';
import { import {
@ -50,21 +50,21 @@ export async function GET(
} }
if (EVENT_COLUMNS.includes(type)) { if (EVENT_COLUMNS.includes(type)) {
let data; const column = FILTER_COLUMNS[type] || type;
if (type === 'event') { if (column === 'event_name') {
data = await getEventMetrics(websiteId, { type, limit, offset }, filters); filters.eventType = EVENT_TYPE.customEvent;
} else {
data = await getPageviewMetrics(websiteId, { type, limit, offset }, filters);
} }
return json(data); if (type === 'event') {
return json(await getEventMetrics(websiteId, { type, limit, offset }, filters));
} else {
return json(await getPageviewMetrics(websiteId, { type, limit, offset }, filters));
}
} }
if (type === 'channel') { if (type === 'channel') {
const data = await getChannelMetrics(websiteId, filters); return json(await getChannelMetrics(websiteId, filters));
return json(data);
} }
return badRequest(); return badRequest();

View file

@ -206,9 +206,10 @@ async function pagedRawQuery(
async function rawQuery<T = unknown>( async function rawQuery<T = unknown>(
query: string, query: string,
params: Record<string, unknown> = {}, params: Record<string, unknown> = {},
name?: string,
): Promise<T> { ): Promise<T> {
if (process.env.LOG_QUERY) { if (process.env.LOG_QUERY) {
log({ query, params }); log({ query, params, name });
} }
await connect(); await connect();

View file

@ -164,10 +164,11 @@ function parseFilters(filters: Record<string, any>, options?: QueryOptions) {
}; };
} }
async function rawQuery(sql: string, data: object): Promise<any> { async function rawQuery(sql: string, data: Record<string, any>, name?: string): Promise<any> {
if (process.env.LOG_QUERY) { if (process.env.LOG_QUERY) {
log('QUERY:\n', sql); log('QUERY:\n', sql);
log('PARAMETERS:\n', data); log('PARAMETERS:\n', data);
log('NAME:\n', name);
} }
const params = []; const params = [];
const schema = getSchema(); const schema = getSchema();

View file

@ -4,6 +4,8 @@ import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getEventMetrics';
export interface EventMetricParameters { export interface EventMetricParameters {
type: string; type: string;
limit?: string; limit?: string;
@ -58,6 +60,7 @@ async function relationalQuery(
offset ${offset} offset ${offset}
`, `,
{ ...queryParams, ...parameters }, { ...queryParams, ...parameters },
FUNCTION_NAME,
); );
} }
@ -89,5 +92,6 @@ async function clickhouseQuery(
offset ${offset} offset ${offset}
`, `,
{ ...queryParams, ...parameters }, { ...queryParams, ...parameters },
FUNCTION_NAME,
); );
} }

View file

@ -1,5 +1,5 @@
import { uuid } from '@/lib/crypto'; import { uuid } from '@/lib/crypto';
import { EVENT_NAME_LENGTH, URL_LENGTH, EVENT_TYPE, PAGE_TITLE_LENGTH } from '@/lib/constants'; import { EVENT_NAME_LENGTH, URL_LENGTH, PAGE_TITLE_LENGTH } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import clickhouse from '@/lib/clickhouse'; import clickhouse from '@/lib/clickhouse';
import kafka from '@/lib/kafka'; import kafka from '@/lib/kafka';
@ -66,10 +66,9 @@ async function relationalQuery({
websiteId, websiteId,
sessionId, sessionId,
visitId, visitId,
createdAt,
eventType, eventType,
createdAt,
pageTitle, pageTitle,
tag,
hostname, hostname,
urlPath, urlPath,
urlQuery, urlQuery,
@ -78,6 +77,7 @@ async function relationalQuery({
referrerDomain, referrerDomain,
eventName, eventName,
eventData, eventData,
tag,
utmSource, utmSource,
utmMedium, utmMedium,
utmCampaign, utmCampaign,
@ -154,9 +154,16 @@ async function clickhouseQuery({
websiteId, websiteId,
sessionId, sessionId,
visitId, visitId,
distinctId, eventType,
createdAt, createdAt,
pageTitle, pageTitle,
hostname,
urlPath,
urlQuery,
referrerPath,
referrerQuery,
referrerDomain,
distinctId,
browser, browser,
os, os,
device, device,
@ -165,15 +172,9 @@ async function clickhouseQuery({
country, country,
region, region,
city, city,
tag,
hostname,
urlPath,
urlQuery,
referrerPath,
referrerQuery,
referrerDomain,
eventName, eventName,
eventData, eventData,
tag,
utmSource, utmSource,
utmMedium, utmMedium,
utmCampaign, utmCampaign,
@ -215,7 +216,7 @@ async function clickhouseQuery({
ttclid: ttclid, ttclid: ttclid,
li_fat_id: lifatid, li_fat_id: lifatid,
twclid: twclid, twclid: twclid,
event_type: eventName ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, event_type: eventType,
event_name: eventName ? eventName?.substring(0, EVENT_NAME_LENGTH) : null, event_name: eventName ? eventName?.substring(0, EVENT_NAME_LENGTH) : null,
tag: tag, tag: tag,
distinct_id: distinctId, distinct_id: distinctId,

View file

@ -3,6 +3,8 @@ import prisma from '@/lib/prisma';
import clickhouse from '@/lib/clickhouse'; import clickhouse from '@/lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from '@/lib/db'; import { runQuery, CLICKHOUSE, PRISMA } from '@/lib/db';
const FUNCTION_NAME = 'getActiveVisitors';
export async function getActiveVisitors(...args: [websiteId: string]) { export async function getActiveVisitors(...args: [websiteId: string]) {
return runQuery({ return runQuery({
[PRISMA]: () => relationalQuery(...args), [PRISMA]: () => relationalQuery(...args),
@ -22,6 +24,7 @@ async function relationalQuery(websiteId: string) {
and created_at >= {{startDate}} and created_at >= {{startDate}}
`, `,
{ websiteId, startDate }, { websiteId, startDate },
FUNCTION_NAME,
); );
return result?.[0] ?? null; return result?.[0] ?? null;
@ -40,6 +43,7 @@ async function clickhouseQuery(websiteId: string): Promise<{ x: number }> {
and created_at >= {startDate:DateTime64} and created_at >= {startDate:DateTime64}
`, `,
{ websiteId, startDate }, { websiteId, startDate },
FUNCTION_NAME,
); );
return result[0] ?? null; return result[0] ?? null;

View file

@ -12,6 +12,8 @@ import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getChannelExpandedMetrics';
export interface ChannelExpandedMetricsParameters { export interface ChannelExpandedMetricsParameters {
limit?: number | string; limit?: number | string;
offset?: number | string; offset?: number | string;
@ -79,6 +81,7 @@ async function relationalQuery(
order by y desc; order by y desc;
`, `,
queryParams, queryParams,
FUNCTION_NAME,
); );
} }
@ -145,6 +148,7 @@ async function clickhouseQuery(
order by visitors desc, visits desc; order by visitors desc, visits desc;
`, `,
queryParams, queryParams,
FUNCTION_NAME,
); );
} }

View file

@ -12,6 +12,8 @@ import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getChannelMetrics';
export async function getChannelMetrics(...args: [websiteId: string, filters?: QueryFilters]) { export async function getChannelMetrics(...args: [websiteId: string, filters?: QueryFilters]) {
return runQuery({ return runQuery({
[PRISMA]: () => relationalQuery(...args), [PRISMA]: () => relationalQuery(...args),
@ -60,6 +62,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
order by y desc; order by y desc;
`, `,
queryParams, queryParams,
FUNCTION_NAME,
); );
} }
@ -117,7 +120,7 @@ async function clickhouseQuery(
order by y desc; order by y desc;
`; `;
return rawQuery(sql, queryParams); return rawQuery(sql, queryParams, FUNCTION_NAME);
} }
function toClickHouseStringArray(arr: string[]): string { function toClickHouseStringArray(arr: string[]): string {

View file

@ -3,6 +3,8 @@ import clickhouse from '@/lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from '@/lib/db'; import { runQuery, CLICKHOUSE, PRISMA } from '@/lib/db';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getRealtimeActivity';
export async function getRealtimeActivity(...args: [websiteId: string, filters: QueryFilters]) { export async function getRealtimeActivity(...args: [websiteId: string, filters: QueryFilters]) {
return runQuery({ return runQuery({
[PRISMA]: () => relationalQuery(...args), [PRISMA]: () => relationalQuery(...args),
@ -40,6 +42,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
limit 100 limit 100
`, `,
queryParams, queryParams,
FUNCTION_NAME,
); );
} }
@ -71,5 +74,6 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters): Promis
limit 100 limit 100
`, `,
queryParams, queryParams,
FUNCTION_NAME,
); );
} }

View file

@ -3,6 +3,8 @@ import clickhouse from '@/lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from '@/lib/db'; import { runQuery, CLICKHOUSE, PRISMA } from '@/lib/db';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getValues';
export async function getValues( export async function getValues(
...args: [websiteId: string, column: string, filters: QueryFilters] ...args: [websiteId: string, column: string, filters: QueryFilters]
) { ) {
@ -64,6 +66,7 @@ async function relationalQuery(websiteId: string, column: string, filters: Query
search: `%${search}%`, search: `%${search}%`,
...params, ...params,
}, },
FUNCTION_NAME,
); );
} }
@ -120,5 +123,6 @@ async function clickhouseQuery(websiteId: string, column: string, filters: Query
search, search,
...params, ...params,
}, },
FUNCTION_NAME,
); );
} }

View file

@ -1,9 +1,11 @@
import clickhouse from '@/lib/clickhouse'; import clickhouse from '@/lib/clickhouse';
import { EVENT_TYPE, FILTER_COLUMNS, GROUPED_DOMAINS, SESSION_COLUMNS } from '@/lib/constants'; import { FILTER_COLUMNS, GROUPED_DOMAINS, SESSION_COLUMNS } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getPageviewExpandedMetrics';
export interface PageviewExpandedMetricsParameters { export interface PageviewExpandedMetricsParameters {
type: string; type: string;
limit?: number | string; limit?: number | string;
@ -40,7 +42,6 @@ async function relationalQuery(
{ {
...filters, ...filters,
websiteId, websiteId,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
}, },
{ joinSession: SESSION_COLUMNS.includes(type) }, { joinSession: SESSION_COLUMNS.includes(type) },
); );
@ -89,6 +90,7 @@ async function relationalQuery(
offset ${offset} offset ${offset}
`, `,
queryParams, queryParams,
FUNCTION_NAME,
); );
} }
@ -103,7 +105,6 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({ const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters, ...filters,
websiteId, websiteId,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
}); });
let excludeDomain = ''; let excludeDomain = '';
@ -164,6 +165,7 @@ async function clickhouseQuery(
offset ${offset} offset ${offset}
`, `,
{ ...queryParams, ...parameters }, { ...queryParams, ...parameters },
FUNCTION_NAME,
); );
} }

View file

@ -1,9 +1,11 @@
import clickhouse from '@/lib/clickhouse'; import clickhouse from '@/lib/clickhouse';
import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { EVENT_COLUMNS, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getPageviewMetrics';
export interface PageviewMetricsParameters { export interface PageviewMetricsParameters {
type: string; type: string;
limit?: number | string; limit?: number | string;
@ -36,7 +38,6 @@ async function relationalQuery(
{ {
...filters, ...filters,
websiteId, websiteId,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
}, },
{ joinSession: SESSION_COLUMNS.includes(type) }, { joinSession: SESSION_COLUMNS.includes(type) },
); );
@ -86,6 +87,7 @@ async function relationalQuery(
offset ${offset} offset ${offset}
`, `,
{ ...queryParams, ...parameters }, { ...queryParams, ...parameters },
FUNCTION_NAME,
); );
} }
@ -100,7 +102,6 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({ const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters, ...filters,
websiteId, websiteId,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
}); });
let sql = ''; let sql = '';
@ -183,5 +184,5 @@ async function clickhouseQuery(
`; `;
} }
return rawQuery(sql, { ...queryParams, ...parameters }); return rawQuery(sql, { ...queryParams, ...parameters }, FUNCTION_NAME);
} }

View file

@ -1,9 +1,11 @@
import clickhouse from '@/lib/clickhouse'; import clickhouse from '@/lib/clickhouse';
import { EVENT_COLUMNS, EVENT_TYPE, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants'; import { EVENT_COLUMNS, FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import { QueryFilters } from '@/lib/types'; import { QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getSessionMetrics';
export interface SessionMetricsParameters { export interface SessionMetricsParameters {
type: string; type: string;
limit?: number | string; limit?: number | string;
@ -31,7 +33,6 @@ async function relationalQuery(
{ {
...filters, ...filters,
websiteId, websiteId,
eventType: EVENT_TYPE.pageView,
}, },
{ {
joinSession: SESSION_COLUMNS.includes(type), joinSession: SESSION_COLUMNS.includes(type),
@ -54,6 +55,7 @@ async function relationalQuery(
${joinSessionQuery} ${joinSessionQuery}
where website_event.website_id = {{websiteId::uuid}} where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}} and website_event.created_at between {{startDate}} and {{endDate}}
and event_type != 2
${filterQuery} ${filterQuery}
group by 1 group by 1
${includeCountry ? ', 3' : ''} ${includeCountry ? ', 3' : ''}
@ -62,6 +64,7 @@ async function relationalQuery(
offset ${offset} offset ${offset}
`, `,
{ ...queryParams, ...parameters }, { ...queryParams, ...parameters },
FUNCTION_NAME,
); );
} }
@ -76,7 +79,6 @@ async function clickhouseQuery(
const { filterQuery, cohortQuery, queryParams } = parseFilters({ const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters, ...filters,
websiteId, websiteId,
eventType: EVENT_TYPE.pageView,
}); });
const includeCountry = column === 'city' || column === 'region'; const includeCountry = column === 'city' || column === 'region';
@ -96,6 +98,7 @@ async function clickhouseQuery(
${cohortQuery} ${cohortQuery}
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}
and event_type != 2
${filterQuery} ${filterQuery}
group by x group by x
${includeCountry ? ', country' : ''} ${includeCountry ? ', country' : ''}
@ -113,6 +116,7 @@ async function clickhouseQuery(
${cohortQuery} ${cohortQuery}
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}
and event_type != 2
${filterQuery} ${filterQuery}
group by x group by x
${includeCountry ? ', country' : ''} ${includeCountry ? ', country' : ''}
@ -122,5 +126,5 @@ async function clickhouseQuery(
`; `;
} }
return rawQuery(sql, { ...queryParams, ...parameters }); return rawQuery(sql, { ...queryParams, ...parameters }, FUNCTION_NAME);
} }