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.
This commit is contained in:
kumarabhirup 2026-03-05 16:09:12 -08:00
parent 00c04f89d3
commit c4ee320994
No known key found for this signature in database
GPG Key ID: DB7CA2289CAB0167
2 changed files with 19 additions and 9 deletions

View File

@ -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.
}

View File

@ -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(() => {});
}, []);