Combining Methods to Prevent Adblockers from Blocking Your Minimal Google Analytics 4 Snippet

Contents

When I developed my Minimal Google Analytics 4 snippet, I thought about preventing it from being blocked by various AdBlockers.

Along with AdBlock Plus, I am also using the DuckDuckGo Privacy Protection extension in Safari. I am using the DuckDuckGo browser on its own as well.

DuckDuckGo, along with restrictive ad blockers, tends to block requests heading to the google-analytics.com domain. This is done on purpose, and I fully understand that.

This is why I described mitigation techniques (Minimal Analytics 4 - masking (hiding) requests).

This technique allows you to utilize Redirect 200 to mask requests to external domains under your domain.

By implementing a redirect as follows:

/g/collect https://www.google-analytics.com/g/collect 200

Instead of calling the address below in a script

https://www.google-analytics.com/g/collect

I am calling this

https://www.example.com/g/collect

Behind the scenes, thanks to Redirect 200, I am sending requests to Google Analytics that are not blocked by either AdBlock Plus or DuckDuckGo.

This solution, however, has 2 major flaws.

  1. Only some people can use Redirect 200, especially for external domains.

Where I cannot do much about it, apart from advising utilizing Netlify for this, users are left with losing the actual analytics and not getting the true figures for website visits.

You can set up Netlify independently of where your site is hosted and utilize it only for Redirect 200. Your website will be pointing in the script to the Netlify address and then from there back to Google Analytics.

  1. Redirect 200 masks users’ locations, from which the traffic is coming.

If you call google-analytics.com in your script directly (and it is not blocked), traffic details are sent to Google Analytics 4 together with information about where it is based on the user’s IP address. This IP address allows for better geolocation and shows much more accurately where (which country, city) the user is coming from.

If you call your domain behind Redirect 200, the request is sent with the location of your server (from where the request originates), or if you are using a CDN, with the location of the CDN point (server).

For example, when using Netlify to perform Redirect 200, and you are surfing from the United Kingdom (or anywhere in Europe), your Google Analytics dashboard will show your users coming from Frankfurt, Germany.

Google Analytics map showing users originates from Frankfurt Germany

You can be in the UK, Poland, or Spain, and you will still be shown as traffic coming from Frankfurt, Germany. This is where the Europe CDN server for Netlify is located.

Inspiration

I have in mind a solution that is available for JavaScript. When JavaScript is enabled, it can run code inside <script>. If JavaScript is not available, then it can return what’s inside the <noscript> tag.

Like this:

<script>
document.write("Hello World!")
</script>
<noscript>Your browser does not support JavaScript!</noscript>

I have been thinking if I can have a similar approach for JavaScript.

Please keep in mind that I am not an expert in that field. I am learning along the way as I explore things.

I want to detect when a request for the google-analytics.com domain is blocked, and then serve the masked request (for users using AdBlocker), but when it is not blocked, serve an unmasked script (for users not blocking requests).

That’s in theory.

Theory in practice

After doing my search, I found something like this:

<script>

    let blocked = false;
  
    function success() {
      console.log("Success! A-script loaded. Website is likely reachable.");
      // Add your actual success logic here
      // minimal analytics tracking code goes here (https://www.google-analytics.com/g/collect)
    }
  
    function alternate() {
      console.log("Failed to load a-script. AdBlock might be blocking the request.");
      // Add your alternate functionality here
      // minimal analytics tracking code with implemented Redirect 200 goes here (https://www.example.com/g/collect)
    }
  
    const ascript = document.createElement('script');
    ascript.src = 'https://www.google-analytics.com/g/collect';  // Update URL to primary a-script
      
    ascript.onload = function() {
      blocked = false;
      success();
    }
  
    ascript.onerror = function() {
      blocked = true;
      alternate();
    }
  
    document.head.appendChild(ascript);
  
</script>

Code from the Minimal Google Analytics 4 Snippet, pasting the content from between the <script> tags only and removing both console.log lines from the script.

When you install the DuckDuckGo Privacy Protection in Safari, it will report straight as “Request Blocked from Loading” and in detail advise about blocked Google Analytics.

If you run Web Inspector, in the console you will see the response Failed to load a-script. AdBlock might be blocking the request..

Just changing google-analytics.com/g/collect to just example.com will return Success! A-script loaded. Website is likely reachable..

We are creating the script element, but we are not loading anything from it. It’s just a dummy script that is used for identification if it is blocked or not.

If the script is blocked, then function alternate() will be fired. This is where we will paste our minimal analytics snippet with implemented Redirect 200.

If the block is not detected, then function success() will run. This will contain code for minimal analytics with a direct reference to the google-analytics.com domain.


If you prefer (recommended), instead of pasting analytics code inside the same script, loading separate scripts, this approach will be:

<script>

  let blocked = false;

  const ascript = document.createElement('script');
  ascript.src = 'https://www.google-analytics.com/g/collect';  // Update URL to primary a-script

  ascript.onload = function() {
    blocked = false;
    console.log("Success! A-script loaded. Website is likely reachable.");

    // Load success script
    const successScript = document.createElement('script');
    successScript.src = 'success.js';
    document.head.appendChild(successScript);
  }

  ascript.onerror = function() {
    blocked = true;
    console.log("Failed to load a-script. AdBlock might be blocking the request.");

    // Load alternate script
    const alternateScript = document.createElement('script');
    alternateScript.src = 'alternate.js';
    document.head.appendChild(alternateScript);
  }

  document.head.appendChild(ascript);

</script>

The alternate.js will contain code with Redirect 200 implemented (https://www.example.com/g/collect) and success.js without (https://www.google-analytics.com/g/collect).

Code from the Minimal Google Analytics 4 Snippet, pasting the content from between the <script> tags only and removing both console.log lines from the script.


While it’s not possible to directly remove the initially created script element (ascript) after onload or onerror because the script execution continues, we can achieve a similar effect by conditionally loading the success or alternate scripts based on the loading outcome.

P.S. Loading the initial script (ascript) without parameters does not do anything; hence, you don’t need to bother with it. The response for the script will be zero (see below - 204 No Content).

% wget https://www.google-analytics.com/g/collect
https://www.google-analytics.com/g/collect
Resolving www.google-analytics.com (www.google-analytics.com)... 216.58.201.110
Connecting to www.google-analytics.com (www.google-analytics.com)|216.58.201.110|:443... connected.
HTTP request sent, awaiting response... 204 No Content
(0.00 B/s) - ‘collect’ saved [0]

In Practice

Shortly after implementation, I didn’t need to wait long to see users from other cities visiting my site, like Leeds in the United Kingdom (which is my visit).

Google Analytics map showing users originates from other locations in Europe

By inspecting the source code, I can see that success.js is loaded when I am browsing through the browser without any blocking extensions, and alternate.js when I am using ad blockers.

This small change should improve the reliability of location tracking through Google Analytics.

After just 24 hours, I noticed around 70% of traffic, on various sites, to be reported from a much more accurate location.

Comments
Categories