diff --git a/public/intl/messages/en-US.json b/public/intl/messages/en-US.json
index d455978f5..e68c428a5 100644
--- a/public/intl/messages/en-US.json
+++ b/public/intl/messages/en-US.json
@@ -332,6 +332,8 @@
"unique": "Unique",
"unique-events": "Unique events",
"unique-visitors": "Unique visitors",
+ "aov": "AOV",
+ "arpu": "ARPU",
"uniqueCustomers": "Unique Customers",
"unknown": "Unknown",
"untitled": "Untitled",
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/revenue/Revenue.tsx b/src/app/(main)/websites/[websiteId]/(reports)/revenue/Revenue.tsx
index abf06aead..c45d0b8b4 100644
--- a/src/app/(main)/websites/[websiteId]/(reports)/revenue/Revenue.tsx
+++ b/src/app/(main)/websites/[websiteId]/(reports)/revenue/Revenue.tsx
@@ -44,7 +44,7 @@ export function Revenue({ websiteId, startDate, endDate, unit }: RevenueProps) {
const metrics = useMemo(() => {
if (!data) return [];
- const { sum, count, average, unique_count, comparison } = data.total;
+ const { sum, count, average, unique_count, arpu, comparison } = data.total;
return [
{
@@ -55,10 +55,16 @@ export function Revenue({ websiteId, startDate, endDate, unit }: RevenueProps) {
},
{
value: average,
- label: t(labels.average),
+ label: t(labels.aov),
change: comparison ? average - comparison.average : 0,
formatValue: (n: number) => formatLongCurrency(n, currency),
},
+ {
+ value: arpu,
+ label: t(labels.arpu),
+ change: comparison ? arpu - (comparison.arpu ?? 0) : 0,
+ formatValue: (n: number) => formatLongCurrency(n, currency),
+ },
{
value: count,
label: t(labels.transactions),
diff --git a/src/app/(main)/websites/[websiteId]/(reports)/revenue/RevenueTable.tsx b/src/app/(main)/websites/[websiteId]/(reports)/revenue/RevenueTable.tsx
deleted file mode 100644
index f8164147f..000000000
--- a/src/app/(main)/websites/[websiteId]/(reports)/revenue/RevenueTable.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { DataColumn, DataTable } from '@umami/react-zen';
-import { useMessages } from '@/components/hooks';
-import { formatLongCurrency } from '@/lib/format';
-
-export function RevenueTable({ data = [] }) {
- const { t, labels } = useMessages();
-
- return (
-
-
-
- {(row: any) => formatLongCurrency(row.sum, row.currency)}
-
-
- {(row: any) => formatLongCurrency(row.count ? row.sum / row.count : 0, row.currency)}
-
-
-
-
- );
-}
diff --git a/src/components/messages.ts b/src/components/messages.ts
index 9b403b43b..da1c81aac 100644
--- a/src/components/messages.ts
+++ b/src/components/messages.ts
@@ -255,6 +255,8 @@ export const labels: Record = {
myAccount: 'label.my-account',
transfer: 'label.transfer',
transactions: 'label.transactions',
+ aov: 'label.aov',
+ arpu: 'label.arpu',
uniqueCustomers: 'label.uniqueCustomers',
viewedPage: 'message.viewed-page',
collectedData: 'message.collected-data',
diff --git a/src/queries/sql/reports/getRevenueStats.ts b/src/queries/sql/reports/getRevenueStats.ts
index c0eac90fe..116166133 100644
--- a/src/queries/sql/reports/getRevenueStats.ts
+++ b/src/queries/sql/reports/getRevenueStats.ts
@@ -9,6 +9,7 @@ export interface RevenueStatsResult {
count: number;
average: number;
unique_count: number;
+ arpu: number;
}
export async function getRevenueStats(
@@ -52,7 +53,11 @@ async function relationalQuery(
select
sum(revenue.revenue) as sum,
count(distinct revenue.event_id) as count,
- count(distinct revenue.session_id) as unique_count
+ count(distinct revenue.session_id) as unique_count,
+ (select count(distinct session_id)
+ from website_event
+ where website_id = {{websiteId::uuid}}
+ and created_at between {{startDate}} and {{endDate}}) as total_sessions
from revenue
${joinQuery}
${cohortQuery}
@@ -66,6 +71,7 @@ async function relationalQuery(
).then(result => result?.[0]);
total.average = total.count > 0 ? Number(total.sum) / Number(total.count) : 0;
+ total.arpu = total.total_sessions > 0 ? Number(total.sum) / Number(total.total_sessions) : 0;
return total;
}
@@ -97,12 +103,21 @@ async function clickhouseQuery(
and website_event.event_id = website_revenue.event_id`
: '';
- const total = await rawQuery<{ sum: number; count: number; unique_count: number }>(
+ const total = await rawQuery<{
+ sum: number;
+ count: number;
+ unique_count: number;
+ total_sessions: number;
+ }>(
`
select
sum(website_revenue.revenue) as sum,
uniqExact(website_revenue.event_id) as count,
- uniqExact(website_revenue.session_id) as unique_count
+ uniqExact(website_revenue.session_id) as unique_count,
+ (select uniqExact(session_id)
+ from website_event
+ where website_id = {websiteId:UUID}
+ and created_at between {startDate:DateTime64} and {endDate:DateTime64}) as total_sessions
from website_revenue
${joinQuery}
${cohortQuery}
@@ -115,6 +130,7 @@ async function clickhouseQuery(
).then(result => result?.[0]);
total.average = total.count > 0 ? total.sum / total.count : 0;
+ total.arpu = total.total_sessions > 0 ? total.sum / total.total_sessions : 0;
return total;
}