The secret to productivity? Block internet distractions. Learn more about Cold Turkey Pro »

How to collect Google Analytics data with a lightweight, cacheable alternative?

Situation: You track visitors with Google Analytics but noticed speed tests like Google PageSpeed, WebPageTest, and Pingdom Speedtest all complain about the 2-hour cacheability of Google’s analytics.js file. You’d like to follow that best practice and wonder if there’s an alternative that can be cached for a long time.

Solution: replace Google Analytics code with ga-lite

ga-lite implements the official Google Analytics API but is a small, cacheable alternative to Google Analytics’ own script. It’s simple to add ga-lite to your Hugo website: reference ga-lite.min.js instead of analytics.js and then replace any ga() function call with galite().

Step 1. An easy way to include ga-lite’s JavaScript is from jsDelivr. (See GitHub for how to download and host ga-lite on your own server.)

To add ga-lite, open the theme file where you want to include it. For most themes, that file is likely named header.html or footer.html and located in your /themes/[theme-name]/layouts/partials/ folder. In that file place the following code (replace the example Google Analytics ID with your own):

<script>
    (function(e,t,n,i,s,a,c){e[n]=e[n]||function(){(e[n].q=e[n].q||[]).push(arguments)}
    ;a=t.createElement(i);c=t.getElementsByTagName(i)[0];a.async=true;a.src=s
    ;c.parentNode.insertBefore(a,c)
    })(window,document,"galite","script","https://cdn.jsdelivr.net/npm/ga-lite@2.0.1/dist/ga-lite.min.js");

    galite('create', 'UA-XXXXXXXX-X', 'auto');
    galite('send', 'pageview');
</script>

Step 2. Now replace all ga() function calls in your theme with galite(). That means when you for instance track Google Analytics events, you’ll now need to send those to Google with galite() instead of ga().

Discussion: collect Google Analytics data with a cacheable alternative

Google Analytics is a popular way to collect traffic data. Rightly so, because this free tool has plenty of features. But one thing missing from the official Google Analytics client is a long cache period: the default analytics.js file is only cached by browsers for 2 hours.

With that short caching period the Google Analytics team can quickly update and correct their code. But most website speed tools lower the pagespeed score because of that 2-hour caching period, and suggest to use a much longer caching period for static assets.

The ga-lite script makes it possible to get that longer caching period, while still implementing the official Google Analytics API. The jsDelivr file we used in the solution above is cacheable for 1 year, for instance. But ga-lite has more benefits. The ga-lite.min.js file is smaller than analytics.js and weighs just 3.4 KB when compressed. We can also install ga-lite from NPM and host it on our own server. Furthermore, ga-lite doesn’t track browsers that send a “Do not track” flag, which is something Google Analytics doesn’t listen to (GitHub, 2018).

ga-lite implements most, but not all, features that Google Analytics (analytics.js) offers (GitHub, 2018). Implemented features are page and event tracking, social interactions, user timings, and exception tracking. Currently missing are page load times and custom dimensions. See the open GitHub issues for which features are currently not implemented.

To use ga-lite we not only replace analytics.js with the ga-lite script. We also need to replace all ga() function calls on our website with galite() (GitHub, 2018). Failure to do so will give JavaScript errors due to referencing a non-existing function (ga()).

Implement ga-lite with asynchronous JavaScript code

The recipe solution above uses synchronous JavaScript code to insert the ga-lite script. But the issue with JavaScript is that it temporarily blocks the browser from rendering the webpage. That is, when a browser reads our HTML page and comes across JavaScript code, it pauses and executes the JavaScript code. After that it continues with rendering the rest of the document (Grigorik, 2018).

When we want our pages to render as quickly as possible, that situation isn’t ideal. Worse, when the JavaScript is an external file (like the jsDelivr file used above) the browser also needs to fetch that file, which also gives an additional DNS lookup and SSL negotiations. Luckily, we can mark a JavaScript file as async.

Doing that instructs the browser to download the JavaScript in the background and continue with rendering the page. Then when the file becomes available, the browser pauses page rendering to execute it (Grigorik, 2018). This way we don’t have to block page rendering till the browser connects to the remote host and downloads the file. (In other words, asynchronous JavaScript behaves like in-line code: it’s still rendering blocking, but we don’t have the browser wait till the external resource is available.)

To get that small performance benefit and use ga-lite asynchronously, place the following code in your theme file. (Which likely is footer.html or header.html file from the /themes/[theme-name]/layouts/partials folder.)

<script>
    window.galite=window.galite||function(){(galite.q=galite.q||[]).push(arguments)};
    galite('create', 'UA-XXXXXXXX-X', 'auto');
    galite('send', 'pageview');
</script>

<script async src="https://cdn.jsdelivr.net/npm/ga-lite@2.0.1/dist/ga-lite.min.js"></script>

Note that with this approach you’ll still need to replace all ga() function calls with galite() – it’s just the way of downloading the file that’s different.

Learn more

References

GitHub (2018, January 11). ga-lite/README.md. Retrieved on February 8, 2018, from https://github.com/jehna/ga-lite/blob/master/README.md

Grigorik, I. (2018, January 3). Adding Interactivity with JavaScript. Retrieved on February 12, 2018, from https://developers.google.com/web/fundamentals/performance/critical-rendering-path/adding-interactivity-with-javascript