Skip to content

Commit

Permalink
feat(analytics): Fix syntax for analytics with react-ga4
Browse files Browse the repository at this point in the history
  • Loading branch information
Ninfa-Jeon committed Feb 18, 2025
1 parent 41ae90e commit 2e9bef6
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/components/App/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe("App", () => {
);
expect(initializeSpy).toHaveBeenCalled();
expect(pageviewSpy).toHaveBeenCalledWith({
hitType: "page_view",
hitType: "pageview",
page: "/models",
});
});
Expand Down
12 changes: 10 additions & 2 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ function App() {
const isProduction = import.meta.env.PROD;
const analyticsEnabled = useAppSelector(getAnalyticsEnabled);
if (isProduction && analyticsEnabled) {
ReactGA.initialize("UA-1018242-68"); // TODO: should use the GA4 Measurement ID (which starts with "G-")
ReactGA.initialize("G-JHXHM8VXJ1", {
gtagOptions: {
custom_map: {
dimension1: "dashboardVersion",
dimension2: "controllerVersion",
dimension3: "isJuju",
},
},
});
ReactGA.send({
hitType: "page_view",
hitType: "pageview",
page: window.location.href.replace(window.location.origin, ""),
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/CaptureRoutes/CaptureRoutes.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ describe("CaptureRoutes", () => {
</BrowserRouter>,
);
expect(pageviewSpy).toHaveBeenCalledWith({
hitType: "page_view",
hitType: "pageview",
page: "/new/path",
});
});
Expand Down
13 changes: 1 addition & 12 deletions src/components/LogIn/LogIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {
getWSControllerURL,
isLoggedIn,
getIsJuju,
getAppVersion,
getControllerConnection,
} from "store/general/selectors";
import { AuthMethod } from "store/general/types";
import { useAppSelector } from "store/store";
Expand All @@ -33,11 +31,7 @@ export default function LogIn() {
const sendAnalytics = useAnalytics();
const config = useSelector(getConfig);
const isJuju = useSelector(getIsJuju);
const appVersion = useSelector(getAppVersion);
const wsControllerURL = useAppSelector(getWSControllerURL);
const controllerVersion = useAppSelector((state) =>
getControllerConnection(state, wsControllerURL),
)?.serverVersion;
const userIsLoggedIn = useAppSelector((state) =>
isLoggedIn(state, wsControllerURL),
);
Expand Down Expand Up @@ -84,14 +78,9 @@ export default function LogIn() {
sendAnalytics({
category: "Authentication",
action: "User Login",
eventParams: {
dashboardVersion: appVersion ?? "",
controllerVersion: controllerVersion ?? "",
isJuju: (!!isJuju).toString(),
},
});
}
}, [userIsLoggedIn, appVersion, controllerVersion, isJuju, sendAnalytics]);
}, [userIsLoggedIn, sendAnalytics]);

let form: ReactNode = null;
switch (config?.authMethod) {
Expand Down
15 changes: 9 additions & 6 deletions src/hooks/useAnalytics.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { renderHook } from "@testing-library/react";
import ReactGA from "react-ga4";
import type { MockInstance } from "vitest";
import { vi } from "vitest";

import * as store from "store/store";
import { renderWrappedHook } from "testing/utils";

import useAnalytics from "./useAnalytics";

Expand Down Expand Up @@ -38,7 +38,7 @@ describe("useAnalytics", () => {
vi.fn().mockReturnValue(true),
);
vi.stubEnv("PROD", false);
const { result } = renderHook(() => useAnalytics());
const { result } = renderWrappedHook(() => useAnalytics());
result.current({ path: "/some/path" });
expect(eventSpy).not.toHaveBeenCalled();
expect(pageviewSpy).not.toHaveBeenCalled();
Expand All @@ -48,7 +48,7 @@ describe("useAnalytics", () => {
vi.spyOn(store, "useAppSelector").mockImplementation(
vi.fn().mockReturnValue(false),
);
const { result } = renderHook(() => useAnalytics());
const { result } = renderWrappedHook(() => useAnalytics());
result.current({ path: "/some/path" });
expect(eventSpy).not.toHaveBeenCalled();
expect(pageviewSpy).not.toHaveBeenCalled();
Expand All @@ -58,10 +58,10 @@ describe("useAnalytics", () => {
vi.spyOn(store, "useAppSelector").mockImplementation(
vi.fn().mockReturnValue(true),
);
const { result } = renderHook(() => useAnalytics());
const { result } = renderWrappedHook(() => useAnalytics());
result.current({ path: "/some/path" });
expect(pageviewSpy).toHaveBeenCalledWith({
hitType: "page_view",
hitType: "pageview",
page: "/some/path",
});
});
Expand All @@ -70,11 +70,14 @@ describe("useAnalytics", () => {
vi.spyOn(store, "useAppSelector").mockImplementation(
vi.fn().mockReturnValue(true),
);
const { result } = renderHook(() => useAnalytics());
const { result } = renderWrappedHook(() => useAnalytics());
result.current({ category: "sidebar", action: "toggle" });
expect(eventSpy).toHaveBeenCalledWith({
category: "sidebar",
action: "toggle",
controllerVersion: "",
dashboardVersion: "",
isJuju: "false",
});
});
});
32 changes: 22 additions & 10 deletions src/hooks/useAnalytics.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,46 @@
import ReactGA from "react-ga4";
import { useSelector } from "react-redux";

import { getAnalyticsEnabled } from "store/general/selectors";
import {
getAnalyticsEnabled,
getAppVersion,
getControllerConnection,
getIsJuju,
getWSControllerURL,
} from "store/general/selectors";
import { useAppSelector } from "store/store";

type AnalyticMessage = {
path?: string;
category?: string;
action?: string;
eventParams?: { [key: string]: string };
};

export default function useAnalytics() {
const analyticsEnabled = useAppSelector(getAnalyticsEnabled);
return ({
path,
category = "",
action = "",
eventParams = {},
}: AnalyticMessage) => {
const isJuju = useSelector(getIsJuju);
const appVersion = useSelector(getAppVersion);
const wsControllerURL = useAppSelector(getWSControllerURL);
const controllerVersion = useAppSelector((state) =>
getControllerConnection(state, wsControllerURL),
)?.serverVersion;

return ({ path, category = "", action = "" }: AnalyticMessage) => {
const isProduction = import.meta.env.PROD;
if (!isProduction || !analyticsEnabled) {
return;
}
if (path) {
ReactGA.send({ hitType: "page_view", page: path });
ReactGA.send({ hitType: "pageview", page: path });
} else {
ReactGA.event({
category,
action,
...eventParams,
...{
dashboardVersion: appVersion ?? "",
controllerVersion: controllerVersion ?? "",
isJuju: (!!isJuju).toString(),
},
});
}
};
Expand Down

0 comments on commit 2e9bef6

Please sign in to comment.