* Replace GTM ID

* Comment regarding container id added | GTM ID updated in mozfest base

* Linting corrections: indentation

* Update initial GTM setup - replace first ReactGA event: footer donate button

* Files updated from ReactGA.event to dataLayer.push: primary nav, submission form, layout signup

* Analytics events updated from ReactGA.event to dataLayer.push

* Share vote tap events updated  from ReactGA to GTM dataLayer.push

* ReactGA module removal and events update for cta-button, header-donate, and social share

* Footer social button event updated

* home-banner, primary-button, and homepage events updated

* homepage linting fix | participate donate, pulse profile, pulse profile list, and share button events updated

* CTA download event updated | ReactGA module removed from not used files

* Linting fixtures and integration tests

* Conflicts fixed in merge with main

* GTM ID correction after merged

* Duplicated angle bracket corrected

* csp_nonce template added to new inline script
This commit is contained in:
Diego López 2024-09-10 11:57:32 -06:00 коммит произвёл GitHub
Родитель f71d5a9729
Коммит 4875003e16
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
20 изменённых файлов: 80 добавлений и 68 удалений

Просмотреть файл

@ -9,9 +9,9 @@
{% block ga_identifier %}
<meta name="google-site-verification" content="xuTYNuCtTC9SLIkAUtmUY9Wce5RDJofc4z4fMprPYUk" />
<meta name="ga-identifier" content="UA-87658599-15">
<!-- The current GTM ID replaced an unkown GTM container with no clear access -->
<meta name="gtm-identifier" content="GTM-PQQ8H6PM">
<script nonce="{{ request.csp_nonce }}">window.dataLayer = window.dataLayer || [];</script>
<script nonce="{{ request.csp_nonce }}">(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=

Просмотреть файл

@ -39,9 +39,9 @@
{% block ga_identifier %}
<meta name="google-site-verification" content="D7k-r3fHm-XfJ9E7T1uZ5aqHJG2mx-0uUZFeBUDN2lY">
<meta name="ga-identifier" content="UA-87658599-6">
<!-- The current GTM ID replaced an unkown GTM container with no clear access -->
<meta name="gtm-identifier" content="GTM-PQQ8H6PM">
<script nonce="{{ request.csp_nonce }}">window.dataLayer = window.dataLayer || [];</script>
<script nonce="{{ request.csp_nonce }}">(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=

Просмотреть файл

@ -1,4 +1,4 @@
import { ReactGA, GoogleAnalytics } from "../common";
import { GoogleAnalytics } from "../common";
/**
* Based on given page title and product name, generate an object to use for GA events
@ -10,6 +10,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
return {
// "site-wide" events
"[data-donate-header-button]": {
event: `donate_header_button`,
category: `buyersguide`,
action: `donate tap`,
label: `${pageTitle} donate header`,
@ -17,6 +18,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
// product events
"#product-company-url": {
event: `product_company_link_tap`,
category: `product`,
action: `company link tap`,
label: `company link for ${productName}`,
@ -25,6 +27,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
conditionalQuery: `#view-product-page`,
},
"#product-live-chat": {
event: `customer_support_link_tap`,
category: `product`,
action: `customer support link tap`,
label: `support link for ${productName}`,
@ -34,6 +37,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
optional_element: true,
},
"#product-email": {
event: `email_link_tap`,
category: `product`,
action: `email link tap`,
label: `email link for ${productName}`,
@ -43,6 +47,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
optional_element: true,
},
"#product-twitter": {
event: `twitter_link_tap`,
category: `product`,
action: `twitter link tap`,
label: `twitter link for ${productName}`,
@ -52,6 +57,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
optional_element: true,
},
"#creep-vote-btn": {
event: `opinion_submitted`,
category: `product`,
action: `opinion submitted`,
label: `opinion on ${productName}`,
@ -59,6 +65,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
conditionalQuery: `#view-product-page`,
},
"a.privacy-policy-link": {
event: `privacy_policy_link_tap`,
category: `product`,
action: `privacy policy link tap`,
label: `policy link for ${productName}`,
@ -67,6 +74,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
conditionalQuery: `#view-product-page`,
},
".product-update-link": {
event: `update_article_link_tap`,
category: `product`,
action: `update article link tap`,
label: `update article link for ${productName}`,
@ -77,6 +85,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
optional_element: true,
},
"#mss-link": {
event: `minimum_security_standards_link_tap`,
category: `product`,
action: `minimum security standards link tap`,
label: `mss link for ${productName}`,
@ -84,6 +93,7 @@ function getQuerySelectorEvents(pageTitle, productName) {
conditionalQuery: `#view-product-page`,
},
".btn-recommend": {
event: `submit_a_product_button_tap`,
category: `buyersguide`,
action: `submit a product button tap`,
label: `submit a product button tap on ${pageTitle}`,
@ -99,7 +109,11 @@ function getQuerySelectorEvents(pageTitle, productName) {
* @param {Object} eventData data to send as GA event
*/
function setupElementGA(element, eventData) {
element.addEventListener("click", () => ReactGA.event(eventData), true);
element.addEventListener(
"click",
() => window.dataLayer.push(eventData),
true
);
}
/**
@ -120,7 +134,7 @@ function bindCheckboxCheckedGA(selector, eventData) {
"change",
() => {
if (checkbox.checked) {
ReactGA.event(eventData);
window.dataLayer.push(eventData);
}
},
true
@ -147,7 +161,8 @@ function trackSearchBoxUsage() {
let searchBoxUsed = sessionStorage.getItem(SESSION_KEY);
if (!searchBoxUsed) {
ReactGA.event({
window.dataLayer.push({
event: `type_in_search_box`,
category: `buyersguide`,
action: `type in search box`,
label: `search box used`,
@ -177,7 +192,8 @@ function trackGoBackToAllProductsLink() {
link.addEventListener(
"click",
() => {
ReactGA.event({
window.dataLayer.push({
event: `product_not_found_all_link_tap`,
category: `buyersguide`,
action: `product not found All link tap`,
label: `All link tap for ${searchBox.value}`,
@ -228,6 +244,7 @@ const ProductGA = {
if (elements.length > 0) {
const eventData = {
event: baseData.event,
category: baseData.category,
action: baseData.action,
label: baseData.label,
@ -248,6 +265,7 @@ const ProductGA = {
// tracks when MSS accordion on product page is expanded
if (document.querySelector(`#view-product-page`)) {
bindCheckboxCheckedGA("#view-product-page #mss-accordion-toggle", {
event: `security_expand_accordion_tap`,
category: `product`,
action: `security expand accordion tap`,
label: `detail view for MSS on for ${productName}`,
@ -256,6 +274,7 @@ const ProductGA = {
if (document.querySelector(`body.catalog`)) {
bindCheckboxCheckedGA("body.catalog #product-filter-pni-toggle", {
event: `ding_checkbox_checked`,
category: `buyersguide`,
action: `ding checkbox checked`,
label: `ding checkbox checked on ${pageTitle}`,

Просмотреть файл

@ -1,5 +1,4 @@
import React from "react";
import { ReactGA } from "../../../common";
import copyToClipboard from "../../../../js/copy-to-clipboard.js";
/**
@ -15,6 +14,7 @@ const SocialShareLink = (props) => {
props.productName
} is ${props.creepType.toUpperCase()}. What do you think? Check out the Creep-O-Meter over on @mozillas ${link} buyers guide.`;
let shareEvent = {
event: `share_vote_`,
category: `product`,
action: `share tap`,
label: `share vote `,
@ -25,6 +25,7 @@ const SocialShareLink = (props) => {
classes += `facebook-share`;
srLabel = `Facebook`;
shareEvent.label += `to facebook`;
shareEvent.event += `to_facebook`;
link = `https://www.facebook.com/sharer/sharer.php?u=https://${link}`;
}
@ -32,6 +33,7 @@ const SocialShareLink = (props) => {
classes += `twitter-share`;
srLabel = `Twitter`;
shareEvent.label += `to twitter`;
shareEvent.event += `to_twitter`;
link = `https://twitter.com/intent/tweet?text=${encodeURIComponent(
shareText
)}`;
@ -41,6 +43,7 @@ const SocialShareLink = (props) => {
classes += `email-share`;
srLabel = `Email`;
shareEvent.label += `via email`;
shareEvent.event += `via_email`;
link = `mailto:?&body=${encodeURIComponent(shareText)}`;
}
@ -48,11 +51,12 @@ const SocialShareLink = (props) => {
classes += `link-share`;
srLabel = `Copy`;
shareEvent.label += `using a link`;
shareEvent.event += `using_a_link`;
link = `#`;
}
let trackShareAction = () => {
ReactGA.event(shareEvent);
window.dataLayer.push(shareEvent);
};
// We actually need slightly different behaviour

Просмотреть файл

@ -5,13 +5,14 @@ import { ReactGA } from "../react-ga-proxy.js";
* ("Donate" button on footer)
*/
export default () => {
let donateFooterBtn = document.getElementById(`donate-footer-btn`);
let donateFooterBtn = document.getElementById("donate-footer-btn");
if (donateFooterBtn) {
donateFooterBtn.addEventListener(`click`, () => {
ReactGA.event({
category: `donate`,
action: `donate button tap`,
donateFooterBtn.addEventListener("click", () => {
window.dataLayer.push({
event: "donate_button_click",
category: "donate",
action: "donate button tap",
label: `${document.title} footer`,
});
});

Просмотреть файл

@ -1,4 +1,4 @@
import { ReactGA } from "../../common";
import { ReactGA } from "../react-ga-proxy.js";
/**
* Bind click handler to data-donate-header-button
@ -11,7 +11,8 @@ export default () => {
if (donateHeaderBtn.length > 0) {
donateHeaderBtn.forEach((element) => {
element.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `donate_button_tap_header`,
category: `donate`,
action: `donate button tap`,
label: `${document.title} header`,

Просмотреть файл

@ -12,7 +12,6 @@ import ButtonQuit from "../atoms/button-quit.jsx";
import APIErrorMessage from "../atoms/api-error-message.jsx";
import withSubmissionLogic from "./with-submission-logic.jsx";
import utility from "../../../utility.js";
import { ReactGA } from "../../../common";
import { getText, getCurrentLanguage } from "../../petition/locales";
import { COUNTRY_OPTIONS } from "../data/country-options.js";
import { LANGUAGE_OPTIONS } from "../data/language-options.js";
@ -92,7 +91,8 @@ class DefaultSignupForm extends Component {
}
handleInputFocus() {
ReactGA.event({
window.dataLayer.push({
event: `signup_form_input_focused`,
category: `signup`,
action: `form focus`,
label: `Signup form input focused`,

Просмотреть файл

@ -1,6 +1,5 @@
import React from "react";
import PropTypes from "prop-types";
import { ReactGA } from "../../../common";
import { getText } from "../../petition/locales";
/**
@ -104,21 +103,17 @@ function withSubmissionLogic(WrappedComponent) {
* @returns {void}
*/
trackFormSubmit(formData) {
ReactGA.event({
category: `signup`,
action: `form submit tap`,
label: `Signup submitted from ${
this.props.formPosition ? this.props.formPosition : document.title
}`,
});
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: "form_submission",
event: "form_submission_newsletter_signup",
category: `signup_submitted_from`,
action: `form submit tap`,
form_type: "newsletter_signup",
form_location: this.props.formPosition || null,
country: formData.country,
language: formData.language,
label: `Signup submitted from ${
this.props.formPosition ? this.props.formPosition : document.title
}`,
});
}

Просмотреть файл

@ -1,5 +1,4 @@
import { Component } from "react";
import { ReactGA } from "../../common";
import DonationModal from "./donation-modal.jsx";
import copyToClipboard from "../../copy-to-clipboard";

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../../../common";
/**
* Bind handler to CTA button on Dear Internet page
*/
@ -9,7 +7,8 @@ export default () => {
if (!ctaButton) return;
ctaButton.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `main_cta_donate_button_tap`,
category: `donate`,
action: `donate button tap`,
label: `main CTA`,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../../../common";
/**
* Bind handler to social buttons on MozFest footer
*/
@ -8,7 +6,8 @@ export default () => {
.querySelectorAll(`body.mozfest footer a[data-platform]`)
.forEach((button) => {
button.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `footer_social_button_tap`,
category: `social`,
action: `social button tap`,
label: `${button.dataset.platform} footer button tap`,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../../../common";
/**
* Mozfest hero banner video component.
* Provides play/pause buttons functionality, as well as GA tracking of video plays.
@ -100,7 +98,8 @@ const backgroundHardcodedVideoHandler = () => {
// Track video watches in google analytics
const trackWatchVideoClicks = () => {
ReactGA.event({
window.dataLayer.push({
event: `cta_watch_video_tap`,
category: `CTA`,
action: `watch video tap`,
label: `watch video button tap`,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../../../common";
/**
* Bind handler to primary buttons on MozFest
*/
@ -8,7 +6,8 @@ export default () => {
.querySelectorAll(`body.mozfest .cms a.tw-btn-primary`)
.forEach((button) => {
button.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `cta_button_tap`,
category: `CTA`,
action: `button tap`,
label: button.innerText,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../../../../common";
/**
* Bind handler to download button for Firefox/Chrome download button
* on the youtube regrets page.
@ -17,7 +15,8 @@ export default () => {
: ``;
button.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `cta_download`,
category: `CTA download`,
action: `${browserName}${location} button tap`,
label: `${document.title} - ${button.innerText}`,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../common";
/**
* Bind click handler for call to action links
*/
@ -9,7 +7,8 @@ export default () => {
let bindCtaGA = (element, eventAction) => {
if (element) {
element.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: eventAction.replace(" ", "_"),
category: `CTA read more`,
action: eventAction,
label: `${DOC_TITLE} - ${element.innerText}`,
@ -46,7 +45,8 @@ export default () => {
let donateBannerCta = document.querySelector("#donate-banner-cta");
if (donateBannerCta) {
donateBannerCta.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `donate_button_tap_banner`,
category: `donate`,
action: `donate button tap banner`,
label: `${DOC_TITLE} banner`,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../common";
/**
* Bind click handler to "#view-participate .card-cta .btn[href*="donate.mozilla.org"]"
* (the Donate CTA button on participate page)
@ -11,7 +9,8 @@ export default () => {
if (participateDonateBtn) {
participateDonateBtn.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `donate_button_tap_participate_page`,
category: `donate`,
action: `donate button tap`,
label: document.title,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "../../common";
/**
* Bind handlers to elements in ".profiles .person-card"
*/
@ -13,8 +11,8 @@ export default () => {
) {
if (socialTwitter) {
socialTwitter.addEventListener(`click`, () => {
ReactGA.event({
category: `profiles`,
window.dataLayer.push({
category: `profiles_tap_twitter`,
action: `profile tap`,
label: `${document.title} ${profileName} twitter`,
transport: `beacon`,
@ -24,8 +22,8 @@ export default () => {
if (socialLinkedIn) {
socialLinkedIn.addEventListener(`click`, () => {
ReactGA.event({
category: `profiles`,
window.dataLayer.push({
category: `profiles_tap_linkedin`,
action: `profile tap`,
label: `${document.title} ${profileName} linkedin`,
transport: `beacon`,
@ -40,7 +38,8 @@ export default () => {
// event listener & GA
let bindAnalytics = (element, profileName) => {
element.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `profiles_tap_pulse_profile`,
category: `profiles`,
action: `profile tap`,
label: `${document.title} ${profileName} pulse profile`,

Просмотреть файл

@ -1,10 +1,9 @@
import { ReactGA } from "../../common";
/**
* Bind click handler to
* ".profile-directory .fellowships-directory-filter .filter-option button"
* (filter buttons on fellowships' Pulse directory)
*/
export default () => {
document
.querySelectorAll(
@ -13,7 +12,8 @@ export default () => {
.forEach((filter) => {
let year = filter.textContent.trim();
filter.addEventListener(`click`, () => {
ReactGA.event({
window.dataLayer.push({
event: `profiles_directory_filter`,
category: `profiles`,
action: `directory filter`,
label: `${document.title} ${year}`,

Просмотреть файл

@ -1,4 +1,3 @@
import { ReactGA } from "../../common";
import copyToClipboard from "../../copy-to-clipboard";
export default () => {
@ -11,7 +10,8 @@ export default () => {
}
let bindGaEvent = (type = ``) => {
ReactGA.event({
window.dataLayer.push({
event: `social_share_tap`,
category: `social`,
action: `${type} share tap`,
label: `${type} share`,

Просмотреть файл

@ -1,5 +1,3 @@
import { ReactGA } from "./common";
let primaryNav = {
init: function () {
let elBurger = document.querySelector(`.burger`);
@ -35,13 +33,15 @@ let primaryNav = {
function trackMenuState(openMenu) {
if (openMenu) {
ReactGA.event({
window.dataLayer.push({
event: `show_navigation_menu`,
category: `navigation`,
action: `show menu`,
label: `Show navigation menu`,
});
} else {
ReactGA.event({
window.dataLayer.push({
event: `hide_navigation_menu`,
category: `navigation`,
action: `hide menu`,
label: `Hide navigation menu`,