What is the best way to integrate Google Tag Manager into the content scripts of a Chrome extension?

I have a chrome extension that activates on certain websites and injects elements into the HTML DOM. Now, I am looking to integrate Google Tag Manager into the extension.

In the Google Tag Manager documentation, it instructs to add a specific function in the <head> tag of the page. Initially, I attempted to add the script tag to the document's <head> tag as soon as the extension is loaded:

const loadGTM = () => {
  const scriptTag = document.createElement("script");
  scriptTag.innerHTML = `(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=
  'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
  })(window,document,'script','dataLayer','GTM-XXXXXXX');`;
  document.head.appendChild(scriptTag);

  const noScriptTag = document.createElement("noscript");
  noScriptTag.innerHTML = `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
  height="0" width="0" style="display:none;visibility:hidden"></iframe>`;
  document.body.prepend(noScriptTag);
}

However, when I tried to connect through Google Tag Assistant, it was unsuccessful.

Subsequently, I experimented with running the script instead of adding it to the head tag. I created a new file named gtm.js and included the script within it:

//gtm.js
const accountToken = `GTM-XXXXXXX`;
function integrateGTM() {
  (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 = "https://www.googletagmanager.com/gtm.js?id=" + i + dl;
    f.parentNode.insertBefore(j, f);
  })(window, document, "script", "dataLayer", accountToken);
  const code = `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=${accountToken}"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>`;
  const bodyScript = document.createElement("noscript");
  bodyScript.innerHTML = code;
  document.body.prepend(bodyScript);
}

integrateGTM();

Yet again, after attempting to connect through Tag Assistant, there was no success.

If anyone has any insights or experience in this area, I would greatly appreciate some guidance. Thank you!

Answer №1

If you're unsure about using Google Tag Manager, an alternative option is to send requests directly to Google Analytics.

To make a post fetch request from your content script, you can use the following code snippet:

const trackEvent = (category, action, label, value) => {
const data = {
// API Version.
v: '1',
// Tracking ID / Property ID.
tid: GA_TRACKING_ID,
// Anonymous Client Identifier. This should ideally be a UUID associated with a specific user, device, or browser instance.
cid: '555',
// Event hit type.
t: 'event',
// Event category.
ec: category,
// Event action.
ea: action,
// Event label.
el: label,
// Event value.
ev: value,
};

return fetch('http://www.google-analytics.com/debug/collect', {
 params: data,
});
}

If necessary, you may need to include headers to mimic a request coming from a browser:

headers: {
    'user-agent':
      'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36',
  },

Additionally, you can also make a get request like this:

'https://www.google-analytics.com/collect?v=1&t={category}&tid=${GA_TRACKING_ID}&cid=555&dp=tube'

For more information, refer to: https://developers.google.com/analytics/devguides/collection/protocol/v1/reference#overview

In your script, call the function as follows:

try {
await trackEvent(
  'Example category',
  'Example action',
  'Example label',
  '100'
);
return 'Event tracked.');
} catch (error) {
 // handle error
}

Resources: https://cloud.google.com/appengine/docs/standard/integrating-with-analytics?tab=node.js#top

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for incorporating an XML page with vike (ssr) into my website?

When it comes to my website's SEO, I use vike for ssr and would like to incorporate a sitemap in XML format. The issue arises as vike builds my pages in html format. Is there a way to integrate an XML file for SEO purposes? I attempted to access the ...

Populate the table with JSON content using jQuery

