Skip to content

Commit b504d7b

Browse files
Merge pull request #1236 from mykonos-ibiza/feat-product-analytics
feat: analytics on various events
2 parents c7a22d9 + 921925a commit b504d7b

File tree

10 files changed

+115
-2
lines changed

10 files changed

+115
-2
lines changed

frontend/instrumentation-client.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import posthog from 'posthog-js';
2+
3+
if (process.env.NEXT_PUBLIC_POSTHOG_KEY) {
4+
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
5+
api_host: '/ingest',
6+
ui_host: 'https://eu.posthog.com',
7+
defaults: '2025-05-24',
8+
capture_exceptions: true, // This enables capturing exceptions using Error Tracking, set to false if you don't want this
9+
debug: process.env.NODE_ENV === 'development',
10+
});
11+
}

frontend/next.config.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@ import type { NextConfig } from 'next';
22

33
const nextConfig = (): NextConfig => ({
44
output: (process.env.NEXT_OUTPUT as 'standalone') || undefined,
5+
async rewrites() {
6+
return [
7+
{
8+
source: '/ingest/static/:path*',
9+
destination: 'https://eu-assets.i.posthog.com/static/:path*',
10+
},
11+
{
12+
source: '/ingest/:path*',
13+
destination: 'https://eu.i.posthog.com/:path*',
14+
},
15+
{
16+
source: '/ingest/flags',
17+
destination: 'https://eu.i.posthog.com/flags',
18+
},
19+
];
20+
},
21+
skipTrailingSlashRedirect: true,
522
});
623

724
export default nextConfig;

frontend/package-lock.json

Lines changed: 47 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989
"papaparse": "^5.5.2",
9090
"pdfjs-dist": "4.8.69",
9191
"postcss": "8.4.33",
92+
"posthog-js": "^1.258.6",
93+
"posthog-node": "^5.6.0",
9294
"react": "^18",
9395
"react-day-picker": "^8.10.1",
9496
"react-diff-viewer-continued": "^3.4.0",

frontend/src/app/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { Analytics } from '@vercel/analytics/react';
99
import { GoogleAnalytics } from '@next/third-parties/google';
1010
import { SpeedInsights } from '@vercel/speed-insights/next';
1111
import Script from 'next/script';
12+
import { PostHogIdentify } from '@/components/posthog-identify';
1213

1314
const geistSans = Geist({
1415
variable: '--font-geist-sans',
@@ -152,6 +153,7 @@ export default function RootLayout({
152153
<Analytics />
153154
<GoogleAnalytics gaId="G-6ETJFB3PT3" />
154155
<SpeedInsights />
156+
<PostHogIdentify />
155157
</ThemeProvider>
156158
</body>
157159
</html>

frontend/src/components/home/sections/pricing-section.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
import { toast } from 'sonner';
1717
import { isLocalMode, isYearlyCommitmentDowngrade, isPlanChangeAllowed, getPlanInfo } from '@/lib/config';
1818
import { useSubscription, useSubscriptionCommitment } from '@/hooks/react-query';
19+
import posthog from 'posthog-js';
1920

2021
// Constants
2122
export const SUBSCRIPTION_PLANS = {
@@ -241,6 +242,7 @@ function PricingTier({
241242
case 'checkout_created':
242243
case 'commitment_created':
243244
if (response.url) {
245+
posthog.capture('plan_purchase_attempted');
244246
window.location.href = response.url;
245247
} else {
246248
console.error(
@@ -255,6 +257,7 @@ function PricingTier({
255257
? `Subscription upgraded from $${response.details.current_price} to $${response.details.new_price}`
256258
: 'Subscription updated successfully';
257259
toast.success(upgradeMessage);
260+
posthog.capture('plan_upgraded');
258261
if (onSubscriptionUpdate) onSubscriptionUpdate();
259262
break;
260263
case 'commitment_blocks_downgrade':
@@ -276,6 +279,7 @@ function PricingTier({
276279
</p>
277280
</div>,
278281
);
282+
posthog.capture('plan_downgraded');
279283
if (onSubscriptionUpdate) onSubscriptionUpdate();
280284
break;
281285
case 'no_change':
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use client';
2+
3+
import posthog from 'posthog-js';
4+
import { useEffect } from 'react';
5+
import { createClient } from '@/lib/supabase/client';
6+
7+
export const PostHogIdentify = () => {
8+
useEffect(() => {
9+
const supabase = createClient();
10+
const listener = supabase.auth.onAuthStateChange((_, session) => {
11+
if (session) {
12+
posthog.identify(session.user.id, { email: session.user.email });
13+
} else {
14+
posthog.reset();
15+
}
16+
});
17+
18+
return () => {
19+
listener.data.subscription.unsubscribe();
20+
};
21+
}, []);
22+
23+
return null;
24+
};

frontend/src/components/sidebar/sidebar-left.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { useIsMobile } from '@/hooks/use-mobile';
4141
import { cn } from '@/lib/utils';
4242
import { usePathname, useSearchParams } from 'next/navigation';
4343
import { useFeatureFlags } from '@/lib/feature-flags';
44+
import posthog from 'posthog-js';
4445

4546
export function SidebarLeft({
4647
...props
@@ -150,7 +151,7 @@ export function SidebarLeft({
150151
<Link href="/dashboard">
151152
<SidebarMenuButton className={cn({
152153
'bg-accent text-accent-foreground font-medium': pathname === '/dashboard',
153-
})}>
154+
})} onClick={() => posthog.capture('new_task_clicked')}>
154155
<Plus className="h-4 w-4 mr-1" />
155156
<span className="flex items-center justify-between w-full">
156157
New Task

frontend/src/components/thread/chat-input/chat-input.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { useSubscriptionWithStreaming } from '@/hooks/react-query/subscriptions/
2828
import { isLocalMode } from '@/lib/config';
2929
import { BillingModal } from '@/components/billing/billing-modal';
3030
import { useRouter } from 'next/navigation';
31+
import posthog from 'posthog-js';
3132

3233
export interface ChatInputHandles {
3334
getPendingFiles: () => File[];
@@ -282,6 +283,8 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
282283
thinkingEnabled = true;
283284
}
284285

286+
posthog.capture("task_prompt_submitted", { message });
287+
285288
onSubmit(message, {
286289
model_name: baseModelName,
287290
enable_thinking: thinkingEnabled,

frontend/src/lib/api.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { createClient } from '@/lib/supabase/client';
22
import { handleApiError } from './error-handler';
3+
import posthog from 'posthog-js';
34

45
// Get backend URL from environment variables
56
const API_URL = process.env.NEXT_PUBLIC_BACKEND_URL || '';
@@ -838,6 +839,8 @@ export const stopAgent = async (agentRunId: string): Promise<void> => {
838839
cache: 'no-store',
839840
});
840841

842+
posthog.capture('task_abandoned', { agentRunId });
843+
841844
if (!response.ok) {
842845
const stopError = new Error(`Error stopping agent: ${response.statusText}`);
843846
handleApiError(stopError, { operation: 'stop agent', resource: 'AI assistant' });

0 commit comments

Comments
 (0)