diff --git a/Dockerfile b/Dockerfile index cab60159de..3fc4e7e959 100644 --- a/Dockerfile +++ b/Dockerfile @@ -60,6 +60,7 @@ ARG REALM_HOST ARG PORT=3000 ARG SERVICE_NAME=blip ARG ROLLBAR_POST_SERVER_TOKEN +ARG REACT_APP_GAID ARG I18N_ENABLED=false ARG RX_ENABLED=false ARG PENDO_ENABLED=true @@ -71,6 +72,7 @@ ENV \ PORT=$PORT \ SERVICE_NAME=$SERVICE_NAME \ ROLLBAR_POST_SERVER_TOKEN=$ROLLBAR_POST_SERVER_TOKEN \ + REACT_APP_GAID=$REACT_APP_GAID \ I18N_ENABLED=$I18N_ENABLED \ RX_ENABLED=$RX_ENABLED \ PENDO_ENABLED=$PENDO_ENABLED \ diff --git a/app/bootstrap.js b/app/bootstrap.js index 65c25e67b0..cd7f22facb 100644 --- a/app/bootstrap.js +++ b/app/bootstrap.js @@ -59,7 +59,6 @@ appContext.props = { }; appContext.init = callback => { - function beginInit() { initNoTouch(); } diff --git a/app/googleanalytics.js b/app/googleanalytics.js new file mode 100644 index 0000000000..c1b34cafeb --- /dev/null +++ b/app/googleanalytics.js @@ -0,0 +1,31 @@ +import React from 'react'; +import ReactGA from 'react-ga4'; +import { useLocation } from 'react-router-dom'; + +/* global __REACT_APP_GAID__ */ + +const GoogleAnalyticsWrapper = ({ children }) => { + const location = useLocation(); + const isInitialized = ReactGA.isInitialized; + + React.useEffect(() => { + if (__REACT_APP_GAID__ && isInitialized === false) { + ReactGA.initialize(__REACT_APP_GAID__, { gtagOptions: { 'send_page_view': false } }); + } + }, [isInitialized]); + + React.useEffect(() => { + if (ReactGA.isInitialized) { + ReactGA.send({ + hitType: 'pageview', + page: location?.pathname + location?.search + location?.hash, + 'page_search': location?.search, + 'page_hash': location?.hash, + }); + } + }, [location]); + + return children; +}; + +export default GoogleAnalyticsWrapper diff --git a/app/pages/signup/signup.js b/app/pages/signup/signup.js index 7a5eb3cd70..5e920ff6ed 100644 --- a/app/pages/signup/signup.js +++ b/app/pages/signup/signup.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; import React from 'react'; +import ReactGA from 'react-ga4'; import { connect } from 'react-redux'; import { translate, Trans} from 'react-i18next'; import { bindActionCreators } from 'redux'; @@ -167,6 +168,15 @@ export let Signup = translate()(class extends React.Component { if(inviteEmail){ options.loginHint = inviteEmail; } + + if (ReactGA.isInitialized) { + ReactGA.event({ + category: 'redirect', + action: 'Keycloak Sign Up', + label: inviteEmail ? 'Has inviteEmail' : 'No inviteEmail', + }); + } + keycloak.register(options); } diff --git a/app/redux/containers/Root.dev.js b/app/redux/containers/Root.dev.js index f3e12bf529..fff375cf53 100644 --- a/app/redux/containers/Root.dev.js +++ b/app/redux/containers/Root.dev.js @@ -8,6 +8,7 @@ import { KeycloakWrapper } from '../../keycloak'; import baseTheme from '../../themes/baseTheme'; import { history } from '../store/configureStore.dev'; import { ToastProvider } from '../../providers/ToastProvider'; +import GoogleAnalyticsWrapper from '../../googleanalytics'; setConfig({ logLevel: 'warning' }) @@ -21,7 +22,9 @@ class Root extends Component {
- {routing} + + {routing} +
diff --git a/app/redux/containers/Root.prod.js b/app/redux/containers/Root.prod.js index 7d2b3ebe60..2a83577d49 100644 --- a/app/redux/containers/Root.prod.js +++ b/app/redux/containers/Root.prod.js @@ -6,6 +6,7 @@ import { ThemeProvider } from 'styled-components'; import baseTheme from '../../themes/baseTheme'; import { history } from '../store/configureStore.prod'; import { ToastProvider } from '../../providers/ToastProvider'; +import GoogleAnalyticsWrapper from '../../googleanalytics'; import { KeycloakWrapper } from '../../keycloak'; export default class Root extends Component { @@ -18,7 +19,9 @@ export default class Root extends Component {
- {routing} + + {routing} +
diff --git a/config.webpack.js b/config.webpack.js index a4d6749b19..504b6bd2e0 100644 --- a/config.webpack.js +++ b/config.webpack.js @@ -27,6 +27,7 @@ const defineEnvPlugin = new webpack.DefinePlugin({ __PENDO_ENABLED__: JSON.stringify(process.env.PENDO_ENABLED || true), __VERSION__: JSON.stringify(VERSION), __ROLLBAR_POST_CLIENT_TOKEN__: JSON.stringify(ROLLBAR_POST_CLIENT_TOKEN), + __REACT_APP_GAID__: JSON.stringify(process.env.REACT_APP_GAID || null), __VERSION_SHA__: JSON.stringify(VERSION_SHA), __DEV__: isDev, __TEST__: false, diff --git a/config/local.example.js b/config/local.example.js index cf88dbe323..57c83c3143 100644 --- a/config/local.example.js +++ b/config/local.example.js @@ -35,6 +35,7 @@ const environments = { }; const apiHost = environments.dev; +const reactAppGAID = ' '; const uploadApi = apiHost; module.exports = { @@ -42,5 +43,6 @@ module.exports = { linkedPackages, featureFlags, apiHost, + reactAppGAID, uploadApi, }; diff --git a/package.json b/package.json index 1f4c37dad7..6c9f838995 100644 --- a/package.json +++ b/package.json @@ -130,6 +130,7 @@ "react": "16.12.0", "react-dates": "21.8.0", "react-dom": "16.12.0", + "react-ga4": "2.1.0", "react-hooks-testing-library": "0.6.0", "react-hot-loader": "4.12.19", "react-i18next": "7.13.0", diff --git a/webpack.config.js b/webpack.config.js index 1a00db3443..82897c6657 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -21,6 +21,7 @@ const isProd = (process.env.NODE_ENV === 'production'); const linkedPackages = (isDev || isTest) ? _.get(optional('./config/local'), 'linkedPackages', {}) : {}; const apiHost = _.get(optional('./config/local'), 'apiHost', process.env.API_HOST || null); const uploadApi = _.get(optional('./config/local'), 'uploadApi', process.env.UPLOAD_API || null); +const reactAppGAID = _.get(optional('./config/local'), 'reactAppGAID', process.env.REACT_APP_GAID || null); const featureFlags = _.get(optional('./config/local'), 'featureFlags', { i18nEnabled: process.env.I18N_ENABLED || false, rxEnabled: process.env.RX_ENABLED || false, @@ -158,6 +159,7 @@ const plugins = [ __PENDO_ENABLED__: JSON.stringify(featureFlags.pendoEnabled), __VERSION__: JSON.stringify(VERSION), __ROLLBAR_POST_CLIENT_TOKEN__: JSON.stringify(ROLLBAR_POST_CLIENT_TOKEN), + __REACT_APP_GAID__: JSON.stringify(reactAppGAID), __VERSION_SHA__: JSON.stringify(VERSION_SHA), __DEV__: isDev, __TEST__: isTest, diff --git a/yarn.lock b/yarn.lock index fdd0f02e9f..16bd90badc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15587,6 +15587,11 @@ react-focus-lock@^2.1.0: use-callback-ref "^1.2.1" use-sidecar "^1.0.1" +react-ga4@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-ga4/-/react-ga4-2.1.0.tgz#56601f59d95c08466ebd6edfbf8dede55c4678f9" + integrity sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ== + react-helmet-async@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.0.4.tgz#079ef10b7fefcaee6240fefd150711e62463cc97"