Google Universal Analytics property is shutting down. Here is what you need to know.

Contents

On the 16th of March 2022 Google announced its plans for a shutdown of Universal Analytics property and replace it fully with Goole Analytics 4 (v4) that been in the market since late 2020.

Google like to kill off their services. Luckily, this is not about shutting down Google Analytics but only the method, how analytics data are collected from websites. If you have been using Google Analytics for some time, then it’s more likely that you have been using Universal Analytics. You will know that by looking at your tracking code that will carry UA- on front of the numbers.

Analytics in its 4th version (UA is 3rd) has been developed for some time, but it wasn’t adopted as quick as Google could expect (or want), this is why they forcing a change by shutting down one in favour of another.

The first problem is, that UA is not compatible with GAv4. You cannot (not yet, and I would not expect that this will be possible) migrate your current traffic, visits etc. into GAv4. GAv4 is using a different method of gathering traffic and this is why if you want to use it, you will need to start collecting data from scratch (yes, I know, total nonsense!).

If you, as a web owner (but not only), need to migrate to GAv4, then the best time would be the last day of the year 2022 or the first day of the next one (2023).

Luckily Universal Analytics is shutting down on 1st July 2023 so you can carry on using your current solution and gather data for 2022 uninterrupted, and from the new year switch to Google Analytics 4. Thanks to that, if you need to analyse past year data, you will not need to jiggle between two analytics at the time.

The second problem is your website performance. People-oriented in improving web performance (like me) know, that Google Analytics tracking script can be easily blocked by AdBlockers (like I covered in my post Prevent Google Analytics from being blocked by AdBlocker), but also the script itself weight a bit and loading it (remember, Google own script) degrading website performance in PageSpeed Insight (also Google own solution). Mainly affected are crucial Core Web Vitals that are necessary for a good positioning over Google Search results!

Because of that, people have been using Minimal Google Analytics Snippet as a solution. According to minimalanalycs.com website, the Google Tag Manager + Analytics can weigh 73kB (mine weights 93kB!) where the snippet weights only 1.5kB. It looks small but this is a big difference if it’s going about web performance.

Both, the Google Analytics script and Minimal Analytics are vulnerable to blocking by AdBlockers.

If we need to resign from Minimal Analytics, as currently there is no minimal solution for Google Analytics 4 (yet), you will be forced to load Google’s script and risking in performance impact. The new script is a monster that adds at least 171kB (!) to your website and that can cause a huge impact on performance.

I hope, that somebody will manage to sort our minimal version of the new solution before the end of the year (will be monitoring this for my benefit), however, if not, before rushing into the implementation of a new solution into your website, let’s do this the smart way - the way Smashing Magazine do on their website, as I explained it in post Implementing JavaScript Delay for Cookie Consent Banner.

Let’s then delay Google Analytics JavaScript until real user interaction happens on the website, together with marking-up (hiding) Google tracking script in a smart way (which I will cover below), so AdBlockers will not be blocking it, giving us much more accurate data for our analysis.

Before we move any further, there is another issue that you need to remember about closing Universal Analytics property.

You can delay your migration until 1st July 2023 (which I strongly discourage). After this period your UA will stop collecting data and you will have only 6 months left, under which you will be able to access its records (not mentioning that you will have half data in the old property at the time and half in the new that you will need to use). As there is not possible to just migrate them to a new solution you need to remember to export it before they disappear for good. Let’s plan and be ready for 2023 to start with the new solution using a smart approach.

Here is how we will do that.

Smashing Magazine approach #

Before I start, let’s see how Smashing Magazine is calling their analytics script:

<script class=js-additional importance=low delay=https://www.google-analytics.com/analytics.js defer></script>

If I am not wrong, they still using Universal Analytics and they will need to implement GAv4 as well (unless they will migrate somewhere else).

As I mentioned in my previous post regarding JavaScript Delay, they making the above script invalid (for HTML) by removing src part from it. Without it, the script will not load. After that they use another JavaScript that will run JavaScript Delay, which, when required, will replace the word delay with src and the above <script> will become valid again and run what is required.

Let’s ignore class=js-additional and importance=low for now.

The last thing is defer which will try to load (and fail by default) script after a page is loaded.

