javascriptgoogle-chrome-extensiongoogle-analyticsgoogle-tag-managergoogle-analytics-4

Using Google Tag Manager with Google Analytics to track a Chrome Extension (2020)


I am working on a chrome extension, and I would like to be able to track metrics with google analytics. I believe the easiest way to do that would be through tag manager, and I have found this tutorial that explains how to implement google tag manager in a chrome extension. However, just following this tutorial isn't working for me, and I have a few questions.

I have it set up so that the GTM code is in a separate js file that is injected into the iframe html code at the end of the head tag. I have modified the CSP in the manifest to allow requests to google analytics and google tag manager. And when building the tag in GTM, I set the fields checkProtocolTask to false, page to a custom url, and path to {{Page Path}} as the above tutorial and this SO question have suggested. For now I have my GA account set up with GA4, and I'm using a web data stream. I have the GTM tag as a GA4 configuration and I have made sure I included the correct measurement ID. I'm having a hard time finding any information about using GTM/GA in a chrome extension, and so any answers or suggestions would be greatly appreciated.


Solution

  • Okay, for anyone still wondering how to add Analytics to a Chrome Extension, I've figured it out.

    First of all, you have to use Universal Analytics (analytics.js), Google Analytics 4 (gtag.js) will not work. It doesn't handle tasks, and we will need to disable certain tasks in order to send hits. Also, it may be possible to use UA with Google Tag Manager, but after I got so deep into figuring this out I decided it would just be easier for me to implement tracking in the code myself. This video that shows you how to set up a UA property in Google Analytics.

    In my code, I created a JavaScript file ga.js, with the typical google analytics tracking code that looks like this:

    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
    
    ga("create", "UA-XXXXX-X", "auto");
    

    with two slight modifications: add the 'https:' in front of the google analytics url, and of course add your own UA property id.

    After that, we have to disable checkProtocolTask by adding

    ga('set', 'checkProtocolTask', null);
    

    This disables file protocol checking, which we need because google analytics aborts the hit if it's not originating from an http or https protocol (this is originating from a 'chrome-extension://' protocol). I also found I needed to disable checkStorageTask in the same manner, though I am less sure why I needed to do that. All of the resources I have found say that only the checkProtocolTask needs to be disabled to use GA in a CE. My best guess is because my extension isn't a popup, but an injected iFrame, so the cookie permissions are different. I asked this question about it, but haven't gotten any responses. In order to still track user sessions without the use of cookies, I used localStorage to store the ga clientId, as shown here.

    I then linked this javascript file at the bottom of the head section of my html file, and added

    "content_security_policy": "script-src 'self' https://www.google-analytics.com; object-src 'self'"
    

    to my manifest.json. And Voila! It's working.

    Some last minute notes: I definitely recommend using analytics_debug.js while debugging analytics, and if you are still having trouble figuring out the issue then try setting window.ga_debug = {trace: true}; to get an even more detailed log in the console. Also, when sending pageviews, it is important to include the page in the hit as so: ga('send', 'pageview', '/popup');.

    This was an absolute headache to figure out, so I hope this helps someone!