From 9257ba1bdec610984d7ad1e66166a95c1f0f6f06 Mon Sep 17 00:00:00 2001 From: Celine Pelletier Date: Mon, 11 Dec 2023 17:20:28 -0500 Subject: [PATCH] feat: SKFP-889 add google analytics --- .env.schema | 4 +++- package-lock.json | 13 ++++++++++++- package.json | 1 + src/App.tsx | 3 +++ src/helpers/EnvVariables.ts | 2 ++ src/provider/KeycloakProvider.tsx | 5 +++++ src/services/analytics.ts | 21 +++++++++++++++++++++ 7 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/services/analytics.ts diff --git a/.env.schema b/.env.schema index 781c79521..ab218f859 100644 --- a/.env.schema +++ b/.env.schema @@ -10,6 +10,9 @@ REACT_APP_NAMESPACE=dev # App lifecycle REACT_APP_MAINTENANCE_MODE=false +# Google Analytics +REACT_APP_MEASUREMENT_ID= + # APIS REACT_APP_PERSONA_API= REACT_APP_USERS_API_URL= @@ -20,7 +23,6 @@ REACT_APP_ARRANGER_PROJECT_ID= REACT_APP_CAVATICA_USER_BASE_URL= REACT_APP_VARIANT_CLUSTER_API= -jkjdkljksjd;w # FENCES REACT_APP_KEY_MANAGER_API_URL= REACT_APP_FENCE_API_URL= diff --git a/package-lock.json b/package-lock.json index 79f0d220c..b45a325df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "kids-first-portal-ui", - "version": "1.4.0", + "version": "5.0.0", "dependencies": { "@ant-design/icons": "^4.7.0", "@apollo/client": "^3.5.10", @@ -80,6 +80,7 @@ "react-app-polyfill": "^3.0.0", "react-dev-utils": "^12.0.1", "react-dom": "^17.0.2", + "react-ga4": "^2.1.0", "react-highlight-words": "^0.18.0", "react-intl-universal": "^2.4.8", "react-redux": "^7.2.6", @@ -27738,6 +27739,11 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, + "node_modules/react-ga4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz", + "integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==" + }, "node_modules/react-grid-layout": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.4.4.tgz", @@ -54487,6 +54493,11 @@ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" }, + "react-ga4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz", + "integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ==" + }, "react-grid-layout": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.4.4.tgz", diff --git a/package.json b/package.json index cd073726f..ae1c9b290 100644 --- a/package.json +++ b/package.json @@ -120,6 +120,7 @@ "react-app-polyfill": "^3.0.0", "react-dev-utils": "^12.0.1", "react-dom": "^17.0.2", + "react-ga4": "^2.1.0", "react-highlight-words": "^0.18.0", "react-intl-universal": "^2.4.8", "react-redux": "^7.2.6", diff --git a/src/App.tsx b/src/App.tsx index 3fa9d9400..41ccce4fe 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -41,6 +41,7 @@ import Spinner from 'components/uiKit/Spinner'; import NotificationContextHolder from 'components/utils/NotificationContextHolder'; import { useLang } from 'store/global'; import { DYNAMIC_ROUTES, STATIC_ROUTES } from 'utils/routes'; +import { initGa } from 'services/analytics'; const loadableProps = { fallback: }; const Dashboard = loadable(() => import('views/Dashboard'), loadableProps); @@ -53,6 +54,8 @@ const VariantEntity2 = loadable(() => import('views/VariantEntity'), loadablePro const FileEntity = loadable(() => import('views/FileEntity'), loadableProps); const ProfileSettings = loadable(() => import('views/Profile/Settings'), loadableProps); +initGa(); + const App = () => { const lang = useLang(); const { keycloak, initialized } = useKeycloak(); diff --git a/src/helpers/EnvVariables.ts b/src/helpers/EnvVariables.ts index 4c7c4f8e3..3338281bc 100644 --- a/src/helpers/EnvVariables.ts +++ b/src/helpers/EnvVariables.ts @@ -27,6 +27,8 @@ export default class EnvironmentVariables { REPORTS_API_URL: process.env.REACT_APP_REPORTS_API_URL, // MAINTENANCE MAINTENANCE_MODE: process.env.REACT_APP_MAINTENANCE_MODE, + // GA + MEASUREMENT_ID: process.env.REACT_APP_MEASUREMENT_ID, }; static configFor(key: string): string { diff --git a/src/provider/KeycloakProvider.tsx b/src/provider/KeycloakProvider.tsx index 97bd67e05..04ee29980 100644 --- a/src/provider/KeycloakProvider.tsx +++ b/src/provider/KeycloakProvider.tsx @@ -6,6 +6,7 @@ import { import EnvVariables from "helpers/EnvVariables"; import { ReactKeycloakProvider as KeycloakProvider } from "@react-keycloak/web"; import keycloak from "auth/keycloak-api/keycloak"; +import { trackAuthSuccess } from "services/analytics"; export interface IProvider { children: React.ReactNode; @@ -16,6 +17,10 @@ const eventLogger = (eventType: AuthClientEvent, error?: AuthClientError) => { console.error("eventLogger ", "eventType ", eventType); console.error("eventLogger ", error); } + + if (eventType === 'onAuthSuccess') { + trackAuthSuccess(); + } }; const Keycloak = ({ children }: IProvider): ReactElement => ( diff --git a/src/services/analytics.ts b/src/services/analytics.ts new file mode 100644 index 000000000..be0bc8b31 --- /dev/null +++ b/src/services/analytics.ts @@ -0,0 +1,21 @@ +import EnvironmentVariables from 'helpers/EnvVariables'; +import ReactGA from 'react-ga4'; + +const measurementId = EnvironmentVariables.configFor('MEASUREMENT_ID'); +const isDev = EnvironmentVariables.configFor('ENV') === 'development'; +const isGaActive = measurementId && !isDev; + +export const initGa = () => { + if (isGaActive) { + ReactGA.initialize(measurementId); + } +}; + +export const trackAuthSuccess = () => { + if (isGaActive) { + ReactGA.event({ + category: 'Authentication', + action: 'login success', + }); + } +};