Skip to content

Commit 28c4162

Browse files
committed
cleanup pricing
1 parent 54c66dc commit 28c4162

File tree

9 files changed

+223
-45
lines changed

9 files changed

+223
-45
lines changed

apps/api/src/query/builders/sessions.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ export const SessionsBuilders: Record<string, SimpleQueryConfig> = {
66
table: Analytics.events,
77
fields: [
88
"COUNT(DISTINCT session_id) as total_sessions",
9-
"median(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END) as median_session_duration",
9+
"AVG(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END) as avg_session_duration",
10+
"AVG(CASE WHEN is_bounce = 1 THEN 100 ELSE 0 END) as bounce_rate",
1011
"COUNT(*) as total_events",
1112
],
1213
where: ["event_name = 'screen_view'"],
@@ -41,7 +42,7 @@ export const SessionsBuilders: Record<string, SimpleQueryConfig> = {
4142
"device_type as name",
4243
"COUNT(DISTINCT session_id) as sessions",
4344
"COUNT(DISTINCT anonymous_id) as visitors",
44-
"ROUND(median(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END), 2) as median_session_duration",
45+
"ROUND(AVG(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END), 2) as avg_session_duration",
4546
],
4647
where: ["event_name = 'screen_view'", "device_type != ''"],
4748
groupBy: ["device_type"],
@@ -56,7 +57,7 @@ export const SessionsBuilders: Record<string, SimpleQueryConfig> = {
5657
"browser_name as name",
5758
"COUNT(DISTINCT session_id) as sessions",
5859
"COUNT(DISTINCT anonymous_id) as visitors",
59-
"ROUND(median(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END), 2) as median_session_duration",
60+
"ROUND(AVG(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END), 2) as avg_session_duration",
6061
],
6162
where: ["event_name = 'screen_view'", "browser_name != ''"],
6263
groupBy: ["browser_name"],
@@ -72,7 +73,7 @@ export const SessionsBuilders: Record<string, SimpleQueryConfig> = {
7273
"toDate(time) as date",
7374
"COUNT(DISTINCT session_id) as sessions",
7475
"COUNT(DISTINCT anonymous_id) as visitors",
75-
"ROUND(median(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END), 2) as median_session_duration",
76+
"ROUND(AVG(CASE WHEN time_on_page > 0 THEN time_on_page / 1000 ELSE NULL END), 2) as avg_session_duration",
7677
],
7778
where: ["event_name = 'screen_view'"],
7879
groupBy: ["toDate(time)"],

apps/api/src/query/builders/summary.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
3939
name: "median_session_duration",
4040
type: "number",
4141
label: "Median Session Duration",
42-
description: "Median session duration in seconds",
42+
description: "Median time spent actively on pages",
4343
unit: "seconds",
4444
},
4545
{
@@ -81,7 +81,8 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
8181
const baseEventsQuery = helpers?.sessionAttributionCTE
8282
? `base_events AS (
8383
SELECT e.session_id, e.anonymous_id, e.event_name,
84-
toTimeZone(e.time, {timezone:String}) as normalized_time
84+
toTimeZone(e.time, {timezone:String}) as normalized_time,
85+
e.time_on_page
8586
FROM analytics.events e
8687
${helpers.sessionAttributionJoin("e")}
8788
WHERE e.client_id = {websiteId:String}
@@ -92,7 +93,8 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
9293
),`
9394
: `base_events AS (
9495
SELECT session_id, anonymous_id, event_name,
95-
toTimeZone(time, {timezone:String}) as normalized_time
96+
toTimeZone(time, {timezone:String}) as normalized_time,
97+
time_on_page
9698
FROM analytics.events
9799
WHERE client_id = {websiteId:String}
98100
AND time >= toDateTime({startDate:String})
@@ -108,8 +110,8 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
108110
session_agg AS (
109111
SELECT session_id,
110112
countIf(event_name = 'screen_view') as page_count,
111-
countIf(event_name != 'screen_view') as engagement_count,
112-
dateDiff('second', min(normalized_time), max(normalized_time)) as duration
113+
countIf(event_name != 'screen_view' AND event_name != 'page_exit') as engagement_count,
114+
sumIf(time_on_page, event_name = 'page_exit' AND time_on_page > 0) as duration
113115
FROM base_events
114116
GROUP BY session_id
115117
),
@@ -225,7 +227,7 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
225227
name: "median_session_duration",
226228
type: "number",
227229
label: "Median Session Duration",
228-
description: "Median session duration in seconds",
230+
description: "Median time spent actively on pages",
229231
unit: "seconds",
230232
},
231233
{
@@ -273,7 +275,8 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
273275
const baseEventsQuery = helpers?.sessionAttributionCTE
274276
? `base_events AS (
275277
SELECT e.session_id, e.anonymous_id, e.event_name,
276-
toTimeZone(e.time, {timezone:String}) as normalized_time
278+
toTimeZone(e.time, {timezone:String}) as normalized_time,
279+
e.time_on_page
277280
FROM analytics.events e
278281
${helpers.sessionAttributionJoin("e")}
279282
WHERE e.client_id = {websiteId:String}
@@ -283,7 +286,8 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
283286
),`
284287
: `base_events AS (
285288
SELECT session_id, anonymous_id, event_name,
286-
toTimeZone(time, {timezone:String}) as normalized_time
289+
toTimeZone(time, {timezone:String}) as normalized_time,
290+
time_on_page
287291
FROM analytics.events
288292
WHERE client_id = {websiteId:String}
289293
AND ${dateFilter}
@@ -299,8 +303,8 @@ export const SummaryBuilders: Record<string, SimpleQueryConfig> = {
299303
SELECT session_id,
300304
${timeBucketFn}(minIf(normalized_time, event_name = 'screen_view')) as time_bucket,
301305
countIf(event_name = 'screen_view') as page_count,
302-
countIf(event_name != 'screen_view') as engagement_count,
303-
dateDiff('second', min(normalized_time), max(normalized_time)) as duration
306+
countIf(event_name != 'screen_view' AND event_name != 'page_exit') as engagement_count,
307+
sumIf(time_on_page, event_name = 'page_exit' AND time_on_page > 0) as duration
304308
FROM base_events
305309
GROUP BY session_id
306310
),

apps/dashboard/app/(main)/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { DevToolsDrawer } from "@/components/dev-tools/dev-tools-drawer";
12
import { Sidebar } from "@/components/layout/sidebar";
23
import { CommandSearch } from "@/components/ui/command-search";
34

@@ -10,6 +11,7 @@ export default function MainLayout({
1011
<div className="h-screen overflow-hidden text-foreground">
1112
<Sidebar />
1213
<CommandSearch />
14+
<DevToolsDrawer />
1315
<div className="relative h-screen pl-0 md:pl-76 lg:pl-84">
1416
<div className="h-screen overflow-y-auto overflow-x-hidden pt-12 md:pt-0">
1517
{children}

apps/dashboard/app/(main)/settings/analytics/page.tsx

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,28 @@
22

33
import { ChartLineIcon } from "@phosphor-icons/react";
44
import { RightSidebar } from "@/components/right-sidebar";
5-
import { ComingSoon } from "../_components/settings-section";
5+
import { SettingsSection } from "../_components/settings-section";
66

77
export default function AnalyticsSettingsPage() {
88
return (
99
<div className="h-full lg:grid lg:grid-cols-[1fr_18rem]">
1010
<div className="flex flex-col">
11-
<ComingSoon
12-
description="Configure default date ranges, timezones, auto-refresh behavior, and bot filtering. We're working on making these settings available soon."
13-
icon={
14-
<ChartLineIcon
15-
className="size-8 text-muted-foreground"
16-
weight="duotone"
17-
/>
18-
}
19-
title="Analytics Settings Coming Soon"
20-
/>
11+
<SettingsSection
12+
description="Configure analytics display preferences"
13+
title="Analytics Settings"
14+
>
15+
<div className="flex flex-col items-center justify-center gap-3 py-12 text-center">
16+
<ChartLineIcon className="size-12 text-muted-foreground" weight="duotone" />
17+
<p className="text-muted-foreground text-sm">
18+
Analytics settings coming soon
19+
</p>
20+
</div>
21+
</SettingsSection>
2122
</div>
2223

2324
<RightSidebar className="gap-0 p-0">
24-
<RightSidebar.Section border title="Planned Settings">
25-
<div className="space-y-2 text-muted-foreground text-sm">
26-
<p>• Default date range</p>
27-
<p>• Timezone preferences</p>
28-
<p>• Auto-refresh behavior</p>
29-
<p>• Bot filtering options</p>
30-
</div>
31-
</RightSidebar.Section>
32-
3325
<RightSidebar.Section>
34-
<RightSidebar.Tip description="These settings will let you customize how analytics are displayed across all your websites." />
26+
<RightSidebar.Tip description="Analytics settings will allow you to customize how metrics are calculated and displayed." />
3527
</RightSidebar.Section>
3628
</RightSidebar>
3729
</div>

apps/dashboard/app/(main)/websites/[id]/_components/tabs/overview-tab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ export function WebsiteOverviewTab({
840840
},
841841
{
842842
id: "session-duration-chart",
843-
title: "Median Duration",
843+
title: "Session Duration",
844844
value: (() => {
845845
const duration = analytics.summary?.median_session_duration;
846846
if (!duration) {

apps/dashboard/components/autumn/pricing-table.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ export default function PricingTable({
135135

136136
const filteredProducts =
137137
products?.filter(
138-
(p) => p.id !== "free" && p.id !== "verification_fee" && intervalFilter(p)
138+
(p) =>
139+
p.id !== "free" &&
140+
p.id !== "verification_fee" &&
141+
!(p as Product & { is_add_on?: boolean }).is_add_on &&
142+
intervalFilter(p)
139143
) ?? [];
140144

141145
return (
@@ -151,7 +155,11 @@ export default function PricingTable({
151155
disabled:
152156
plan.scenario === "active" || plan.scenario === "scheduled",
153157
onClick: async () => {
154-
await attach({ productId: plan.id, dialog: AttachDialog });
158+
await attach({
159+
productId: plan.id,
160+
dialog: AttachDialog,
161+
...(plan.id === "hobby" && { reward: "SAVE80" }),
162+
});
155163
},
156164
}}
157165
isSelected={selectedPlan === plan.id}
@@ -382,11 +390,11 @@ function PricingCard({
382390
<div className="p-5 pt-0">
383391
<PricingCardButton
384392
disabled={buttonProps?.disabled}
385-
onClick={() => {
393+
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
386394
if (isDowngrade) {
387395
setShowDowngradeDialog(true);
388396
} else {
389-
buttonProps?.onClick?.();
397+
buttonProps?.onClick?.(e);
390398
}
391399
}}
392400
recommended={isRecommended}
@@ -401,7 +409,11 @@ function PricingCard({
401409
onClose={() => setShowDowngradeDialog(false)}
402410
onConfirm={async () => {
403411
setShowDowngradeDialog(false);
404-
await attach({ productId: product.id, dialog: AttachDialog });
412+
await attach({
413+
productId: product.id,
414+
dialog: AttachDialog,
415+
...(product.id === "hobby" && { reward: "SAVE80" }),
416+
});
405417
}}
406418
productName={productDisplay?.name || name}
407419
/>

0 commit comments

Comments
 (0)