fix: unify PostHog distinctId across client and server

Client-side posthog-js was using a random anonymous ID (reset every
page load) while server-side posthog-node used a deterministic
SHA256(hostname:username) hash. Bootstrap the client with the server's
anonymous ID so both sides share the same per-machine-per-user identity.
This commit is contained in:
kumarabhirup 2026-03-05 10:47:36 -08:00
parent f41c0411eb
commit a771ab7259
No known key found for this signature in database
GPG Key ID: DB7CA2289CAB0167
3 changed files with 10 additions and 5 deletions

View File

@ -9,11 +9,15 @@ const POSTHOG_HOST = "https://us.i.posthog.com";
let initialized = false;
function initPostHog() {
function initPostHog(anonymousId: string) {
if (initialized || !POSTHOG_KEY || typeof window === "undefined") return;
posthog.init(POSTHOG_KEY, {
api_host: POSTHOG_HOST,
bootstrap: {
distinctID: anonymousId,
isIdentifiedID: false,
},
capture_pageview: false,
capture_pageleave: true,
persistence: "memory",
@ -24,12 +28,12 @@ function initPostHog() {
initialized = true;
}
export function PostHogPageviewTracker() {
export function PostHogPageviewTracker({ anonymousId }: { anonymousId: string }) {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
initPostHog();
initPostHog(anonymousId);
}, []);
useEffect(() => {

View File

@ -1,5 +1,6 @@
import type { Metadata, Viewport } from "next";
import { Suspense } from "react";
import { getAnonymousId } from "@/lib/telemetry";
import { PostHogPageviewTracker } from "./components/posthog-provider";
import "./globals.css";
@ -42,7 +43,7 @@ export default function RootLayout({
</head>
<body className="antialiased">
<Suspense fallback={null}>
<PostHogPageviewTracker />
<PostHogPageviewTracker anonymousId={getAnonymousId()} />
</Suspense>
{children}
</body>

View File

@ -7,7 +7,7 @@ const POSTHOG_HOST = "https://us.i.posthog.com";
let client: PostHog | null = null;
function getAnonymousId(): string {
export function getAnonymousId(): string {
try {
const raw = `${os.hostname()}:${os.userInfo().username}`;
return createHash("sha256").update(raw).digest("hex").slice(0, 16);