I am attempting to populate a table with JSON data using jQuery, but the content within the div remains empty. I need assistance in identifying the error. The array list contains the data (I verified this using console.log(list)). Additionally, list[' ...

JavaScript generator function

I'm working on creating a function generator that can iterate over an infinite sequence, similar to the fibonacci sequence. The goal is to have it return the next value in the sequence each time it's called. Here is the function prototype I' ...

Reset Vuetify form when dialog is opened

I'm currently facing an issue on a Vue page that utilizes the Vuetify framework. The problem arises with a button that triggers a dialog from a child component: <div id="app"> <v-app id="inspire"> <v-row justif ...

Nodejs script designed to efficiently download all files from an FTP server to a local directory before seamlessly transferring them to another FTP folder

I am currently facing a challenge in downloading all files from a specific folder on an FTP site. The folder, named "IN" (as demonstrated in the example code), contains several .csv files. The requirements for this task are: Download all CSV files presen ...

Learn how to quickly resolve the issue in nodejs where the new image automatically replaces the old one when added

I have successfully created a file to upload images, however the image name appears as undefined.jpg in this project. I am using the Express file upload middleware. *admin.js var express = require("express"); const productHelpers = require("../helpers/pr ...

Tips on modifying the structure of a JSON array using a loop

Hello, I am currently extracting data from an API, but I need to transform the data into a different format in order to pass it to a function successfully. The reason for this is that I have a chart that only accepts data in a specific format for it to dis ...

What is the best way to add a color swatch image using Javascript?

I'm facing a challenge in Shopify where I need to assign corresponding background images to color swatches. Currently, my icons are set up with the correct links for each color, but they are missing their respective images, similar to this example. I ...

Setting up an Express route for updating data

I am in the process of developing a MEVN stack CRUD application (Vue, Node, Express, MongoDB). I am currently working on setting up an Express route for handling updates in my app... postRoutes.post('/update/:id', async(req, res)=> { cons ...

Tips for incorporating conditional statements within return statements in functional components in React JS

I need to display the login page if the user is not logged in, otherwise show the forbidden 403 page. Since I'm using a functional component, I can't use render(). return forbidden === false ? ( <> <Container maxWidth="x ...

How to retrieve the value of a table row by clicking with the mouse using jQuery?

I am having an issue with my table data display. Each row in the table is assigned a unique ID, which corresponds to the value of the tr-tag. My goal is to log this ID in the console when a table row is clicked. Here is the table: $.getJSON(`http://local ...

There is no index signature that includes a parameter of type 'number' on the specified type xx

Here are the data types I am currently utilizing: export interface IHelpDeskTextData { supportPaneltext: ContactHelpdeskContex[]; selected?: number | null; brandOptions?: string[]; textPanel?: ITextPanel[]; } export class ContactHelpdeskContex { ...

Sharing FormikProps between components in React: A step-by-step guide

I am struggling to pass the necessary values and props that Formik requires to the component one level up. My approach involves using several small components for various forms, and I need to pass them through a complex component to be able to pass them do ...

The Angular.js resource REST request encountered a TypeError due to a function being undefined

My goal is to update data using a REST call. I have already made a GET request to populate the form, and upon clicking the update button, I intend to initiate a PUT call. However, instead of successfully executing the PUT call, I encounter a Type Error. B ...

Choosing multiple options in a dropdown menu that updates dynamically according to the selection made in another dropdown

Is there a way to enable multi-select in a dynamically populated dropdown based on the selection of another dropdown? I have two dropdowns on my page. Initially, the second dropdown is empty. When a value is selected in the first dropdown, the options in ...

Is it possible to assign a different array to a variable in JavaScript?

I'm facing an issue with manipulating arrays in JavaScript within a function. This problem arises from an exercise found in the book Eloquent JavaScript, focusing on two specific functions: reverseArray(): designed to produce a new array that is the ...

What is the best way to display data retrieved from a GET request in Angular?

Spending too much time on a development issue is causing me frustration. After extensive research, I find myself stuck at this point. The problem lies in making a GET request from a service which is called by a controller. Below is the code for the servi ...

Linking two div elements together with a circular connector at the termination point of the line

I am currently working on designing a set of cards that will showcase a timeline. I envision these cards to be connected by lines with circles at each end, for a visually appealing effect. At the moment, I have created the cards themselves but I am struggl ...

JavaScript behavior differs in HTML form based on browser compatibility, resulting in "NaN" error in IE but functioning properly in Chrome

Although I may not be a skilled programmer, I was able to make this work in Chrome successfully. However, when I attempted it on IE (specifically version 11), I encountered an issue where it displayed "NaN." The script essentially takes four criteria and ...

the absence of any content being shown when using v-else

I'm currently delving into Vue.js and stumbled upon an unusual behavior that I couldn't find any information about on the Internet. For some reason, the DIV with v-else isn't rendering any content that I place inside it. I tried to underst ...