Skip to content

Commit

Permalink
GoogleAnalitics established + VITE_GA_TOKEN in workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
HGZdev committed Nov 16, 2024
1 parent 3868980 commit 1138001
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 17 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deployToGithubPages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
- name: Build the project
env:
VITE_JWT_SECRET: ${{ secrets.VITE_JWT_SECRET }}
VITE_GA_TOKEN: ${{ vars.VITE_GA_TOKEN }}
VITE_HASH_ROUTER: ${{ vars.VITE_HASH_ROUTER }}
VITE_BASE_URL: ${{ vars.VITE_BASE_URL }}
VITE_PROD_HOST_URL: ${{ vars.VITE_PROD_HOST_URL }}
Expand Down
111 changes: 111 additions & 0 deletions lib/GoogleAnalytics/GoogleAnalyticsProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import React, {createContext, useContext, useEffect} from "react";
import ReactGA from "react-ga4";

// Initialize Google Analytics
export const initGA = (measurementId: string): void => {
try {
if (!measurementId) {
throw new Error(
"Measurement ID is required to initialize Google Analytics."
);
}
ReactGA.initialize(measurementId);
} catch (error) {
console.error("Error initializing Google Analytics:", error);
}
};

// Log a page view
export const logPageViewGA = (path: string): void => {
try {
if (!path) {
throw new Error("Path is required to log a page view.");
}
ReactGA.send({hitType: "pageview", page: path});
} catch (error) {
console.error("Error logging page view:", error);
}
};

// Log an event
export const logEventGA = (
category: string,
action: string,
label?: string
): void => {
try {
if (!category || !action) {
throw new Error("Category and action are required to log an event.");
}
ReactGA.event({
category,
action,
label,
});
} catch (error) {
console.error("Error logging event:", error);
}
};

// Analytics Context
interface GoogleAnalyticsContextProps {
logPageView: (path: string) => void;
logEvent: (category: string, action: string, label?: string) => void;
}

const GoogleAnalyticsContext = createContext<
GoogleAnalyticsContextProps | undefined
>(undefined);

interface GoogleAnalyticsProviderProps {
measurementId: string;
children: React.ReactNode;
}

export const GoogleAnalyticsProvider: React.FC<
GoogleAnalyticsProviderProps
> = ({measurementId, children}) => {
if (!measurementId) {
console.warn(new Error("Google Analytics measurement ID is required."));
return <>{children}</>;
}

useEffect(() => {
try {
initGA(measurementId);
const path = window.location.pathname + window.location.search;
logPageViewGA(path); // Log the initial page view
console.log("Google Analytics Initialized and Pageview Logged:", path);
} catch (error) {
console.error("Error during Google Analytics setup:", error);
}
}, [measurementId]);

useEffect(() => {
try {
const path = window.location.pathname + window.location.search;
logPageViewGA(path); // Log each page view
console.log("Pageview Logged:", path);
} catch (error) {
console.error("Error logging page view on path change:", error);
}
}, []);

return (
<GoogleAnalyticsContext.Provider
value={{logPageView: logPageViewGA, logEvent: logEventGA}}
>
{children}
</GoogleAnalyticsContext.Provider>
);
};

export const useGoogleAnalytics = (): GoogleAnalyticsContextProps => {
const context = useContext(GoogleAnalyticsContext);
if (!context) {
throw new Error(
"useGoogleAnalytics must be used within a GoogleAnalyticsProvider"
);
}
return context;
};
1 change: 1 addition & 0 deletions lib/GoogleAnalytics/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./GoogleAnalyticsProvider";
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"msw": "^2.3.5",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-ga4": "^2.1.0",
"react-helmet": "^6.1.0",
"react-icons": "^5.3.0",
"react-router-dom": "^6.26.1",
Expand Down
27 changes: 14 additions & 13 deletions pnpm-lock.yaml

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

13 changes: 10 additions & 3 deletions src/client/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ import About from "./Pages/Public/About.tsx";
import Templates from "./Pages/Public/Templates.tsx";
import Metadata from "./Components/Metadata.tsx";
import ScrollToTopRoute from "./Components/ScrollToTopRoute.tsx";
import {GoogleAnalyticsProvider} from "../../lib/GoogleAnalytics";

export const ApolloProvider = makeApolloProvider(import.meta.env);

const {VITE_BASE_URL, VITE_APP_NAME, VITE_HASH_ROUTER} = import.meta.env;
const {VITE_BASE_URL, VITE_APP_NAME, VITE_HASH_ROUTER, VITE_GA_TOKEN} =
import.meta.env;
const BASE_URL = VITE_HASH_ROUTER ? "" : VITE_BASE_URL;

export const RoutesConfig = (
Expand Down Expand Up @@ -55,8 +57,13 @@ const Root: React.FC = () => {
<Metadata />
<ApolloProvider>
<DraftProvider>
<GlobalStyles />
<RouterProvider router={router} future={{v7_startTransition: true}} />
<GoogleAnalyticsProvider measurementId={VITE_GA_TOKEN}>
<GlobalStyles />
<RouterProvider
router={router}
future={{v7_startTransition: true}}
/>
</GoogleAnalyticsProvider>
</DraftProvider>
</ApolloProvider>
</>
Expand Down
4 changes: 3 additions & 1 deletion vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
interface ImportMetaEnv {
readonly VITE_JWT_SECRET: string;
readonly VITE_GA_TOKEN: string;

readonly VITE_APP_NAME: string;
readonly VITE_APP_DESC: string;
readonly VITE_BASE_URL: string;
readonly VITE_GRAPHQL_DIR: string;
readonly VITE_JWT_SECRET: string;
readonly VITE_HASH_ROUTER: string;

readonly VITE_LOCAL_PORT: string;
Expand Down

0 comments on commit 1138001

Please sign in to comment.