Skip to content

Commit 5349b3c

Browse files
Add initial GA4 implementation (GoogleChrome#9168)
* Add initial GA4 implementation * Address review feedback * Switch to exceptions name instead of error * Update pageshow event * guard loading GTM script on user cookies consent * Update cookie bar functionality * Fix lint issue * Address review feedback Co-authored-by: Ewa Gasperowicz <[email protected]>
1 parent 37d85a3 commit 5349b3c

File tree

48 files changed

+465
-367
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+465
-367
lines changed

.eslintrc.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ module.exports = {
1414
globals: {
1515
customElements: true,
1616
firebase: true,
17-
ga: true,
17+
gtag: true,
18+
loadScript: true,
19+
dataLayer: true,
1820
},
1921
rules: {
2022
indent: [

package-lock.json

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@
122122
"@percy/cli": "^1.0.0-beta.71",
123123
"@percy/puppeteer": "^2.0.0",
124124
"@types/chai": "^4.3.0",
125-
"@types/google.analytics": "0.0.40",
126125
"@types/grecaptcha": "^3.0.3",
126+
"@types/gtag.js": "^0.0.12",
127127
"@types/gulp": "^4.0.8",
128128
"@types/markdown-it": "^12.0.3",
129129
"@types/mocha": "^9.0.0",

rollup.config.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ const isProd = process.env.ELEVENTY_ENV === 'prod';
2929
const buildVirtualJSON = require('./src/build/virtual-json');
3030
const virtualImports = {
3131
webdev_analytics: {
32-
id: isProd ? site.analytics.ids.prod : site.analytics.ids.staging,
32+
ids: {
33+
UA: site.analytics.ids.ua,
34+
GA4: site.analytics.ids.ga4,
35+
},
3336
dimensions: site.analytics.dimensions,
3437
version: site.analytics.version,
3538
},

src/lib/actions.js

+45-14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {runPsi} from './psi-service';
44
import lang from './utils/language';
55
import {localStorage} from './utils/storage';
66
import cookies from 'js-cookie';
7+
import {ids} from 'webdev_analytics';
8+
import {isProd} from 'webdev_config';
79

810
export const clearSignedInState = store.action(() => {
911
const {isSignedIn} = store.getState();
@@ -156,26 +158,45 @@ export const closeModal = store.action(() => {
156158
return {isModalOpen: false};
157159
});
158160

159-
export const checkIfUserAcceptsCookies = store.action(
160-
({userAcceptsCookies}) => {
161-
if (userAcceptsCookies) {
162-
return;
163-
}
161+
export const checkIfUserAcceptsCookies = store.action(({cookiePreference}) => {
162+
if (cookiePreference) {
163+
return;
164+
}
164165

165-
if (localStorage['web-accepts-cookies']) {
166-
return {
167-
userAcceptsCookies: true,
168-
};
169-
}
166+
// If set, this will be either the string '1' or '0' based on whether
167+
// the user has accepted or rejected the use of cookies.
168+
// If not set it means the user has not made a choice (or cleared storage).
169+
const storedWebAcceptsCookiesValue = localStorage['web-accepts-cookies'];
170170

171-
return {showingSnackbar: true, snackbarType: 'cookies'};
172-
},
173-
);
171+
if (typeof storedWebAcceptsCookiesValue === 'string') {
172+
cookiePreference =
173+
storedWebAcceptsCookiesValue === '1' ? 'accepts' : 'rejects';
174+
} else {
175+
cookiePreference = null;
176+
}
177+
178+
// Only show the cookie snack-bar if the user hasn't set a preference.
179+
const showingSnackbar = cookiePreference === null;
180+
181+
return {cookiePreference, showingSnackbar, snackbarType: 'cookies'};
182+
});
174183

175184
export const setUserAcceptsCookies = store.action(() => {
176185
localStorage['web-accepts-cookies'] = '1';
177186
return {
178-
userAcceptsCookies: true,
187+
cookiePreference: 'accepts',
188+
showingSnackbar: false,
189+
// Note we don't set the snackbarType to null because that would cause the
190+
// snackbar to re-render and break the animation.
191+
// Instead, snackbarType is allowed to stick around and future updates can
192+
// overwrite it.
193+
};
194+
});
195+
196+
export const setUserRejectsCookies = store.action(() => {
197+
localStorage['web-accepts-cookies'] = '0';
198+
return {
199+
cookiePreference: 'rejects',
179200
showingSnackbar: false,
180201
// Note we don't set the snackbarType to null because that would cause the
181202
// snackbar to re-render and break the animation.
@@ -200,3 +221,13 @@ export const setLanguage = store.action((state, language) => {
200221
currentLanguage: language,
201222
};
202223
});
224+
225+
export const loadAnalyticsScript = store.action(() => {
226+
const {g4ScriptLoaded} = store.getState();
227+
if (!g4ScriptLoaded && isProd) {
228+
loadScript(`https://www.googletagmanager.com/gtag/js?id=${ids.GA4}`, null);
229+
return {
230+
g4ScriptLoaded: true,
231+
};
232+
}
233+
});

0 commit comments

Comments
 (0)