Now it’s time for delayer.

JavaScript Delay #

We will be using following code (ideally as a last part before closing </body>):

<script>
const autoLoadDuration = 5; //In Seconds
const eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];

const autoLoadTimeout = setTimeout(runScripts, autoLoadDuration * 1000);

eventList.forEach(function(event) {
    window.addEventListener(event, triggerScripts, { passive: true })
});

function triggerScripts() {
    runScripts();
    clearTimeout(autoLoadTimeout);
    eventList.forEach(function(event) {
         window.removeEventListener(event, triggerScripts, { passive: true });
    });
}

function runScripts() {
    document.querySelectorAll("script[delay]").forEach(function(scriptTag) {
        scriptTag.setAttribute("src", scriptTag.getAttribute("delay"));
    });
}
</script>

This script will wait for user interaction by pressing the key, moving a mouse or touching the screen. This is the real interaction of the real user, not the machine that is “just” testing performance or crawling the page.

After that interaction, it will fire up all delayed scripts. In our example, it will fire up Google Analytics.

The problem with trying to run an external script from google-analytics.com is that this will be blocked by most AdBlockers.

It will work for some users, but you can easily see, that you will be missing like 30% of visits if not more.

Following plausible.io approach to fighting with AdBlockers we will be doing some magic here.

Google Analytics 4 code (Global site tag - gtag.js) #

Before we will do the magic, let’s see how the new tracking code looks.

<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-FD38MN17VB"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-FD38MN17VB');
</script>

Independently if it runs from google-analytics.com or googletagmanager.com it will still be picked and blocked by AdBlockers.

Masking (hiding) Google Analytics 4 code #

To hide the code from our script we will be pretending that we will be calling our script locally, and using redirect rule 200 we will be doing the rest in the background.

As I am using Netlify as my hosting provider, I will be putting my redirect into _redirects file as follow:

/collect/js   https://www.googletagmanager.com/gtag/js   200

According to Netlify redirect options with Query parameters:

“(…) our service automatically passes on all query string parameters to destination paths for redirects with 200, (…)”

We can make redirects as simple as possible.

If we want however to pick query parameter and pass further, we can do this in such a way

/collect/js id=:id  https://www.googletagmanager.com/gtag/js?id=:id  200

The way, how this can be implemented strictly depend on what your hosting provider is offering.

My modified code with implemented redirect rule will looks as follow:

<script async src="/collect/js?id=G-FD38MN17VB"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-FD38MN17VB');
</script>

If I implement delay (along with defer), it will be:

<script delay="/collect/js?id=G-FD38MN17VB" defer></script>
<script delay="/js/big-g-2nd-part.js" defer></script>

The second part of the code, just:

  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-FD38MN17VB');

I put it into /js/ folder at the root of my website, into a file called big-g-2nd-part.js that will fire up after the first. The naming of the file is up to you, but don’t call it analytics.js as this can be easily blocked.

And like that, theoretically, we will have this heavy (171kB) analytics script fired up after the page is loaded (after Google PageSpeed Insight robots will stop rendering it). And that is working as expected.

What is not working is the masking idea. When calling GTAG script through, when loaded it will still call google-analytics.com/collect, and that will be picked up by AdBlockers and blocked.

I will be evaluating how to bypass that, but not sure if that will be possible without hosting the analytics script locally. For now, the below code will be sufficient.

<script delay="https://www.googletagmanager.com/gtag/js?id=G-FD38MN17VB" defer></script>
<script delay="/js/big-g-2nd-part.js" defer></script>

I am not using self-hosted analytics code, which Google can penalise for, but it would potentially save my website from an unnecessary drop in performance. If I want to future proof it against picking up by AdBlockers however I will need to assess the risk. Big players are doing it, so maybe this Google threatening finger is only for show.

Using marking of the calls to google analytics can have a downside, like I explained in my other post.

Fingers crossed, that somebody will provide for us Minimal Analytics for v4, like David Künnen provided for us for v3 (Universal Analytics).

Based on David’s Minimal Analytics code and a couple of websites explaining Google Analytics 4 measurement protocol I managed to create mine A very Minimal Google Analytics 4 Snippet.

Comments