From cdd8aace86d0d543e41c4621b8cf5d9d6740dbe2 Mon Sep 17 00:00:00 2001
From: "sp.wack" <83104063+amanape@users.noreply.github.com>
Date: Tue, 11 Nov 2025 19:48:56 +0400
Subject: [PATCH] refactor(frontend): migrate from direct posthog imports to
usePostHog hook (#11703)
---
frontend/__tests__/routes/accept-tos.test.tsx | 18 ++++--
.../__tests__/routes/app-settings.test.tsx | 10 +++-
.../__tests__/utils/error-handler.test.ts | 8 +++
.../utils/handle-capture-consent.test.ts | 8 +--
frontend/package-lock.json | 56 ++++++++++---------
frontend/package.json | 3 +-
.../analytics-consent-form-modal.tsx | 4 +-
.../features/chat/chat-interface.tsx | 3 +-
.../conversation-card/conversation-card.tsx | 3 +-
.../shared/modals/settings/settings-form.tsx | 3 +-
frontend/src/context/ws-client-provider.tsx | 14 ++++-
frontend/src/entry.client.tsx | 34 ++++++-----
frontend/src/hooks/mutation/use-logout.ts | 3 +-
.../src/hooks/mutation/use-save-settings.ts | 3 +-
frontend/src/hooks/query/use-git-user.ts | 3 +-
.../use-conversation-name-context-menu.ts | 3 +-
.../src/hooks/use-migrate-user-consent.ts | 8 ++-
frontend/src/hooks/use-tracking.ts | 3 +-
frontend/src/root.tsx | 1 +
frontend/src/routes/accept-tos.tsx | 4 +-
frontend/src/routes/app-settings.tsx | 4 +-
frontend/src/services/actions.ts | 1 +
frontend/src/utils/error-handler.ts | 18 ++++--
frontend/src/utils/handle-capture-consent.ts | 10 +++-
24 files changed, 150 insertions(+), 75 deletions(-)
diff --git a/frontend/__tests__/routes/accept-tos.test.tsx b/frontend/__tests__/routes/accept-tos.test.tsx
index ce6f36793b..7b15081485 100644
--- a/frontend/__tests__/routes/accept-tos.test.tsx
+++ b/frontend/__tests__/routes/accept-tos.test.tsx
@@ -1,10 +1,9 @@
import { render, screen } from "@testing-library/react";
import { it, describe, expect, vi, beforeEach, afterEach } from "vitest";
import userEvent from "@testing-library/user-event";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import AcceptTOS from "#/routes/accept-tos";
import * as CaptureConsent from "#/utils/handle-capture-consent";
-import * as ToastHandlers from "#/utils/custom-toast-handlers";
-import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { openHands } from "#/api/open-hands-axios";
// Mock the react-router hooks
@@ -44,9 +43,13 @@ const createWrapper = () => {
},
});
- return ({ children }: { children: React.ReactNode }) => (
- {children}
- );
+ function Wrapper({ children }: { children: React.ReactNode }) {
+ return (
+ {children}
+ );
+ }
+
+ return Wrapper;
};
describe("AcceptTOS", () => {
@@ -106,7 +109,10 @@ describe("AcceptTOS", () => {
// Wait for the mutation to complete
await new Promise(process.nextTick);
- expect(handleCaptureConsentSpy).toHaveBeenCalledWith(true);
+ expect(handleCaptureConsentSpy).toHaveBeenCalledWith(
+ expect.anything(),
+ true,
+ );
expect(openHands.post).toHaveBeenCalledWith("/api/accept_tos", {
redirect_url: "/dashboard",
});
diff --git a/frontend/__tests__/routes/app-settings.test.tsx b/frontend/__tests__/routes/app-settings.test.tsx
index e7b189a33b..44dacce2fb 100644
--- a/frontend/__tests__/routes/app-settings.test.tsx
+++ b/frontend/__tests__/routes/app-settings.test.tsx
@@ -178,7 +178,10 @@ describe("Form submission", () => {
await userEvent.click(submit);
await waitFor(() =>
- expect(handleCaptureConsentsSpy).toHaveBeenCalledWith(true),
+ expect(handleCaptureConsentsSpy).toHaveBeenCalledWith(
+ expect.anything(),
+ true,
+ ),
);
});
@@ -203,7 +206,10 @@ describe("Form submission", () => {
await userEvent.click(submit);
await waitFor(() =>
- expect(handleCaptureConsentsSpy).toHaveBeenCalledWith(false),
+ expect(handleCaptureConsentsSpy).toHaveBeenCalledWith(
+ expect.anything(),
+ false,
+ ),
);
});
diff --git a/frontend/__tests__/utils/error-handler.test.ts b/frontend/__tests__/utils/error-handler.test.ts
index 0f1e91cae2..b0cf26bc64 100644
--- a/frontend/__tests__/utils/error-handler.test.ts
+++ b/frontend/__tests__/utils/error-handler.test.ts
@@ -32,6 +32,7 @@ describe("Error Handler", () => {
const error = {
message: "Test error",
source: "test",
+ posthog,
};
trackError(error);
@@ -52,6 +53,7 @@ describe("Error Handler", () => {
extra: "info",
details: { foo: "bar" },
},
+ posthog,
};
trackError(error);
@@ -73,6 +75,7 @@ describe("Error Handler", () => {
const error = {
message: "Toast error",
source: "toast-test",
+ posthog,
};
showErrorToast(error);
@@ -94,6 +97,7 @@ describe("Error Handler", () => {
message: "Toast error",
source: "toast-test",
metadata: { context: "testing" },
+ posthog,
};
showErrorToast(error);
@@ -113,6 +117,7 @@ describe("Error Handler", () => {
message: "Agent error",
source: "agent-status",
metadata: { id: "error.agent" },
+ posthog,
});
expect(posthog.captureException).toHaveBeenCalledWith(
@@ -127,6 +132,7 @@ describe("Error Handler", () => {
message: "Server error",
source: "server",
metadata: { error_code: 500, details: "Internal error" },
+ posthog,
});
expect(posthog.captureException).toHaveBeenCalledWith(
@@ -145,6 +151,7 @@ describe("Error Handler", () => {
message: error.message,
source: "feedback",
metadata: { conversationId: "123", error },
+ posthog,
});
expect(posthog.captureException).toHaveBeenCalledWith(
@@ -164,6 +171,7 @@ describe("Error Handler", () => {
message: "Chat error",
source: "chat-test",
msgId: "123",
+ posthog,
};
showChatError(error);
diff --git a/frontend/__tests__/utils/handle-capture-consent.test.ts b/frontend/__tests__/utils/handle-capture-consent.test.ts
index 3b337424a7..0faf999c2b 100644
--- a/frontend/__tests__/utils/handle-capture-consent.test.ts
+++ b/frontend/__tests__/utils/handle-capture-consent.test.ts
@@ -13,14 +13,14 @@ describe("handleCaptureConsent", () => {
});
it("should opt out of of capturing", () => {
- handleCaptureConsent(false);
+ handleCaptureConsent(posthog, false);
expect(optOutSpy).toHaveBeenCalled();
expect(optInSpy).not.toHaveBeenCalled();
});
it("should opt in to capturing if the user consents", () => {
- handleCaptureConsent(true);
+ handleCaptureConsent(posthog, true);
expect(optInSpy).toHaveBeenCalled();
expect(optOutSpy).not.toHaveBeenCalled();
@@ -28,7 +28,7 @@ describe("handleCaptureConsent", () => {
it("should not opt in to capturing if the user is already opted in", () => {
hasOptedInSpy.mockReturnValueOnce(true);
- handleCaptureConsent(true);
+ handleCaptureConsent(posthog, true);
expect(optInSpy).not.toHaveBeenCalled();
expect(optOutSpy).not.toHaveBeenCalled();
@@ -36,7 +36,7 @@ describe("handleCaptureConsent", () => {
it("should not opt out of capturing if the user is already opted out", () => {
hasOptedOutSpy.mockReturnValueOnce(true);
- handleCaptureConsent(false);
+ handleCaptureConsent(posthog, false);
expect(optOutSpy).not.toHaveBeenCalled();
expect(optInSpy).not.toHaveBeenCalled();
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index feb13dcc3a..66b115ae73 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -12,6 +12,7 @@
"@heroui/use-infinite-scroll": "^2.2.11",
"@microlink/react-json-view": "^1.26.2",
"@monaco-editor/react": "^4.7.0-rc.0",
+ "@posthog/react": "^1.4.0",
"@react-router/node": "^7.9.3",
"@react-router/serve": "^7.9.3",
"@react-types/shared": "^3.32.0",
@@ -38,7 +39,7 @@
"jose": "^6.1.0",
"lucide-react": "^0.544.0",
"monaco-editor": "^0.53.0",
- "posthog-js": "^1.268.8",
+ "posthog-js": "^1.290.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-highlight": "^0.15.0",
@@ -3511,9 +3512,29 @@
"license": "MIT"
},
"node_modules/@posthog/core": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.2.2.tgz",
- "integrity": "sha512-f16Ozx6LIigRG+HsJdt+7kgSxZTHeX5f1JlCGKI1lXcvlZgfsCR338FuMI2QRYXGl+jg/vYFzGOTQBxl90lnBg=="
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/@posthog/core/-/core-1.5.2.tgz",
+ "integrity": "sha512-iedUP3EnOPPxTA2VaIrsrd29lSZnUV+ZrMnvY56timRVeZAXoYCkmjfIs3KBAsF8OUT5h1GXLSkoQdrV0r31OQ==",
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^7.0.6"
+ }
+ },
+ "node_modules/@posthog/react": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@posthog/react/-/react-1.4.0.tgz",
+ "integrity": "sha512-xzPeZ753fQ0deZzdgY/0YavZvNpmdaxUzLYJYu5XjONNcZ8PwJnNLEK+7D/Cj8UM4Q8nWI7QC5mjum0uLWa4FA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": ">=16.8.0",
+ "posthog-js": ">=1.257.2",
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
},
"node_modules/@react-aria/breadcrumbs": {
"version": "3.5.28",
@@ -8183,7 +8204,6 @@
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
@@ -8198,7 +8218,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -11403,7 +11422,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
"license": "ISC"
},
"node_modules/istanbul-lib-coverage": {
@@ -14073,7 +14091,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -14264,27 +14281,16 @@
"license": "MIT"
},
"node_modules/posthog-js": {
- "version": "1.268.8",
- "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.268.8.tgz",
- "integrity": "sha512-BJiKK4MlUvs7ybnQcy1KkwAz+SZkE/wRLotetIoank5kbqZs8FLbeyozFvmmgx4aoMmaVymYBSmYphYjYQeidw==",
+ "version": "1.290.0",
+ "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.290.0.tgz",
+ "integrity": "sha512-zavBwZkf+3JeiSDVE7ZDXBfzva/iOljicdhdJH+cZoqp0LsxjKxjnNhGOd3KpAhw0wqdwjhd7Lp1aJuI7DXyaw==",
+ "license": "SEE LICENSE IN LICENSE",
"dependencies": {
- "@posthog/core": "1.2.2",
+ "@posthog/core": "1.5.2",
"core-js": "^3.38.1",
"fflate": "^0.4.8",
"preact": "^10.19.3",
"web-vitals": "^4.2.4"
- },
- "peerDependencies": {
- "@rrweb/types": "2.0.0-alpha.17",
- "rrweb-snapshot": "2.0.0-alpha.17"
- },
- "peerDependenciesMeta": {
- "@rrweb/types": {
- "optional": true
- },
- "rrweb-snapshot": {
- "optional": true
- }
}
},
"node_modules/posthog-js/node_modules/web-vitals": {
@@ -15547,7 +15553,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
@@ -15560,7 +15565,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
diff --git a/frontend/package.json b/frontend/package.json
index 5ad91c3636..ec7e1793d2 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -11,6 +11,7 @@
"@heroui/use-infinite-scroll": "^2.2.11",
"@microlink/react-json-view": "^1.26.2",
"@monaco-editor/react": "^4.7.0-rc.0",
+ "@posthog/react": "^1.4.0",
"@react-router/node": "^7.9.3",
"@react-router/serve": "^7.9.3",
"@react-types/shared": "^3.32.0",
@@ -37,7 +38,7 @@
"jose": "^6.1.0",
"lucide-react": "^0.544.0",
"monaco-editor": "^0.53.0",
- "posthog-js": "^1.268.8",
+ "posthog-js": "^1.290.0",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-highlight": "^0.15.0",
diff --git a/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx b/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx
index c3ab215272..cc2f293235 100644
--- a/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx
+++ b/frontend/src/components/features/analytics/analytics-consent-form-modal.tsx
@@ -1,4 +1,5 @@
import { useTranslation } from "react-i18next";
+import { usePostHog } from "posthog-js/react";
import {
BaseModalTitle,
BaseModalDescription,
@@ -17,6 +18,7 @@ interface AnalyticsConsentFormModalProps {
export function AnalyticsConsentFormModal({
onClose,
}: AnalyticsConsentFormModalProps) {
+ const posthog = usePostHog();
const { t } = useTranslation();
const { mutate: saveUserSettings } = useSaveSettings();
@@ -29,7 +31,7 @@ export function AnalyticsConsentFormModal({
{ user_consents_to_analytics: analytics },
{
onSuccess: () => {
- handleCaptureConsent(analytics);
+ handleCaptureConsent(posthog, analytics);
onClose();
},
},
diff --git a/frontend/src/components/features/chat/chat-interface.tsx b/frontend/src/components/features/chat/chat-interface.tsx
index cabf087689..f37bd59c26 100644
--- a/frontend/src/components/features/chat/chat-interface.tsx
+++ b/frontend/src/components/features/chat/chat-interface.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import { useParams } from "react-router";
import { useTranslation } from "react-i18next";
import { convertImageToBase64 } from "#/utils/convert-image-to-base-64";
@@ -60,6 +60,7 @@ function getEntryPoint(
}
export function ChatInterface() {
+ const posthog = usePostHog();
const { setMessageToSend } = useConversationStore();
const { data: conversation } = useActiveConversation();
const { errorMessage } = useErrorMessageStore();
diff --git a/frontend/src/components/features/conversation-panel/conversation-card/conversation-card.tsx b/frontend/src/components/features/conversation-panel/conversation-card/conversation-card.tsx
index 8c6b895eaf..fff0a0888d 100644
--- a/frontend/src/components/features/conversation-panel/conversation-card/conversation-card.tsx
+++ b/frontend/src/components/features/conversation-panel/conversation-card/conversation-card.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import { cn } from "#/utils/utils";
import { transformVSCodeUrl } from "#/utils/vscode-url-helper";
import ConversationService from "#/api/conversation-service/conversation-service.api";
@@ -44,6 +44,7 @@ export function ConversationCard({
contextMenuOpen = false,
onContextMenuToggle,
}: ConversationCardProps) {
+ const posthog = usePostHog();
const [titleMode, setTitleMode] = React.useState<"view" | "edit">("view");
const onTitleSave = (newTitle: string) => {
diff --git a/frontend/src/components/shared/modals/settings/settings-form.tsx b/frontend/src/components/shared/modals/settings/settings-form.tsx
index 838b4f0b06..e08b59c8e0 100644
--- a/frontend/src/components/shared/modals/settings/settings-form.tsx
+++ b/frontend/src/components/shared/modals/settings/settings-form.tsx
@@ -1,7 +1,7 @@
import { useLocation } from "react-router";
import { useTranslation } from "react-i18next";
import React from "react";
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import { I18nKey } from "#/i18n/declaration";
import { organizeModelsAndProviders } from "#/utils/organize-models-and-providers";
import { DangerModal } from "../confirmation-modals/danger-modal";
@@ -22,6 +22,7 @@ interface SettingsFormProps {
}
export function SettingsForm({ settings, models, onClose }: SettingsFormProps) {
+ const posthog = usePostHog();
const { mutate: saveUserSettings } = useSaveSettings();
const location = useLocation();
diff --git a/frontend/src/context/ws-client-provider.tsx b/frontend/src/context/ws-client-provider.tsx
index 8f0a2829c0..38f390476f 100644
--- a/frontend/src/context/ws-client-provider.tsx
+++ b/frontend/src/context/ws-client-provider.tsx
@@ -1,6 +1,7 @@
import React from "react";
import { io, Socket } from "socket.io-client";
import { useQueryClient } from "@tanstack/react-query";
+import { usePostHog } from "posthog-js/react";
import EventLogger from "#/utils/event-logger";
import { handleAssistantMessage } from "#/services/actions";
import { showChatError, trackError } from "#/utils/error-handler";
@@ -100,7 +101,10 @@ interface ErrorArgData {
msg_id: string;
}
-export function updateStatusWhenErrorMessagePresent(data: ErrorArg | unknown) {
+export function updateStatusWhenErrorMessagePresent(
+ data: ErrorArg | unknown,
+ posthog?: ReturnType,
+) {
const isObject = (val: unknown): val is object =>
!!val && typeof val === "object";
const isString = (val: unknown): val is string => typeof val === "string";
@@ -123,6 +127,7 @@ export function updateStatusWhenErrorMessagePresent(data: ErrorArg | unknown) {
source: "websocket",
metadata,
msgId,
+ posthog,
});
}
}
@@ -131,6 +136,7 @@ export function WsClientProvider({
conversationId,
children,
}: React.PropsWithChildren) {
+ const posthog = usePostHog();
const { setErrorMessage, removeErrorMessage } = useErrorMessageStore();
const { removeOptimisticUserMessage } = useOptimisticUserMessageStore();
const { addEvent, clearEvents } = useEventStore();
@@ -178,6 +184,7 @@ export function WsClientProvider({
message: errorMessage,
source: "chat",
metadata: { msgId: event.id },
+ posthog,
});
setErrorMessage(errorMessage);
@@ -193,6 +200,7 @@ export function WsClientProvider({
message: event.message,
source: "chat",
metadata: { msgId: event.id },
+ posthog,
});
} else {
removeErrorMessage();
@@ -260,14 +268,14 @@ export function WsClientProvider({
sio.io.opts.query = sio.io.opts.query || {};
sio.io.opts.query.latest_event_id = lastEventRef.current?.id;
- updateStatusWhenErrorMessagePresent(data);
+ updateStatusWhenErrorMessagePresent(data, posthog);
setErrorMessage(hasValidMessageProperty(data) ? data.message : "");
}
function handleError(data: unknown) {
// set status
setWebSocketStatus("DISCONNECTED");
- updateStatusWhenErrorMessagePresent(data);
+ updateStatusWhenErrorMessagePresent(data, posthog);
setErrorMessage(
hasValidMessageProperty(data)
diff --git a/frontend/src/entry.client.tsx b/frontend/src/entry.client.tsx
index dc1e2e4dd5..9fe6212d4e 100644
--- a/frontend/src/entry.client.tsx
+++ b/frontend/src/entry.client.tsx
@@ -8,17 +8,18 @@
import { HydratedRouter } from "react-router/dom";
import React, { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
-import posthog from "posthog-js";
+import { PostHogProvider } from "posthog-js/react";
import "./i18n";
import { QueryClientProvider } from "@tanstack/react-query";
import OptionService from "./api/option-service/option-service.api";
import { displayErrorToast } from "./utils/custom-toast-handlers";
import { queryClient } from "./query-client-config";
-function PosthogInit() {
+function PostHogWrapper({ children }: { children: React.ReactNode }) {
const [posthogClientKey, setPosthogClientKey] = React.useState(
null,
);
+ const [isLoading, setIsLoading] = React.useState(true);
React.useEffect(() => {
(async () => {
@@ -27,20 +28,27 @@ function PosthogInit() {
setPosthogClientKey(config.POSTHOG_CLIENT_KEY);
} catch {
displayErrorToast("Error fetching PostHog client key");
+ } finally {
+ setIsLoading(false);
}
})();
}, []);
- React.useEffect(() => {
- if (posthogClientKey) {
- posthog.init(posthogClientKey, {
+ if (isLoading || !posthogClientKey) {
+ return children;
+ }
+
+ return (
+
+ {children}
+
+ );
}
async function prepareApp() {
@@ -62,10 +70,10 @@ prepareApp().then(() =>
document,
-
-
+
+
+
-
,
);
}),
diff --git a/frontend/src/hooks/mutation/use-logout.ts b/frontend/src/hooks/mutation/use-logout.ts
index d3fa98f28e..431fcc01af 100644
--- a/frontend/src/hooks/mutation/use-logout.ts
+++ b/frontend/src/hooks/mutation/use-logout.ts
@@ -1,10 +1,11 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import AuthService from "#/api/auth-service/auth-service.api";
import { useConfig } from "../query/use-config";
import { clearLoginData } from "#/utils/local-storage";
export const useLogout = () => {
+ const posthog = usePostHog();
const queryClient = useQueryClient();
const { data: config } = useConfig();
diff --git a/frontend/src/hooks/mutation/use-save-settings.ts b/frontend/src/hooks/mutation/use-save-settings.ts
index c0c6d5e09e..c8a433e9dc 100644
--- a/frontend/src/hooks/mutation/use-save-settings.ts
+++ b/frontend/src/hooks/mutation/use-save-settings.ts
@@ -1,5 +1,5 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import { DEFAULT_SETTINGS } from "#/services/settings";
import SettingsService from "#/settings-service/settings-service.api";
import { PostSettings } from "#/types/settings";
@@ -41,6 +41,7 @@ const saveSettingsMutationFn = async (settings: Partial) => {
};
export const useSaveSettings = () => {
+ const posthog = usePostHog();
const queryClient = useQueryClient();
const { data: currentSettings } = useSettings();
diff --git a/frontend/src/hooks/query/use-git-user.ts b/frontend/src/hooks/query/use-git-user.ts
index 916088ae12..b919ca460d 100644
--- a/frontend/src/hooks/query/use-git-user.ts
+++ b/frontend/src/hooks/query/use-git-user.ts
@@ -1,11 +1,12 @@
import { useQuery } from "@tanstack/react-query";
import React from "react";
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import { useConfig } from "./use-config";
import UserService from "#/api/user-service/user-service.api";
import { useShouldShowUserFeatures } from "#/hooks/use-should-show-user-features";
export const useGitUser = () => {
+ const posthog = usePostHog();
const { data: config } = useConfig();
// Use the shared hook to determine if we should fetch user data
diff --git a/frontend/src/hooks/use-conversation-name-context-menu.ts b/frontend/src/hooks/use-conversation-name-context-menu.ts
index 017a01f478..0e2c3e837e 100644
--- a/frontend/src/hooks/use-conversation-name-context-menu.ts
+++ b/frontend/src/hooks/use-conversation-name-context-menu.ts
@@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import React from "react";
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import { useParams, useNavigate } from "react-router";
import { transformVSCodeUrl } from "#/utils/vscode-url-helper";
import useMetricsStore from "#/stores/metrics-store";
@@ -29,6 +29,7 @@ export function useConversationNameContextMenu({
showOptions = false,
onContextMenuToggle,
}: UseConversationNameContextMenuProps) {
+ const posthog = usePostHog();
const { t } = useTranslation();
const { conversationId: currentConversationId } = useParams();
const navigate = useNavigate();
diff --git a/frontend/src/hooks/use-migrate-user-consent.ts b/frontend/src/hooks/use-migrate-user-consent.ts
index af9c6a7a50..3998291a71 100644
--- a/frontend/src/hooks/use-migrate-user-consent.ts
+++ b/frontend/src/hooks/use-migrate-user-consent.ts
@@ -1,8 +1,10 @@
import React from "react";
+import { usePostHog } from "posthog-js/react";
import { handleCaptureConsent } from "#/utils/handle-capture-consent";
import { useSaveSettings } from "./mutation/use-save-settings";
export const useMigrateUserConsent = () => {
+ const posthog = usePostHog();
const { mutate: saveUserSettings } = useSaveSettings();
/**
@@ -15,11 +17,11 @@ export const useMigrateUserConsent = () => {
if (userAnalyticsConsent) {
args?.handleAnalyticsWasPresentInLocalStorage();
- await saveUserSettings(
+ saveUserSettings(
{ user_consents_to_analytics: userAnalyticsConsent === "true" },
{
onSuccess: () => {
- handleCaptureConsent(userAnalyticsConsent === "true");
+ handleCaptureConsent(posthog, userAnalyticsConsent === "true");
},
},
);
@@ -27,7 +29,7 @@ export const useMigrateUserConsent = () => {
localStorage.removeItem("analytics-consent");
}
},
- [],
+ [posthog, saveUserSettings],
);
return { migrateUserConsent };
diff --git a/frontend/src/hooks/use-tracking.ts b/frontend/src/hooks/use-tracking.ts
index 714d3a06e7..4b7959c1dd 100644
--- a/frontend/src/hooks/use-tracking.ts
+++ b/frontend/src/hooks/use-tracking.ts
@@ -1,4 +1,4 @@
-import posthog from "posthog-js";
+import { usePostHog } from "posthog-js/react";
import { useConfig } from "./query/use-config";
import { useSettings } from "./query/use-settings";
import { Provider } from "#/types/settings";
@@ -8,6 +8,7 @@ import { Provider } from "#/types/settings";
* from available hooks (config, settings, etc.)
*/
export const useTracking = () => {
+ const posthog = usePostHog();
const { data: config } = useConfig();
const { data: settings } = useSettings();
diff --git a/frontend/src/root.tsx b/frontend/src/root.tsx
index cc3c3c1c1c..6f1f896b4d 100644
--- a/frontend/src/root.tsx
+++ b/frontend/src/root.tsx
@@ -25,6 +25,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
+