mirror of
https://github.com/CopilotKit/CopilotKit.git
synced 2026-09-14 16:26:20 +08:00
1a76f693f0
- PostHog: capture_dead_clicks=false to skip dead-clicks-autocapture.js - Drop duplicate reb2b loader (NEXT_PUBLIC_RB2B_ID); the <Script> in app/layout.tsx using NEXT_PUBLIC_REB2B_KEY is the canonical one and matches the website's reb2b key Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
138 lines
4.9 KiB
TypeScript
138 lines
4.9 KiB
TypeScript
"use client";
|
|
|
|
import { PostHogProvider as PostHogProviderBase } from "posthog-js/react";
|
|
import posthog from "posthog-js";
|
|
import { useEffect, useState, useRef } from "react";
|
|
import { usePathname } from "next/navigation";
|
|
import { normalizePathnameForAnalytics } from "@/lib/analytics-utils";
|
|
|
|
const POSTHOG_KEY = process.env.NEXT_PUBLIC_POSTHOG_KEY;
|
|
// Reverse-proxied via /ingest/* rewrites in next.config.mjs so requests
|
|
// flow through docs.copilotkit.ai instead of *.i.posthog.com — bypasses
|
|
// ad blockers / tracking-protection that target the PostHog hostname.
|
|
const POSTHOG_HOST = "/ingest";
|
|
const POSTHOG_UI_HOST = "https://eu.posthog.com";
|
|
|
|
export function PostHogProvider({ children }: { children: React.ReactNode }) {
|
|
const pathname = usePathname();
|
|
const [sessionId, setSessionId] = useState<string | null>(null);
|
|
const isInitializedRef = useRef(false);
|
|
|
|
// Read session_id from URL only on client side to avoid hydration mismatch
|
|
useEffect(() => {
|
|
if (typeof window !== "undefined") {
|
|
const params = new URLSearchParams(window.location.search);
|
|
setSessionId(params.get("session_id"));
|
|
}
|
|
}, []);
|
|
|
|
// Initialize PostHog once (only on mount)
|
|
useEffect(() => {
|
|
if (POSTHOG_KEY && !posthog?.__loaded && !isInitializedRef.current) {
|
|
isInitializedRef.current = true;
|
|
|
|
// Read sessionId from URL at initialization time
|
|
const params =
|
|
typeof window !== "undefined"
|
|
? new URLSearchParams(window.location.search)
|
|
: null;
|
|
const initSessionId = params?.get("session_id") ?? sessionId;
|
|
|
|
// Suppress all PostHog-related console errors and warnings
|
|
const originalError = console.error;
|
|
const originalWarn = console.warn;
|
|
const originalLog = console.log;
|
|
|
|
const suppressPostHogErrors = () => {
|
|
console.error = (...args: any[]) => {
|
|
const errorString = args.join(" ");
|
|
const isPostHogError =
|
|
errorString.includes("posthog") ||
|
|
errorString.includes("PostHog") ||
|
|
errorString.includes("request.ts") ||
|
|
errorString.includes("posthog-core.ts") ||
|
|
errorString.includes("ERR_BLOCKED_BY_CONTENT_BLOCKER") ||
|
|
args.some(
|
|
(arg) =>
|
|
(typeof arg === "string" && arg.includes("posthog")) ||
|
|
arg?.stack?.includes("posthog") ||
|
|
arg?.message?.includes("posthog"),
|
|
);
|
|
|
|
if (isPostHogError) {
|
|
// Suppress in production, log as warning in development
|
|
if (process.env.NODE_ENV === "development") {
|
|
originalWarn("[PostHog] Error suppressed:", ...args);
|
|
}
|
|
return;
|
|
}
|
|
originalError(...args);
|
|
};
|
|
|
|
console.warn = (...args: any[]) => {
|
|
const warnString = args.join(" ");
|
|
const isPostHogWarn =
|
|
warnString.includes("posthog") ||
|
|
warnString.includes("PostHog") ||
|
|
warnString.includes("[PostHog.js]");
|
|
|
|
if (isPostHogWarn) {
|
|
// Suppress in production, log in development
|
|
if (process.env.NODE_ENV === "development") {
|
|
originalLog("[PostHog] Warning suppressed:", ...args);
|
|
}
|
|
return;
|
|
}
|
|
originalWarn(...args);
|
|
};
|
|
};
|
|
|
|
try {
|
|
// Suppress PostHog errors permanently (they're just noise from ad blockers)
|
|
suppressPostHogErrors();
|
|
|
|
posthog.init(POSTHOG_KEY, {
|
|
api_host: POSTHOG_HOST,
|
|
ui_host: POSTHOG_UI_HOST,
|
|
person_profiles: "identified_only",
|
|
bootstrap: initSessionId
|
|
? {
|
|
sessionID: initSessionId,
|
|
}
|
|
: undefined,
|
|
// Disable automatic pageview capture (we do it manually)
|
|
capture_pageview: false,
|
|
// Reduce network requests by batching
|
|
request_batching: true,
|
|
capture_dead_clicks: false,
|
|
// Don't enable debug mode - it causes too much logging
|
|
});
|
|
} catch (error) {
|
|
// Silently fail if PostHog init fails (e.g., network issues, blocked by ad blockers)
|
|
if (process.env.NODE_ENV === "development") {
|
|
originalWarn("PostHog initialization failed:", error);
|
|
}
|
|
}
|
|
}
|
|
}, []); // Only run once on mount
|
|
|
|
// Capture pageview only after PostHog is initialized
|
|
useEffect(() => {
|
|
if (POSTHOG_KEY && posthog?.__loaded) {
|
|
try {
|
|
const normalizedPathname = normalizePathnameForAnalytics(pathname);
|
|
posthog.capture("$pageview", {
|
|
$current_url: `https://docs.copilotkit.ai${normalizedPathname}`,
|
|
});
|
|
} catch (error) {
|
|
// Silently fail if PostHog capture fails (e.g., network issues)
|
|
if (process.env.NODE_ENV === "development") {
|
|
console.warn("PostHog capture failed:", error);
|
|
}
|
|
}
|
|
}
|
|
}, [pathname]);
|
|
|
|
return <PostHogProviderBase client={posthog}>{children}</PostHogProviderBase>;
|
|
}
|