From 3f1ecf4c1b9b334360baebe52a6aa7a59fe0a2fd Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Fri, 9 May 2025 16:54:49 -0700 Subject: [PATCH] Fixed identify. Closes #3409 --- src/app/api/send/route.ts | 62 ++--- src/queries/sql/events/saveEvent.ts | 237 ++++++++------------ src/queries/sql/events/saveEventData.ts | 28 +-- src/queries/sql/sessions/saveSessionData.ts | 41 ++-- 4 files changed, 156 insertions(+), 212 deletions(-) diff --git a/src/app/api/send/route.ts b/src/app/api/send/route.ts index b35a67b7..60d6f7af 100644 --- a/src/app/api/send/route.ts +++ b/src/app/api/send/route.ts @@ -187,26 +187,19 @@ export async function POST(request: Request) { websiteId, sessionId, visitId, + createdAt, + + // Page + pageTitle: safeDecodeURIComponent(title), + hostname: hostname || urlDomain, urlPath: safeDecodeURI(urlPath), urlQuery, - utmSource, - utmMedium, - utmCampaign, - utmContent, - utmTerm, referrerPath: safeDecodeURI(referrerPath), referrerQuery, referrerDomain, - pageTitle: safeDecodeURIComponent(title), - gclid, - fbclid, - msclkid, - ttclid, - lifatid, - twclid, - eventName: name, - eventData: data, - hostname: hostname || urlDomain, + + // Session + distinctId: id, browser, os, device, @@ -215,24 +208,39 @@ export async function POST(request: Request) { country, region, city, + + // Events + eventName: name, + eventData: data, tag, - distinctId: id, - createdAt, + + // UTM + utmSource, + utmMedium, + utmCampaign, + utmContent, + utmTerm, + + // Click IDs + gclid, + fbclid, + msclkid, + ttclid, + lifatid, + twclid, }); } if (type === COLLECTION_TYPE.identify) { - if (!data) { - return badRequest('Data required.'); + if (data) { + await saveSessionData({ + websiteId, + sessionId, + sessionData: data, + distinctId: id, + createdAt, + }); } - - await saveSessionData({ - websiteId, - sessionId, - sessionData: data, - distinctId: id, - createdAt, - }); } const token = createToken({ websiteId, sessionId, visitId, iat }, secret()); diff --git a/src/queries/sql/events/saveEvent.ts b/src/queries/sql/events/saveEvent.ts index e9b73635..737b9b9f 100644 --- a/src/queries/sql/events/saveEvent.ts +++ b/src/queries/sql/events/saveEvent.ts @@ -6,30 +6,23 @@ import prisma from '@/lib/prisma'; import { uuid } from '@/lib/crypto'; import { saveEventData } from './saveEventData'; -export async function saveEvent(args: { +export interface SaveEventArgs { websiteId: string; sessionId: string; visitId: string; + createdAt?: Date; + + // Page + pageTitle?: string; + hostname?: string; urlPath: string; urlQuery?: string; - utmSource?: string; - utmMedium?: string; - utmCampaign?: string; - utmContent?: string; - utmTerm?: string; referrerPath?: string; referrerQuery?: string; referrerDomain?: string; - pageTitle?: string; - gclid?: string; - fbclid?: string; - msclkid?: string; - ttclid?: string; - lifatid?: string; - twclid?: string; - eventName?: string; - eventData?: any; - hostname?: string; + + // Session + distinctId?: string; browser?: string; os?: string; device?: string; @@ -38,73 +31,65 @@ export async function saveEvent(args: { country?: string; region?: string; city?: string; - tag?: string; - distinctId?: string; - createdAt?: Date; -}) { - return runQuery({ - [PRISMA]: () => relationalQuery(args), - [CLICKHOUSE]: () => clickhouseQuery(args), - }); -} -async function relationalQuery(data: { - websiteId: string; - sessionId: string; - visitId: string; - urlPath: string; - urlQuery?: string; + // Events + eventName?: string; + eventData?: any; + tag?: string; + + // UTM utmSource?: string; utmMedium?: string; utmCampaign?: string; utmContent?: string; utmTerm?: string; - referrerPath?: string; - referrerQuery?: string; - referrerDomain?: string; + + // Click IDs gclid?: string; fbclid?: string; msclkid?: string; ttclid?: string; lifatid?: string; twclid?: string; - pageTitle?: string; - eventName?: string; - eventData?: any; - tag?: string; - hostname?: string; - createdAt?: Date; -}) { - const { - websiteId, - sessionId, - visitId, - urlPath, - urlQuery, - utmSource, - utmMedium, - utmCampaign, - utmContent, - utmTerm, - referrerPath, - referrerQuery, - referrerDomain, - eventName, - eventData, - pageTitle, - gclid, - fbclid, - msclkid, - ttclid, - lifatid, - twclid, - tag, - hostname, - createdAt, - } = data; +} + +export async function saveEvent(args: SaveEventArgs) { + return runQuery({ + [PRISMA]: () => relationalQuery(args), + [CLICKHOUSE]: () => clickhouseQuery(args), + }); +} + +async function relationalQuery({ + websiteId, + sessionId, + visitId, + createdAt, + pageTitle, + tag, + hostname, + urlPath, + urlQuery, + referrerPath, + referrerQuery, + referrerDomain, + eventName, + eventData, + utmSource, + utmMedium, + utmCampaign, + utmContent, + utmTerm, + gclid, + fbclid, + msclkid, + ttclid, + lifatid, + twclid, +}: SaveEventArgs) { const websiteEventId = uuid(); - const websiteEvent = prisma.client.websiteEvent.create({ + await prisma.client.websiteEvent.create({ data: { id: websiteEventId, websiteId, @@ -146,83 +131,49 @@ async function relationalQuery(data: { createdAt, }); } - - return websiteEvent; } -async function clickhouseQuery(data: { - websiteId: string; - sessionId: string; - visitId: string; - urlPath: string; - urlQuery?: string; - utmSource?: string; - utmMedium?: string; - utmCampaign?: string; - utmContent?: string; - utmTerm?: string; - referrerPath?: string; - referrerQuery?: string; - referrerDomain?: string; - pageTitle?: string; - gclid?: string; - fbclid?: string; - msclkid?: string; - ttclid?: string; - lifatid?: string; - twclid?: string; - eventName?: string; - eventData?: any; - hostname?: string; - browser?: string; - os?: string; - device?: string; - screen?: string; - language?: string; - country?: string; - region?: string; - city?: string; - tag?: string; - distinctId?: string; - createdAt?: Date; -}) { - const { - websiteId, - sessionId, - visitId, - urlPath, - urlQuery, - utmSource, - utmMedium, - utmCampaign, - utmContent, - utmTerm, - referrerPath, - referrerQuery, - referrerDomain, - gclid, - fbclid, - msclkid, - ttclid, - lifatid, - twclid, - pageTitle, - eventName, - eventData, - country, - region, - city, - tag, - distinctId, - createdAt, - ...args - } = data; +async function clickhouseQuery({ + websiteId, + sessionId, + visitId, + distinctId, + createdAt, + pageTitle, + browser, + os, + device, + screen, + language, + country, + region, + city, + tag, + hostname, + urlPath, + urlQuery, + referrerPath, + referrerQuery, + referrerDomain, + eventName, + eventData, + utmSource, + utmMedium, + utmCampaign, + utmContent, + utmTerm, + gclid, + fbclid, + msclkid, + ttclid, + lifatid, + twclid, +}: SaveEventArgs) { const { insert, getUTCString } = clickhouse; const { sendMessage } = kafka; const eventId = uuid(); const message = { - ...args, website_id: websiteId, session_id: sessionId, visit_id: visitId, @@ -252,6 +203,12 @@ async function clickhouseQuery(data: { tag: tag, distinct_id: distinctId, created_at: getUTCString(createdAt), + browser, + os, + device, + screen, + language, + hostname, }; if (kafka.enabled) { @@ -271,6 +228,4 @@ async function clickhouseQuery(data: { createdAt, }); } - - return data; } diff --git a/src/queries/sql/events/saveEventData.ts b/src/queries/sql/events/saveEventData.ts index 16a5cab1..0fb86937 100644 --- a/src/queries/sql/events/saveEventData.ts +++ b/src/queries/sql/events/saveEventData.ts @@ -1,4 +1,3 @@ -import { Prisma } from '@prisma/client'; import { DATA_TYPE } from '@/lib/constants'; import { uuid } from '@/lib/crypto'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; @@ -8,7 +7,7 @@ import kafka from '@/lib/kafka'; import prisma from '@/lib/prisma'; import { DynamicData } from '@/lib/types'; -export async function saveEventData(data: { +export interface SaveEventDataArgs { websiteId: string; eventId: string; sessionId?: string; @@ -16,19 +15,16 @@ export async function saveEventData(data: { eventName?: string; eventData: DynamicData; createdAt?: Date; -}) { +} + +export async function saveEventData(data: SaveEventDataArgs) { return runQuery({ [PRISMA]: () => relationalQuery(data), [CLICKHOUSE]: () => clickhouseQuery(data), }); } -async function relationalQuery(data: { - websiteId: string; - eventId: string; - eventData: DynamicData; - createdAt?: Date; -}): Promise { +async function relationalQuery(data: SaveEventDataArgs) { const { websiteId, eventId, eventData, createdAt } = data; const jsonKeys = flattenJSON(eventData); @@ -46,20 +42,12 @@ async function relationalQuery(data: { createdAt, })); - return prisma.client.eventData.createMany({ + await prisma.client.eventData.createMany({ data: flattenedData, }); } -async function clickhouseQuery(data: { - websiteId: string; - eventId: string; - sessionId?: string; - urlPath?: string; - eventName?: string; - eventData: DynamicData; - createdAt?: Date; -}) { +async function clickhouseQuery(data: SaveEventDataArgs) { const { websiteId, sessionId, eventId, urlPath, eventName, eventData, createdAt } = data; const { insert, getUTCString } = clickhouse; @@ -88,6 +76,4 @@ async function clickhouseQuery(data: { } else { await insert('event_data', messages); } - - return data; } diff --git a/src/queries/sql/sessions/saveSessionData.ts b/src/queries/sql/sessions/saveSessionData.ts index 46ad3cf6..cffe8e6e 100644 --- a/src/queries/sql/sessions/saveSessionData.ts +++ b/src/queries/sql/sessions/saveSessionData.ts @@ -7,28 +7,29 @@ import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import kafka from '@/lib/kafka'; import clickhouse from '@/lib/clickhouse'; -export async function saveSessionData(data: { +export interface SaveSessionDataArgs { websiteId: string; sessionId: string; sessionData: DynamicData; distinctId?: string; createdAt?: Date; -}) { +} + +export async function saveSessionData(data: SaveSessionDataArgs) { return runQuery({ [PRISMA]: () => relationalQuery(data), [CLICKHOUSE]: () => clickhouseQuery(data), }); } -export async function relationalQuery(data: { - websiteId: string; - sessionId: string; - sessionData: DynamicData; - distinctId?: string; - createdAt?: Date; -}) { +export async function relationalQuery({ + websiteId, + sessionId, + sessionData, + distinctId, + createdAt, +}: SaveSessionDataArgs) { const { client } = prisma; - const { websiteId, sessionId, sessionData, distinctId, createdAt } = data; const jsonKeys = flattenJSON(sessionData); @@ -75,19 +76,15 @@ export async function relationalQuery(data: { }); } } - - return flattenedData; } -async function clickhouseQuery(data: { - websiteId: string; - sessionId: string; - sessionData: DynamicData; - distinctId?: string; - createdAt?: Date; -}) { - const { websiteId, sessionId, sessionData, distinctId, createdAt } = data; - +async function clickhouseQuery({ + websiteId, + sessionId, + sessionData, + distinctId, + createdAt, +}: SaveSessionDataArgs) { const { insert, getUTCString } = clickhouse; const { sendMessage } = kafka; @@ -112,6 +109,4 @@ async function clickhouseQuery(data: { } else { await insert('session_data', messages); } - - return data; }