Skip to content

Commit

Permalink
feat(GoogleAnalytics): added react-ga
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Dobkowski committed Dec 11, 2024
1 parent aa5fc74 commit a7f4a2b
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 18 deletions.
11 changes: 8 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"react-dates": "^21.8.0",
"react-dates-gte-react-17-21.8.0-version-fixed": "^21.8.0",
"react-dom": "^18.2.0",
"react-ga4": "^2.1.0",
"react-helmet-async": "^1.3.0",
"react-i18next": "^11.17.2",
"react-markdown": "^8.0.0",
Expand Down
31 changes: 17 additions & 14 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react";
import { apolloClient } from "api/apolloClient";
import Footer from "components/Footer";
import Header from "components/Header";
import { AnalyticsWrapper } from "features/analytics";
import StateModal from "features/confirmation/components/StateModal";
import "features/i18n";
import ThemeWrapper from "features/theme/components/ThemeWrapper";
Expand All @@ -15,20 +16,22 @@ import { AppLayoutWrapper } from "./components/layout/AppLayoutWrapper";
function App() {
return (
<RecoilRoot>
<Router>
<ApolloProvider client={apolloClient}>
<ThemeWrapper>
<GlobalStyles />
<AppLayoutWrapper>
<Header />
<PageSwitcher>
<StateModal />
</PageSwitcher>
<Footer />
</AppLayoutWrapper>
</ThemeWrapper>
</ApolloProvider>
</Router>
<AnalyticsWrapper>
<Router>
<ApolloProvider client={apolloClient}>
<ThemeWrapper>
<GlobalStyles />
<AppLayoutWrapper>
<Header />
<PageSwitcher>
<StateModal />
</PageSwitcher>
<Footer />
</AppLayoutWrapper>
</ThemeWrapper>
</ApolloProvider>
</Router>
</AnalyticsWrapper>
</RecoilRoot>
);
}
Expand Down
9 changes: 9 additions & 0 deletions src/features/analytics/AnalyticsWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { PropsWithChildren } from "react";
import { AnalyticsContext } from "./contexts/AnalyticsContext";
import { useGoogleAnalytics } from "./hooks";

export const AnalyticsWrapper: React.FC<PropsWithChildren> = ({ children }) => {
const googleAnalytics = useGoogleAnalytics();

return <AnalyticsContext.Provider value={googleAnalytics}>{children}</AnalyticsContext.Provider>;
};
4 changes: 4 additions & 0 deletions src/features/analytics/contexts/AnalyticsContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import React from "react";
import { UseGoogleAnalyticsReturn } from "../types";

export const AnalyticsContext = React.createContext({} as UseGoogleAnalyticsReturn);
1 change: 1 addition & 0 deletions src/features/analytics/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { useGoogleAnalytics } from "./useGoogleAnalytics";
38 changes: 38 additions & 0 deletions src/features/analytics/hooks/useGoogleAnalytics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useState } from "react";
import ReactGA from "react-ga4";
import { GoogleAnalyticsEvent, UseGoogleAnalytics } from "../types";

export const useGoogleAnalytics: UseGoogleAnalytics = () => {
const [trackingId, setTrackingId] = useState<string>("");

const init = (id: string) => {
if (!id) {
throw new Error("Google Analytics tracking ID is required");
}
ReactGA.initialize(id);
setTrackingId(id);
console.log(`Google Analytics initialized with tracking ID: ${id}`);
};

const sendEvent = (event: GoogleAnalyticsEvent) => {
if (!trackingId) {
throw new Error("Google Analytics is not initialized");
}
ReactGA.event(event);
console.log(`Google Analytics event sent: ${JSON.stringify(event)}`);
};

const send = (path: any) => {
if (!trackingId) {
throw new Error("Google Analytics is not initialized");
}
ReactGA.send(path);
console.log(`Google Analytics pageview sent: ${path}`);
};

return {
init,
sendEvent,
send,
};
};
1 change: 1 addition & 0 deletions src/features/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { AnalyticsWrapper } from "./AnalyticsWrapper";
14 changes: 14 additions & 0 deletions src/features/analytics/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface UseGoogleAnalyticsReturn {
init: (trackingId: string) => void;
sendEvent: (event: any) => void;
send: (fieldObject: any) => void;
}

export type UseGoogleAnalytics = () => UseGoogleAnalyticsReturn;

export interface GoogleAnalyticsEvent {
category: string;
action: string;
label?: string;
value?: number;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useContext } from "react";
import { ContextButton } from "components/ContextButton";
import { Typography } from "components/Typography";
import { AnalyticsContext } from "features/analytics/contexts/AnalyticsContext";
import { getPath } from "helpers/functions";
import { useIsEmbeddedPage } from "helpers/hooks/useIsEmbeddedPage";
import { useTranslation } from "react-i18next";
Expand All @@ -16,6 +18,7 @@ const BackToServiceButton = () => {
const service = useRecoilValue(serviceAtom);
const [searchParams] = useSearchParams();
const urlSearchParams = Object.fromEntries(searchParams.entries());
const { send } = useContext(AnalyticsContext);

if (service === undefined) return null;

Expand All @@ -33,6 +36,15 @@ const BackToServiceButton = () => {
},
}),
);
send({
path: getPath({
url: `${PAGES.SERVICE}:query`,
params: {
id: service.serviceId,
query: `?${createSearchParams(urlSearchParams).toString()}`,
},
}),
});
}}
>
<Typography typographyType="body" align="center" as="span" color="inherit" weight="700">
Expand Down
8 changes: 7 additions & 1 deletion src/features/service/components/ServiceHeaders.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from "react";
import React, { useContext, useEffect } from "react";
import { AnalyticsContext } from "features/analytics/contexts/AnalyticsContext";
import { Helmet, HelmetProvider } from "react-helmet-async";
import { useRecoilValue } from "recoil";
import { serviceAtom } from "state/atoms/service";
Expand All @@ -7,6 +8,11 @@ import { headerSelector } from "state/selectors/headerSelector";
const ServiceHeaders = () => {
const icon = useRecoilValue(headerSelector)?.logoUrl;
const service = useRecoilValue(serviceAtom);
const { init } = useContext(AnalyticsContext);

useEffect(() => {
init("G-1624QD7NDN");
}, [init]);

if (service === undefined) return null;

Expand Down

0 comments on commit a7f4a2b

Please sign in to comment.