Merge branch 'dev' of https://github.com/umami-software/umami into feat/add-segments

This commit is contained in:
Francis Cao 2025-06-11 06:46:31 -07:00
commit 1ccc8a1a86
16 changed files with 360 additions and 272 deletions

View file

@ -25,7 +25,7 @@ body:
- type: input - type: input
attributes: attributes:
label: Which Umami version are you using? (if relevant) label: Which Umami version are you using? (if relevant)
description: 'For example: Chrome, Edge, Firefox, etc' description: 'For example: 2.18.0, 2.15.1, 1.39.0, etc'
- type: input - type: input
attributes: attributes:
label: Which browser are you using? (if relevant) label: Which browser are you using? (if relevant)

View file

@ -11,6 +11,8 @@ env:
jobs: jobs:
build: build:
# Only run the CI if it belongs to the original repository
if: github.repository == 'umami-software/umami'
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:

View file

@ -246,3 +246,38 @@ SELECT * ORDER BY toStartOfDay(created_at), website_id, referrer_domain, created
); );
ALTER TABLE umami.website_event MATERIALIZE PROJECTION website_event_referrer_domain_projection; ALTER TABLE umami.website_event MATERIALIZE PROJECTION website_event_referrer_domain_projection;
-- revenue
CREATE TABLE umami.website_revenue
(
website_id UUID,
session_id UUID,
event_id UUID,
event_name String,
currency String,
revenue DECIMAL(18,4),
created_at DateTime('UTC')
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(created_at)
ORDER BY (website_id, session_id, created_at)
SETTINGS index_granularity = 8192;
CREATE MATERIALIZED VIEW umami.website_revenue_mv
TO umami.website_revenue
AS
SELECT DISTINCT
ed.website_id,
ed.session_id,
ed.event_id,
ed.event_name,
c.currency,
coalesce(toDecimal64(ed.number_value, 2), toDecimal64(ed.string_value, 2)) revenue,
ed.created_at
FROM umami.event_data ed
JOIN (SELECT event_id, string_value as currency
FROM umami.event_data
WHERE positionCaseInsensitive(data_key, 'currency') > 0) c
ON c.event_id = ed.event_id
WHERE positionCaseInsensitive(data_key, 'revenue') > 0;

View file

@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "report"
ALTER COLUMN "parameters" SET DATA TYPE JSONB USING parameters::JSONB;

View file

@ -0,0 +1,31 @@
-- AlterTable
ALTER TABLE "segment" ADD COLUMN "type" VARCHAR(200) NOT NULL;
-- CreateTable
CREATE TABLE "revenue" (
"revenue_id" UUID NOT NULL,
"website_id" UUID NOT NULL,
"session_id" UUID NOT NULL,
"event_id" UUID NOT NULL,
"event_name" VARCHAR(50) NOT NULL,
"currency" VARCHAR(100) NOT NULL,
"revenue" DECIMAL(19,4),
"created_at" TIMESTAMPTZ(6) DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "revenue_pkey" PRIMARY KEY ("revenue_id")
);
-- CreateIndex
CREATE UNIQUE INDEX "revenue_revenue_id_key" ON "revenue"("revenue_id");
-- CreateIndex
CREATE INDEX "revenue_website_id_idx" ON "revenue"("website_id");
-- CreateIndex
CREATE INDEX "revenue_session_id_idx" ON "revenue"("session_id");
-- CreateIndex
CREATE INDEX "revenue_website_id_created_at_idx" ON "revenue"("website_id", "created_at");
-- CreateIndex
CREATE INDEX "revenue_website_id_session_id_created_at_idx" ON "revenue"("website_id", "session_id", "created_at");

View file

@ -43,6 +43,7 @@ model Session {
websiteEvent WebsiteEvent[] websiteEvent WebsiteEvent[]
sessionData SessionData[] sessionData SessionData[]
revenue Revenue[]
@@index([createdAt]) @@index([createdAt])
@@index([websiteId]) @@index([websiteId])
@ -76,6 +77,7 @@ model Website {
team Team? @relation(fields: [teamId], references: [id]) team Team? @relation(fields: [teamId], references: [id])
eventData EventData[] eventData EventData[]
report Report[] report Report[]
revenue Revenue[]
sessionData SessionData[] sessionData SessionData[]
segment Segment[] segment Segment[]
@ -104,12 +106,12 @@ model WebsiteEvent {
referrerQuery String? @map("referrer_query") @db.VarChar(500) referrerQuery String? @map("referrer_query") @db.VarChar(500)
referrerDomain String? @map("referrer_domain") @db.VarChar(500) referrerDomain String? @map("referrer_domain") @db.VarChar(500)
pageTitle String? @map("page_title") @db.VarChar(500) pageTitle String? @map("page_title") @db.VarChar(500)
gclid String? @map("gclid") @db.VarChar(255) gclid String? @db.VarChar(255)
fbclid String? @map("fbclid") @db.VarChar(255) fbclid String? @db.VarChar(255)
msclkid String? @map("msclkid") @db.VarChar(255) msclkid String? @db.VarChar(255)
ttclid String? @map("ttclid") @db.VarChar(255) ttclid String? @db.VarChar(255)
lifatid String? @map("li_fat_id") @db.VarChar(255) lifatid String? @map("li_fat_id") @db.VarChar(255)
twclid String? @map("twclid") @db.VarChar(255) twclid String? @db.VarChar(255)
eventType Int @default(1) @map("event_type") @db.Integer eventType Int @default(1) @map("event_type") @db.Integer
eventName String? @map("event_name") @db.VarChar(50) eventName String? @map("event_name") @db.VarChar(50)
tag String? @db.VarChar(50) tag String? @db.VarChar(50)
@ -200,7 +202,7 @@ model TeamUser {
id String @id() @unique() @map("team_user_id") @db.Uuid id String @id() @unique() @map("team_user_id") @db.Uuid
teamId String @map("team_id") @db.Uuid teamId String @map("team_id") @db.Uuid
userId String @map("user_id") @db.Uuid userId String @map("user_id") @db.Uuid
role String @map("role") @db.VarChar(50) role String @db.VarChar(50)
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
@ -216,10 +218,10 @@ model Report {
id String @id() @unique() @map("report_id") @db.Uuid id String @id() @unique() @map("report_id") @db.Uuid
userId String @map("user_id") @db.Uuid userId String @map("user_id") @db.Uuid
websiteId String @map("website_id") @db.Uuid websiteId String @map("website_id") @db.Uuid
type String @map("type") @db.VarChar(200) type String @db.VarChar(200)
name String @map("name") @db.VarChar(200) name String @db.VarChar(200)
description String @map("description") @db.VarChar(500) description String @db.VarChar(500)
parameters String @map("parameters") @db.VarChar(6000) parameters Json
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
@ -236,8 +238,9 @@ model Report {
model Segment { model Segment {
id String @id() @unique() @map("segment_id") @db.Uuid id String @id() @unique() @map("segment_id") @db.Uuid
websiteId String @map("website_id") @db.Uuid websiteId String @map("website_id") @db.Uuid
name String @map("name") @db.VarChar(200) type String @db.VarChar(200)
filters Json @map("filters") name String @db.VarChar(200)
filters Json
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6) updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamptz(6)
@ -246,3 +249,23 @@ model Segment {
@@index([websiteId]) @@index([websiteId])
@@map("segment") @@map("segment")
} }
model Revenue {
id String @id() @unique() @map("revenue_id") @db.Uuid
websiteId String @map("website_id") @db.Uuid
sessionId String @map("session_id") @db.Uuid
eventId String @map("event_id") @db.Uuid
eventName String @map("event_name") @db.VarChar(50)
currency String @db.VarChar(100)
revenue Decimal? @db.Decimal(19, 4)
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
website Website @relation(fields: [websiteId], references: [id])
session Session @relation(fields: [sessionId], references: [id])
@@index([websiteId])
@@index([sessionId])
@@index([websiteId, createdAt])
@@index([websiteId, sessionId, createdAt])
@@map("revenue")
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Before After
Before After

View file

@ -38,7 +38,7 @@
"label.add-step": [ "label.add-step": [
{ {
"type": 0, "type": 0,
"value": "Add step" "value": "إضافة خطوة"
} }
], ],
"label.add-website": [ "label.add-website": [
@ -77,6 +77,18 @@
"value": "تحليلات" "value": "تحليلات"
} }
], ],
"label.attribution": [
{
"type": 0,
"value": "الإسناد"
}
],
"label.attribution-description": [
{
"type": 0,
"value": "شاهد كيف يتفاعل المستخدمون مع حملاتك التسويقية وما الذي يحفز التحويلات."
}
],
"label.average": [ "label.average": [
{ {
"type": 0, "type": 0,
@ -122,7 +134,7 @@
"label.cancel": [ "label.cancel": [
{ {
"type": 0, "type": 0,
"value": "ألغِ" "value": "إلغاء"
} }
], ],
"label.change-password": [ "label.change-password": [
@ -152,7 +164,7 @@
"label.compare": [ "label.compare": [
{ {
"type": 0, "type": 0,
"value": "Compare" "value": "المقارنة"
} }
], ],
"label.confirm": [ "label.confirm": [
@ -170,7 +182,7 @@
"label.contains": [ "label.contains": [
{ {
"type": 0, "type": 0,
"value": "يحتوي" "value": "يحتوي على"
} }
], ],
"label.continue": [ "label.continue": [
@ -182,7 +194,7 @@
"label.count": [ "label.count": [
{ {
"type": 0, "type": 0,
"value": "Count" "value": "العدد"
} }
], ],
"label.countries": [ "label.countries": [
@ -236,7 +248,7 @@
"label.current": [ "label.current": [
{ {
"type": 0, "type": 0,
"value": "Current" "value": "الحالي"
} }
], ],
"label.current-password": [ "label.current-password": [
@ -254,7 +266,7 @@
"label.dashboard": [ "label.dashboard": [
{ {
"type": 0, "type": 0,
"value": "الشاشة الرئيسية" "value": "لوحة التحكم"
} }
], ],
"label.data": [ "label.data": [
@ -356,7 +368,7 @@
"label.does-not-contain": [ "label.does-not-contain": [
{ {
"type": 0, "type": 0,
"value": "لا يحتوي" "value": "لا يحتوي على"
} }
], ],
"label.domain": [ "label.domain": [
@ -374,7 +386,7 @@
"label.edit": [ "label.edit": [
{ {
"type": 0, "type": 0,
"value": "عدّل" "value": "تعديل"
} }
], ],
"label.edit-dashboard": [ "label.edit-dashboard": [
@ -398,13 +410,13 @@
"label.end-step": [ "label.end-step": [
{ {
"type": 0, "type": 0,
"value": "End Step" "value": "الخطوة الأخيرة"
} }
], ],
"label.entry": [ "label.entry": [
{ {
"type": 0, "type": 0,
"value": "Entry URL" "value": "رابط الدخول"
} }
], ],
"label.event": [ "label.event": [
@ -428,7 +440,7 @@
"label.exit": [ "label.exit": [
{ {
"type": 0, "type": 0,
"value": "Exit URL" "value": "رابط المغادرة"
} }
], ],
"label.false": [ "label.false": [
@ -476,7 +488,7 @@
"label.first-seen": [ "label.first-seen": [
{ {
"type": 0, "type": 0,
"value": "First seen" "value": "أول ظهور"
} }
], ],
"label.funnel": [ "label.funnel": [
@ -494,19 +506,19 @@
"label.goal": [ "label.goal": [
{ {
"type": 0, "type": 0,
"value": "Goal" "value": "الهدف"
} }
], ],
"label.goals": [ "label.goals": [
{ {
"type": 0, "type": 0,
"value": "Goals" "value": "الأهداف"
} }
], ],
"label.goals-description": [ "label.goals-description": [
{ {
"type": 0, "type": 0,
"value": "Track your goals for pageviews and events." "value": "تابع تحقق أهدافك المرتبطة بمشاهدات الصفحات والأحداث."
} }
], ],
"label.greater-than": [ "label.greater-than": [
@ -548,13 +560,13 @@
"label.is": [ "label.is": [
{ {
"type": 0, "type": 0,
"value": "هو" "value": "يساوي"
} }
], ],
"label.is-not": [ "label.is-not": [
{ {
"type": 0, "type": 0,
"value": م" "value": ا يساوي"
} }
], ],
"label.is-not-set": [ "label.is-not-set": [
@ -584,13 +596,13 @@
"label.journey": [ "label.journey": [
{ {
"type": 0, "type": 0,
"value": "Journey" "value": "رحلة المستخدم"
} }
], ],
"label.journey-description": [ "label.journey-description": [
{ {
"type": 0, "type": 0,
"value": "Understand how users navigate through your website." "value": "تعرّف على كيفية تنقّل المستخدمين داخل موقعك."
} }
], ],
"label.language": [ "label.language": [
@ -642,7 +654,7 @@
"label.last-months": [ "label.last-months": [
{ {
"type": 0, "type": 0,
"value": "Last " "value": "آخر "
}, },
{ {
"type": 1, "type": 1,
@ -650,13 +662,13 @@
}, },
{ {
"type": 0, "type": 0,
"value": " months" "value": " شهر/أشهر"
} }
], ],
"label.last-seen": [ "label.last-seen": [
{ {
"type": 0, "type": 0,
"value": "Last seen" "value": "آخر ظهور"
} }
], ],
"label.leave": [ "label.leave": [
@ -704,7 +716,7 @@
"label.manager": [ "label.manager": [
{ {
"type": 0, "type": 0,
"value": "Manager" "value": "مدير"
} }
], ],
"label.max": [ "label.max": [
@ -876,13 +888,13 @@
"label.path": [ "label.path": [
{ {
"type": 0, "type": 0,
"value": "Path" "value": "المسار"
} }
], ],
"label.paths": [ "label.paths": [
{ {
"type": 0, "type": 0,
"value": "Paths" "value": "المسارات"
} }
], ],
"label.powered-by": [ "label.powered-by": [
@ -898,19 +910,19 @@
"label.previous": [ "label.previous": [
{ {
"type": 0, "type": 0,
"value": "Previous" "value": "السابق"
} }
], ],
"label.previous-period": [ "label.previous-period": [
{ {
"type": 0, "type": 0,
"value": "Previous period" "value": "الفترة السابقة"
} }
], ],
"label.previous-year": [ "label.previous-year": [
{ {
"type": 0, "type": 0,
"value": "Previous year" "value": "العام السابق"
} }
], ],
"label.profile": [ "label.profile": [
@ -922,13 +934,13 @@
"label.properties": [ "label.properties": [
{ {
"type": 0, "type": 0,
"value": "Properties" "value": "الخصائص"
} }
], ],
"label.property": [ "label.property": [
{ {
"type": 0, "type": 0,
"value": "Property" "value": "الخاصية"
} }
], ],
"label.queries": [ "label.queries": [
@ -1042,19 +1054,19 @@
"label.revenue": [ "label.revenue": [
{ {
"type": 0, "type": 0,
"value": "Revenue" "value": "الإيرادات"
} }
], ],
"label.revenue-description": [ "label.revenue-description": [
{ {
"type": 0, "type": 0,
"value": "Look into your revenue across time." "value": "قم بإلقاء نظرة على بيانات إيراداتك وكيفية إنفاق المستخدمين."
} }
], ],
"label.revenue-property": [ "label.revenue-property": [
{ {
"type": 0, "type": 0,
"value": "Revenue Property" "value": "خاصية الإيرادات"
} }
], ],
"label.role": [ "label.role": [
@ -1114,7 +1126,7 @@
"label.session": [ "label.session": [
{ {
"type": 0, "type": 0,
"value": "Session" "value": "الزيارة"
} }
], ],
"label.sessions": [ "label.sessions": [
@ -1144,13 +1156,13 @@
"label.start-step": [ "label.start-step": [
{ {
"type": 0, "type": 0,
"value": "Start Step" "value": "الخطوة الأولى"
} }
], ],
"label.steps": [ "label.steps": [
{ {
"type": 0, "type": 0,
"value": "Steps" "value": "الخطوات"
} }
], ],
"label.sum": [ "label.sum": [
@ -1165,6 +1177,18 @@
"value": "تابلت" "value": "تابلت"
} }
], ],
"label.tag": [
{
"type": 0,
"value": "الوسم"
}
],
"label.tags": [
{
"type": 0,
"value": "الوسوم"
}
],
"label.team": [ "label.team": [
{ {
"type": 0, "type": 0,
@ -1180,7 +1204,7 @@
"label.team-manager": [ "label.team-manager": [
{ {
"type": 0, "type": 0,
"value": "Team manager" "value": "مدير الفريق"
} }
], ],
"label.team-member": [ "label.team-member": [
@ -1204,7 +1228,7 @@
"label.team-view-only": [ "label.team-view-only": [
{ {
"type": 0, "type": 0,
"value": "Team view only" "value": "عرض الفريق فقط"
} }
], ],
"label.team-websites": [ "label.team-websites": [
@ -1288,13 +1312,13 @@
"label.transactions": [ "label.transactions": [
{ {
"type": 0, "type": 0,
"value": "Transactions" "value": "المعاملات"
} }
], ],
"label.transfer": [ "label.transfer": [
{ {
"type": 0, "type": 0,
"value": "Transfer" "value": "نقل"
} }
], ],
"label.transfer-website": [ "label.transfer-website": [
@ -1330,7 +1354,7 @@
"label.uniqueCustomers": [ "label.uniqueCustomers": [
{ {
"type": 0, "type": 0,
"value": "Unique Customers" "value": "العملاء الفريدون"
} }
], ],
"label.unknown": [ "label.unknown": [
@ -1348,19 +1372,19 @@
"label.update": [ "label.update": [
{ {
"type": 0, "type": 0,
"value": "Update" "value": "تحديث"
} }
], ],
"label.url": [ "label.url": [
{ {
"type": 0, "type": 0,
"value": "URL" "value": "الرابط"
} }
], ],
"label.urls": [ "label.urls": [
{ {
"type": 0, "type": 0,
"value": "URLs" "value": "الروابط"
} }
], ],
"label.user": [ "label.user": [
@ -1372,7 +1396,7 @@
"label.user-property": [ "label.user-property": [
{ {
"type": 0, "type": 0,
"value": "User Property" "value": "سمات المستخدم"
} }
], ],
"label.username": [ "label.username": [
@ -1396,7 +1420,7 @@
"label.utm-description": [ "label.utm-description": [
{ {
"type": 0, "type": 0,
"value": "Track your campaigns through UTM parameters." "value": "تابع حملاتك التسويقية باستخدام معلمات UTM."
} }
], ],
"label.value": [ "label.value": [
@ -1432,7 +1456,7 @@
"label.views-per-visit": [ "label.views-per-visit": [
{ {
"type": 0, "type": 0,
"value": "Views per visit" "value": "مشاهدات لكل زيارة"
} }
], ],
"label.visit-duration": [ "label.visit-duration": [
@ -1450,7 +1474,7 @@
"label.visits": [ "label.visits": [
{ {
"type": 0, "type": 0,
"value": "Visits" "value": "الزيارات"
} }
], ],
"label.website": [ "label.website": [
@ -1534,7 +1558,7 @@
"message.collected-data": [ "message.collected-data": [
{ {
"type": 0, "type": 0,
"value": "Collected data" "value": "البيانات المجمعة"
} }
], ],
"message.confirm-delete": [ "message.confirm-delete": [
@ -1754,15 +1778,7 @@
"message.share-url": [ "message.share-url": [
{ {
"type": 0, "type": 0,
"value": "هذا الرابط الذي تم مشاركته بشكل عام لـ " "value": "إحصائيات موقعك متاحة للجميع على الرابط التالي:"
},
{
"type": 1,
"value": "target"
},
{
"type": 0,
"value": "."
} }
], ],
"message.team-already-member": [ "message.team-already-member": [

View file

@ -25,7 +25,8 @@ FROM (SELECT event_id, website_id, session_id,
(regexp_matches(url_query, '(?:[&?]|^)utm_medium=([^&]+)', 'i'))[1] AS utm_medium, (regexp_matches(url_query, '(?:[&?]|^)utm_medium=([^&]+)', 'i'))[1] AS utm_medium,
(regexp_matches(url_query, '(?:[&?]|^)utm_source=([^&]+)', 'i'))[1] AS utm_source, (regexp_matches(url_query, '(?:[&?]|^)utm_source=([^&]+)', 'i'))[1] AS utm_source,
(regexp_matches(url_query, '(?:[&?]|^)utm_term=([^&]+)', 'i'))[1] AS utm_term (regexp_matches(url_query, '(?:[&?]|^)utm_term=([^&]+)', 'i'))[1] AS utm_term
FROM "website_event") url FROM "website_event"
WHERE url_query IS NOT NULL) url
WHERE we.event_id = url.event_id WHERE we.event_id = url.event_id
and we.session_id = url.session_id and we.session_id = url.session_id
and we.website_id = url.website_id; and we.website_id = url.website_id;
@ -45,4 +46,4 @@ SET fbclid = LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REGEXP_SUBSTR(url_query, '(?:[
utm_medium = LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REGEXP_SUBSTR(url_query, '(?:[&?]|^)utm_medium=[^&]+'), '=', -1), '&', 1), 255), utm_medium = LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REGEXP_SUBSTR(url_query, '(?:[&?]|^)utm_medium=[^&]+'), '=', -1), '&', 1), 255),
utm_source = LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REGEXP_SUBSTR(url_query, '(?:[&?]|^)utm_source=[^&]+'), '=', -1), '&', 1), 255), utm_source = LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REGEXP_SUBSTR(url_query, '(?:[&?]|^)utm_source=[^&]+'), '=', -1), '&', 1), 255),
utm_term = LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REGEXP_SUBSTR(url_query, '(?:[&?]|^)utm_term=[^&]+'), '=', -1), '&', 1), 255) utm_term = LEFT(SUBSTRING_INDEX(SUBSTRING_INDEX(REGEXP_SUBSTR(url_query, '(?:[&?]|^)utm_term=[^&]+'), '=', -1), '&', 1), 255)
WHERE 1 = 1; WHERE url_query IS NOT NULL;

View file

@ -145,7 +145,8 @@ export async function POST(request: Request) {
const base = hostname ? `https://${hostname}` : 'https://localhost'; const base = hostname ? `https://${hostname}` : 'https://localhost';
const currentUrl = new URL(url, base); const currentUrl = new URL(url, base);
let urlPath = currentUrl.pathname === '/undefined' ? '' : currentUrl.pathname; let urlPath =
currentUrl.pathname === '/undefined' ? '' : currentUrl.pathname + currentUrl.hash;
const urlQuery = currentUrl.search.substring(1); const urlQuery = currentUrl.search.substring(1);
const urlDomain = currentUrl.hostname.replace(/^www./, ''); const urlDomain = currentUrl.hostname.replace(/^www./, '');
@ -169,7 +170,7 @@ export async function POST(request: Request) {
const twclid = currentUrl.searchParams.get('twclid'); const twclid = currentUrl.searchParams.get('twclid');
if (process.env.REMOVE_TRAILING_SLASH) { if (process.env.REMOVE_TRAILING_SLASH) {
urlPath = urlPath.replace(/(.+)\/$/, '$1'); urlPath = urlPath.replace(/\/(?=(#.*)?$)/, '');
} }
if (referrer) { if (referrer) {

View file

@ -5,13 +5,15 @@
"label.add": "أضِف", "label.add": "أضِف",
"label.add-description": "أضِف وصف", "label.add-description": "أضِف وصف",
"label.add-member": "أضِف عضو", "label.add-member": "أضِف عضو",
"label.add-step": "Add step", "label.add-step": "إضافة خطوة",
"label.add-website": "إضافة موقع", "label.add-website": "إضافة موقع",
"label.admin": "مدير", "label.admin": "مدير",
"label.after": "يعد", "label.after": "يعد",
"label.all": "الكل", "label.all": "الكل",
"label.all-time": "كل الوقت", "label.all-time": "كل الوقت",
"label.analytics": "تحليلات", "label.analytics": "تحليلات",
"label.attribution": "الإسناد",
"label.attribution-description": "شاهد كيف يتفاعل المستخدمون مع حملاتك التسويقية وما الذي يحفز التحويلات.",
"label.average": "المتوسط", "label.average": "المتوسط",
"label.back": "للخلف", "label.back": "للخلف",
"label.before": "قبل", "label.before": "قبل",
@ -19,17 +21,17 @@
"label.breakdown": "التصنيف", "label.breakdown": "التصنيف",
"label.browser": "المتصفح", "label.browser": "المتصفح",
"label.browsers": "المتصفحات", "label.browsers": "المتصفحات",
"label.cancel": "ألغِ", "label.cancel": "إلغاء",
"label.change-password": "تغيير كلمة المرور", "label.change-password": "تغيير كلمة المرور",
"label.cities": "المدن", "label.cities": "المدن",
"label.city": "المدينة", "label.city": "المدينة",
"label.clear-all": "مسح الكل", "label.clear-all": "مسح الكل",
"label.compare": "Compare", "label.compare": "المقارنة",
"label.confirm": "تأكيد", "label.confirm": "تأكيد",
"label.confirm-password": "تأكيد كلمة المرور", "label.confirm-password": "تأكيد كلمة المرور",
"label.contains": "يحتوي", "label.contains": "يحتوي على",
"label.continue": "تابع", "label.continue": "تابع",
"label.count": "Count", "label.count": "العدد",
"label.countries": "الدول", "label.countries": "الدول",
"label.country": "الدولة", "label.country": "الدولة",
"label.create": "أنشِئ", "label.create": "أنشِئ",
@ -38,10 +40,10 @@
"label.create-user": "أنشِئ مستخدم", "label.create-user": "أنشِئ مستخدم",
"label.created": "أُنشئت", "label.created": "أُنشئت",
"label.created-by": "أُنشئ من قبل", "label.created-by": "أُنشئ من قبل",
"label.current": "Current", "label.current": "الحالي",
"label.current-password": "كلمة المرور الحالية", "label.current-password": "كلمة المرور الحالية",
"label.custom-range": "فترة مخصّصة", "label.custom-range": "فترة مخصّصة",
"label.dashboard": "الشاشة الرئيسية", "label.dashboard": "لوحة التحكم",
"label.data": "البيانات", "label.data": "البيانات",
"label.date": "التاريخ", "label.date": "التاريخ",
"label.date-range": "فترة مخصّصة", "label.date-range": "فترة مخصّصة",
@ -58,19 +60,19 @@
"label.device": "الجهاز", "label.device": "الجهاز",
"label.devices": "الأجهزة", "label.devices": "الأجهزة",
"label.dismiss": "تجاهل", "label.dismiss": "تجاهل",
"label.does-not-contain": "لا يحتوي", "label.does-not-contain": "لا يحتوي على",
"label.domain": "النطاق", "label.domain": "النطاق",
"label.dropoff": "إنزال", "label.dropoff": "إنزال",
"label.edit": "عدّل", "label.edit": "تعديل",
"label.edit-dashboard": "عدّل لوحة التحكم", "label.edit-dashboard": "عدّل لوحة التحكم",
"label.edit-member": "عدّل العضو", "label.edit-member": "عدّل العضو",
"label.enable-share-url": "فعّل مشاركة الرابط", "label.enable-share-url": "فعّل مشاركة الرابط",
"label.end-step": "End Step", "label.end-step": "الخطوة الأخيرة",
"label.entry": "Entry URL", "label.entry": "رابط الدخول",
"label.event": "الحدث", "label.event": "الحدث",
"label.event-data": "تاريخ الحدث", "label.event-data": "تاريخ الحدث",
"label.events": "الأحداث", "label.events": "الأحداث",
"label.exit": "Exit URL", "label.exit": "رابط المغادرة",
"label.false": "خطأ", "label.false": "خطأ",
"label.field": "الحقل", "label.field": "الحقل",
"label.fields": "الحقول", "label.fields": "الحقول",
@ -78,33 +80,33 @@
"label.filter-combined": "مُجمّعة", "label.filter-combined": "مُجمّعة",
"label.filter-raw": "خام", "label.filter-raw": "خام",
"label.filters": "التصفيات", "label.filters": "التصفيات",
"label.first-seen": "First seen", "label.first-seen": "أول ظهور",
"label.funnel": "قمع", "label.funnel": "قمع",
"label.funnel-description": "فهم معدل التحويل والانقطاع عن المستخدمين.", "label.funnel-description": "فهم معدل التحويل والانقطاع عن المستخدمين.",
"label.goal": "Goal", "label.goal": "الهدف",
"label.goals": "Goals", "label.goals": "الأهداف",
"label.goals-description": "Track your goals for pageviews and events.", "label.goals-description": "تابع تحقق أهدافك المرتبطة بمشاهدات الصفحات والأحداث.",
"label.greater-than": "أكبَر مِن", "label.greater-than": "أكبَر مِن",
"label.greater-than-equals": "أكبَر مِن أو يساوي", "label.greater-than-equals": "أكبَر مِن أو يساوي",
"label.host": "Host", "label.host": "Host",
"label.hosts": "Hosts", "label.hosts": "Hosts",
"label.insights": "نتائج التحليلات", "label.insights": "نتائج التحليلات",
"label.insights-description": "تعمق في بياناتك باستخدام الشرائح والتصفيات.", "label.insights-description": "تعمق في بياناتك باستخدام الشرائح والتصفيات.",
"label.is": "هو", "label.is": "يساوي",
"label.is-not": م", "label.is-not": ا يساوي",
"label.is-not-set": "لم ضُبط", "label.is-not-set": "لم ضُبط",
"label.is-set": "ضُبط", "label.is-set": "ضُبط",
"label.join": "انضم", "label.join": "انضم",
"label.join-team": "انضم للفريق", "label.join-team": "انضم للفريق",
"label.journey": "Journey", "label.journey": "رحلة المستخدم",
"label.journey-description": "Understand how users navigate through your website.", "label.journey-description": "تعرّف على كيفية تنقّل المستخدمين داخل موقعك.",
"label.language": "اللغة", "label.language": "اللغة",
"label.languages": "اللغات", "label.languages": "اللغات",
"label.laptop": "لابتوب", "label.laptop": "لابتوب",
"label.last-days": "آخر {x} يوم/ايام", "label.last-days": "آخر {x} يوم/ايام",
"label.last-hours": "آخر {x} ساعة", "label.last-hours": "آخر {x} ساعة",
"label.last-months": "Last {x} months", "label.last-months": "آخر {x} شهر/أشهر",
"label.last-seen": "Last seen", "label.last-seen": "آخر ظهور",
"label.leave": "غادر", "label.leave": "غادر",
"label.leave-team": "مغادرة المجموعة", "label.leave-team": "مغادرة المجموعة",
"label.less-than": "أقل مِن", "label.less-than": "أقل مِن",
@ -112,7 +114,7 @@
"label.login": "تسجيل الدخول", "label.login": "تسجيل الدخول",
"label.logout": "تسجيل الخروج", "label.logout": "تسجيل الخروج",
"label.manage": "التحكم", "label.manage": "التحكم",
"label.manager": "Manager", "label.manager": "مدير",
"label.max": "الحد الأقصى", "label.max": "الحد الأقصى",
"label.member": "عضو", "label.member": "عضو",
"label.members": "الأعضاء", "label.members": "الأعضاء",
@ -134,15 +136,15 @@
"label.pageTitle": "عنوان الصفحة", "label.pageTitle": "عنوان الصفحة",
"label.pages": "الصفحات", "label.pages": "الصفحات",
"label.password": "كلمة المرور", "label.password": "كلمة المرور",
"label.path": "Path", "label.path": "المسار",
"label.paths": "Paths", "label.paths": "المسارات",
"label.powered-by": "مشغل بواسطة {name}", "label.powered-by": "مشغل بواسطة {name}",
"label.previous": "Previous", "label.previous": "السابق",
"label.previous-period": "Previous period", "label.previous-period": "الفترة السابقة",
"label.previous-year": "Previous year", "label.previous-year": "العام السابق",
"label.profile": "الملف الشخصي", "label.profile": "الملف الشخصي",
"label.properties": "Properties", "label.properties": "الخصائص",
"label.property": "Property", "label.property": "الخاصية",
"label.queries": "استعلامات", "label.queries": "استعلامات",
"label.query": "استعلام", "label.query": "استعلام",
"label.query-parameters": "متغيرات الرابط", "label.query-parameters": "متغيرات الرابط",
@ -161,9 +163,9 @@
"label.reset-website": "اعادة تعيين الإحصائيات", "label.reset-website": "اعادة تعيين الإحصائيات",
"label.retention": "الاحتفاظ", "label.retention": "الاحتفاظ",
"label.retention-description": "قس مدى ثبات موقعك على الويب من خلال تتبع عدد مرات عودة المستخدمين.", "label.retention-description": "قس مدى ثبات موقعك على الويب من خلال تتبع عدد مرات عودة المستخدمين.",
"label.revenue": "Revenue", "label.revenue": "الإيرادات",
"label.revenue-description": "Look into your revenue across time.", "label.revenue-description": "قم بإلقاء نظرة على بيانات إيراداتك وكيفية إنفاق المستخدمين.",
"label.revenue-property": "Revenue Property", "label.revenue-property": "خاصية الإيرادات",
"label.role": "الصلاحية", "label.role": "الصلاحية",
"label.run-query": "شغّل الاستعلام", "label.run-query": "شغّل الاستعلام",
"label.save": "حفظ", "label.save": "حفظ",
@ -173,22 +175,24 @@
"label.select-date": "حدد التاريخ", "label.select-date": "حدد التاريخ",
"label.select-role": "حدد الدور", "label.select-role": "حدد الدور",
"label.select-website": "حدد موقع", "label.select-website": "حدد موقع",
"label.session": "Session", "label.session": "الزيارة",
"label.sessions": "الزيارات", "label.sessions": "الزيارات",
"label.settings": "الإعدادات", "label.settings": "الإعدادات",
"label.share-url": "مشاركة الرابط", "label.share-url": "مشاركة الرابط",
"label.single-day": "يوم واحد", "label.single-day": "يوم واحد",
"label.start-step": "Start Step", "label.start-step": "الخطوة الأولى",
"label.steps": "Steps", "label.steps": "الخطوات",
"label.sum": "المجموع", "label.sum": "المجموع",
"label.tablet": "تابلت", "label.tablet": "تابلت",
"label.tag": "الوسم",
"label.tags": "الوسوم",
"label.team": "الفريق", "label.team": "الفريق",
"label.team-id": "معرّف الفريق", "label.team-id": "معرّف الفريق",
"label.team-manager": "Team manager", "label.team-manager": "مدير الفريق",
"label.team-member": "عضو الفريق", "label.team-member": "عضو الفريق",
"label.team-name": "اسم الفريق", "label.team-name": "اسم الفريق",
"label.team-owner": "مدير الفريق", "label.team-owner": "مدير الفريق",
"label.team-view-only": "Team view only", "label.team-view-only": "عرض الفريق فقط",
"label.team-websites": "مواقع الفريق", "label.team-websites": "مواقع الفريق",
"label.teams": "الفرق", "label.teams": "الفرق",
"label.theme": "السمة", "label.theme": "السمة",
@ -202,34 +206,34 @@
"label.total": "الإجمالي", "label.total": "الإجمالي",
"label.total-records": "إجمالي السجلات", "label.total-records": "إجمالي السجلات",
"label.tracking-code": "كود التتبع", "label.tracking-code": "كود التتبع",
"label.transactions": "Transactions", "label.transactions": "المعاملات",
"label.transfer": "Transfer", "label.transfer": "نقل",
"label.transfer-website": "انقل الموقع", "label.transfer-website": "انقل الموقع",
"label.true": "حقيقي", "label.true": "حقيقي",
"label.type": "النوع", "label.type": "النوع",
"label.unique": "فريد", "label.unique": "فريد",
"label.unique-visitors": "زائرون فريدون", "label.unique-visitors": "زائرون فريدون",
"label.uniqueCustomers": "Unique Customers", "label.uniqueCustomers": "العملاء الفريدون",
"label.unknown": "غير معروف", "label.unknown": "غير معروف",
"label.untitled": "بدون عنوان", "label.untitled": "بدون عنوان",
"label.update": "Update", "label.update": "تحديث",
"label.url": "URL", "label.url": "الرابط",
"label.urls": "URLs", "label.urls": "الروابط",
"label.user": "المستخدم", "label.user": "المستخدم",
"label.user-property": "User Property", "label.user-property": "سمات المستخدم",
"label.username": "اسم المستخدم", "label.username": "اسم المستخدم",
"label.users": "المستخدمين", "label.users": "المستخدمين",
"label.utm": "UTM", "label.utm": "UTM",
"label.utm-description": "Track your campaigns through UTM parameters.", "label.utm-description": "تابع حملاتك التسويقية باستخدام معلمات UTM.",
"label.value": "القيمة", "label.value": "القيمة",
"label.view": "عرض", "label.view": "عرض",
"label.view-details": "عرض التفاصيل", "label.view-details": "عرض التفاصيل",
"label.view-only": "عرض فقط", "label.view-only": "عرض فقط",
"label.views": "المشاهدات", "label.views": "المشاهدات",
"label.views-per-visit": "Views per visit", "label.views-per-visit": "مشاهدات لكل زيارة",
"label.visit-duration": "متوسط وقت الزيارة", "label.visit-duration": "متوسط وقت الزيارة",
"label.visitors": "الزوار", "label.visitors": "الزوار",
"label.visits": "Visits", "label.visits": "الزيارات",
"label.website": "الموقع", "label.website": "الموقع",
"label.website-id": "معرّف الموقع", "label.website-id": "معرّف الموقع",
"label.websites": "المواقع", "label.websites": "المواقع",
@ -237,7 +241,7 @@
"label.yesterday": "الأمس", "label.yesterday": "الأمس",
"message.action-confirmation": "اكتب {confirmation} في المربع أدناه للتأكيد.", "message.action-confirmation": "اكتب {confirmation} في المربع أدناه للتأكيد.",
"message.active-users": "{x} حاليا {x, plural, one {زائر واحد} other {زوار}}", "message.active-users": "{x} حاليا {x, plural, one {زائر واحد} other {زوار}}",
"message.collected-data": "Collected data", "message.collected-data": "البيانات المجمعة",
"message.confirm-delete": "هل أنت متأكد من حذف {target}?", "message.confirm-delete": "هل أنت متأكد من حذف {target}?",
"message.confirm-leave": "هل أنت متأكد من مغادرة {target}?", "message.confirm-leave": "هل أنت متأكد من مغادرة {target}?",
"message.confirm-remove": "هل انت متأكد من حذف {target}?", "message.confirm-remove": "هل انت متأكد من حذف {target}?",
@ -261,9 +265,9 @@
"message.no-websites-configured": "لم تقم بإعداد اي موقع.", "message.no-websites-configured": "لم تقم بإعداد اي موقع.",
"message.page-not-found": "الصفحة غير موجودة.", "message.page-not-found": "الصفحة غير موجودة.",
"message.reset-website": "لإعادة ضبط موقع الويب هذا، اكتب {confirmation} في المربع أدناه للتأكيد.", "message.reset-website": "لإعادة ضبط موقع الويب هذا، اكتب {confirmation} في المربع أدناه للتأكيد.",
"message.reset-website-warning": "سيتم اعادة تعيين كافة الإحصائيات لهذا الموقع، لكن لن يتم تعيير كود التتبع", "message.reset-website-warning": "سيتم اعادة تعيين كافة الإحصائيات لهذا الموقع، لكن لن يتم تغيير كود التتبع",
"message.saved": "تم الحفظ بنجاح.", "message.saved": "تم الحفظ بنجاح.",
"message.share-url": "هذا الرابط الذي تم مشاركته بشكل عام لـ {target}.", "message.share-url": "إحصائيات موقعك متاحة للجميع على الرابط التالي:",
"message.team-already-member": "أنت عضو في الفريق", "message.team-already-member": "أنت عضو في الفريق",
"message.team-not-found": "لم يتم العثور على الفريق", "message.team-not-found": "لم يتم العثور على الفريق",
"message.team-websites-info": "يمكن مشاهدة الموقع من اي عضو في الفريق.", "message.team-websites-info": "يمكن مشاهدة الموقع من اي عضو في الفريق.",

View file

@ -124,7 +124,9 @@ export async function getLocation(ip: string = '', headers: Headers, hasPayloadI
if (!global[MAXMIND]) { if (!global[MAXMIND]) {
const dir = path.join(process.cwd(), 'geo'); const dir = path.join(process.cwd(), 'geo');
global[MAXMIND] = await maxmind.open(path.resolve(dir, 'GeoLite2-City.mmdb')); global[MAXMIND] = await maxmind.open(
process.env.GEOLITE_DB_PATH || path.resolve(dir, 'GeoLite2-City.mmdb'),
);
} }
const result = global[MAXMIND].get(ip); const result = global[MAXMIND].get(ip);

View file

@ -5,6 +5,7 @@ import kafka from '@/lib/kafka';
import prisma from '@/lib/prisma'; import prisma from '@/lib/prisma';
import { uuid } from '@/lib/crypto'; import { uuid } from '@/lib/crypto';
import { saveEventData } from './saveEventData'; import { saveEventData } from './saveEventData';
import { saveRevenue } from './saveRevenue';
export interface SaveEventArgs { export interface SaveEventArgs {
websiteId: string; websiteId: string;
@ -130,6 +131,20 @@ async function relationalQuery({
eventData, eventData,
createdAt, createdAt,
}); });
const { revenue, currency } = eventData;
if (revenue > 0 && currency) {
await saveRevenue({
websiteId,
sessionId,
eventId: websiteEventId,
eventName: eventName?.substring(0, EVENT_NAME_LENGTH),
currency,
revenue,
createdAt,
});
}
} }
} }

View file

@ -0,0 +1,36 @@
import { uuid } from '@/lib/crypto';
import { PRISMA, runQuery } from '@/lib/db';
import prisma from '@/lib/prisma';
export interface SaveRevenueArgs {
websiteId: string;
sessionId: string;
eventId: string;
eventName: string;
currency: string;
revenue: number;
createdAt: Date;
}
export async function saveRevenue(data: SaveRevenueArgs) {
return runQuery({
[PRISMA]: () => relationalQuery(data),
});
}
async function relationalQuery(data: SaveRevenueArgs) {
const { websiteId, sessionId, eventId, eventName, currency, revenue, createdAt } = data;
await prisma.client.revenue.create({
data: {
id: uuid(),
websiteId,
sessionId,
eventId,
eventName,
currency,
revenue,
createdAt,
},
});
}

View file

@ -79,24 +79,14 @@ async function relationalQuery(
const revenueEventQuery = `WITH events AS ( const revenueEventQuery = `WITH events AS (
select select
we.session_id, session_id,
max(ed.created_at) max_dt, max(created_at) max_dt,
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) value sum(revenue) value
from event_data ed from revenue
join website_event we
on we.event_id = ed.website_event_id
and we.website_id = ed.website_id
join (select website_event_id
from event_data
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 data_key ${like} '%currency%'
and string_value = {{currency}}) currency
on currency.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ${column} = {{conversionStep}} and ${column} = {{conversionStep}}
and ed.data_key ${like} '%revenue%' and currency ${like} {{currency}}
group by 1),`; group by 1),`;
function getModelQuery(model: string) { function getModelQuery(model: string) {
@ -311,21 +301,14 @@ async function clickhouseQuery(
const revenueEventQuery = `WITH events AS ( const revenueEventQuery = `WITH events AS (
select select
ed.session_id, session_id,
max(ed.created_at) max_dt, max(created_at) max_dt,
sum(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as value sum(revenue) as value
from event_data ed from website_revenue
join (select event_id
from event_data
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'currency') > 0
and string_value = {currency:String}) c
on c.event_id = ed.event_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}
and ${column} = {conversionStep:String} and ${column} = {conversionStep:String}
and positionCaseInsensitive(ed.data_key, 'revenue') > 0 and currency = {currency:String}
group by 1),`; group by 1),`;
function getModelQuery(model: string) { function getModelQuery(model: string) {

View file

@ -48,22 +48,13 @@ async function relationalQuery(
const chartRes = await rawQuery( const chartRes = await rawQuery(
` `
select select
we.event_name x, event_name x,
${getDateSQL('ed.created_at', unit, timezone)} t, ${getDateSQL('created_at', unit, timezone)} t,
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) y sum(revenue) y
from event_data ed from revenue
join website_event we
on we.event_id = ed.website_event_id
join (select website_event_id
from event_data
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 data_key ${like} '%currency%' and currency ${like} {{currency}}
and string_value = {{currency}}) currency
on currency.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
group by x, t group by x, t
order by t order by t
`, `,
@ -74,22 +65,13 @@ async function relationalQuery(
` `
select select
s.country as name, s.country as name,
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) value sum(r.revenue) value
from event_data ed from revenue r
join website_event we
on we.event_id = ed.website_event_id
join session s join session s
on s.session_id = we.session_id on s.session_id = r.session_id
join (select website_event_id where r.website_id = {{websiteId::uuid}}
from event_data and r.created_at between {{startDate}} and {{endDate}}
where website_id = {{websiteId::uuid}} and r.currency ${like} {{currency}}
and created_at between {{startDate}} and {{endDate}}
and data_key ${like} '%currency%'
and string_value = {{currency}}) currency
on currency.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
group by s.country group by s.country
`, `,
{ websiteId, startDate, endDate, currency }, { websiteId, startDate, endDate, currency },
@ -98,22 +80,13 @@ async function relationalQuery(
const totalRes = await rawQuery( const totalRes = await rawQuery(
` `
select select
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as sum, sum(revenue) as sum,
count(distinct event_id) as count, count(distinct event_id) as count,
count(distinct session_id) as unique_count count(distinct session_id) as unique_count
from event_data ed from revenue r
join website_event we
on we.event_id = ed.website_event_id
join (select website_event_id
from event_data
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 data_key ${like} '%currency%' and currency ${like} {{currency}}
and string_value = {{currency}}) currency
on currency.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
`, `,
{ websiteId, startDate, endDate, currency }, { websiteId, startDate, endDate, currency },
).then(result => result?.[0]); ).then(result => result?.[0]);
@ -121,24 +94,15 @@ async function relationalQuery(
const tableRes = await rawQuery( const tableRes = await rawQuery(
` `
select select
c.currency, currency,
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as sum, sum(revenue) as sum,
count(distinct ed.website_event_id) as count, count(distinct event_id) as count,
count(distinct we.session_id) as unique_count count(distinct session_id) as unique_count
from event_data ed from revenue r
join website_event we
on we.event_id = ed.website_event_id
join (select website_event_id, string_value as currency
from event_data
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 data_key ${like} '%currency%') c group by currency
on c.website_event_id = ed.website_event_id order by sum desc
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
group by c.currency
order by sum desc;
`, `,
{ websiteId, startDate, endDate, unit, timezone, currency }, { websiteId, startDate, endDate, unit, timezone, currency },
); );
@ -180,18 +144,11 @@ async function clickhouseQuery(
select select
event_name x, event_name x,
${getDateSQL('created_at', unit, timezone)} t, ${getDateSQL('created_at', unit, timezone)} t,
sum(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) y sum(revenue) y
from event_data from website_revenue
join (select event_id
from event_data
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 positionCaseInsensitive(data_key, 'currency') > 0 and currency = {currency:String}
and string_value = {currency:String}) currency
on currency.event_id = event_data.event_id
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'revenue') > 0
group by x, t group by x, t
order by t order by t
`, `,
@ -207,23 +164,16 @@ async function clickhouseQuery(
` `
select select
s.country as name, s.country as name,
sum(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as value sum(w.revenue) as value
from event_data ed from website_revenue w
join (select event_id
from event_data
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'currency') > 0
and string_value = {currency:String}) c
on c.event_id = ed.event_id
join (select distinct website_id, session_id, country join (select distinct website_id, session_id, country
from website_event_stats_hourly from website_event_stats_hourly
where website_id = {websiteId:UUID}) s where website_id = {websiteId:UUID}) s
on ed.website_id = s.website_id on w.website_id = s.website_id
and ed.session_id = s.session_id and w.session_id = s.session_id
where ed.website_id = {websiteId:UUID} where w.website_id = {websiteId:UUID}
and ed.created_at between {startDate:DateTime64} and {endDate:DateTime64} and w.created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(ed.data_key, 'revenue') > 0 and w.currency = {currency:String}
group by s.country group by s.country
`, `,
{ websiteId, startDate, endDate, currency }, { websiteId, startDate, endDate, currency },
@ -237,20 +187,13 @@ async function clickhouseQuery(
}>( }>(
` `
select select
sum(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as sum, sum(revenue) as sum,
uniqExact(event_id) as count, uniqExact(event_id) as count,
uniqExact(session_id) as unique_count uniqExact(session_id) as unique_count
from event_data from website_revenue
join (select event_id
from event_data
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 positionCaseInsensitive(data_key, 'currency') > 0 and currency = {currency:String}
and string_value = {currency:String}) currency
on currency.event_id = event_data.event_id
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'revenue') > 0
`, `,
{ websiteId, startDate, endDate, currency }, { websiteId, startDate, endDate, currency },
).then(result => result?.[0]); ).then(result => result?.[0]);
@ -266,22 +209,15 @@ async function clickhouseQuery(
>( >(
` `
select select
c.currency, currency,
sum(coalesce(toDecimal64(ed.number_value, 2), toDecimal64(ed.string_value, 2))) as sum, sum(revenue) as sum,
uniqExact(ed.event_id) as count, uniqExact(event_id) as count,
uniqExact(ed.session_id) as unique_count uniqExact(session_id) as unique_count
from event_data ed from website_revenue
join (select event_id, string_value as currency
from event_data
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 positionCaseInsensitive(data_key, 'currency') > 0) c group by currency
on c.event_id = ed.event_id order by sum desc
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'revenue') > 0
group by c.currency
order by sum desc;
`, `,
{ websiteId, startDate, endDate, unit, timezone, currency }, { websiteId, startDate, endDate, unit, timezone, currency },
); );