From c4ee320994b0ce68919659125f78d0f3f764dd8c Mon Sep 17 00:00:00 2001 From: kumarabhirup Date: Thu, 5 Mar 2026 16:09:12 -0800 Subject: [PATCH] feat(feedback): forward client PostHog distinct ID to server-side AI traces Ensures server-side trace events are attributed to the same user as client-side analytics. --- apps/web/app/api/feedback/route.ts | 21 +++++++++++++-------- apps/web/app/components/chat-message.tsx | 7 ++++++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/apps/web/app/api/feedback/route.ts b/apps/web/app/api/feedback/route.ts index be95060933b..0bbf8647bf1 100644 --- a/apps/web/app/api/feedback/route.ts +++ b/apps/web/app/api/feedback/route.ts @@ -31,9 +31,10 @@ function extractTextContent(line: ChatLine): string { */ export async function POST(req: Request) { try { - const { sessionId, messageId } = (await req.json()) as { + const { sessionId, messageId, distinctId } = (await req.json()) as { sessionId?: string; messageId?: string; + distinctId?: string; }; if (!sessionId) { return Response.json({ ok: true }); @@ -68,13 +69,17 @@ export async function POST(req: Request) { .filter((m) => m.role === "assistant") .map((m) => ({ role: "assistant" as const, content: extractTextContent(m) })); - trackServer("$ai_trace", { - $ai_trace_id: sessionId, - $ai_session_id: sessionId, - $ai_span_name: "chat_session", - $ai_input_state: inputState.length > 0 ? inputState : undefined, - $ai_output_state: outputState.length > 0 ? outputState : undefined, - }); + trackServer( + "$ai_trace", + { + $ai_trace_id: sessionId, + $ai_session_id: sessionId, + $ai_span_name: "chat_session", + $ai_input_state: inputState.length > 0 ? inputState : undefined, + $ai_output_state: outputState.length > 0 ? outputState : undefined, + }, + distinctId, + ); } catch { // Fail silently -- feedback capture should never block the user. } diff --git a/apps/web/app/components/chat-message.tsx b/apps/web/app/components/chat-message.tsx index 6e81534d4cb..12fafabd139 100644 --- a/apps/web/app/components/chat-message.tsx +++ b/apps/web/app/components/chat-message.tsx @@ -2,6 +2,7 @@ import dynamic from "next/dynamic"; import type { UIMessage } from "ai"; +import posthog from "posthog-js"; import { useThumbSurvey } from "posthog-js/react/surveys"; import { memo, useCallback, useMemo, useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; @@ -697,7 +698,11 @@ function FeedbackButtons({ messageId, sessionId }: { messageId: string; sessionI fetch("/api/feedback", { method: "POST", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ sessionId: sid, messageId: mid }), + body: JSON.stringify({ + sessionId: sid, + messageId: mid, + distinctId: posthog.get_distinct_id?.(), + }), }).catch(() => {}); }, []);