How to use Google Analytics with Sapper

Adding Google Analytics to any website should be pretty straight forward once you have the code snippet that Google provides you with. But when you want to dynamically populate the actual tracking id it gets a bit harder, especially when using a Universal Javascript framework.

For this project I decided to use Sapper which is an Universal JavaScript framework built on top of Svelte. At the time of writing the version of Sapper is 0.12. Sapper has some really nice features out of the box, it has hot module reloading, directory based routing, code splitting and offline support to name a few.

The new Google Analytics (GA) code that Google uses is a bit different to the old one, now they have introduced Google Tag Manager and all tracking is done though that script. The script GA provides look a little like the below:

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

  gtag('config', 'TRACKING_ID');
</script>

This is useful when you want to add script into your page the traditional way, but when its a Universal Javascript application you will need a bit more to get it all dynamic.

My first thought was to just add it to app/template.html, this would work alright, but it would mean that the TRACKING_ID would be hardcoded and now I would have an environment issue where every environment would be using the same TRACKING_ID and If I wanted to open source the project, I would have to leave my hardcoded TRACKING_ID in the codebase.

So I went on to do what I usually do when I have an problem I can find no solution to, I went on the Svelte gitter chat and asked. And low and behold, the creator of Sapper himself Rich Harris replied with this code snippet below and suggested that I add it to app/client.js.

export const googleAnalytics = (gaID) => {
    window.dataLayer = window.dataLayer || []
    function gtag() { dataLayer.push(arguments) }
    gtag('js', new Date())

    gtag('config', gaID)

    const script = document.createElement('script')
    script.src = `https://www.googletagmanager.com/gtag/js?id=${gaID}`
    document.body.appendChild(script)
}

I created a separate file in app called ga.js and then import that into app/client.js. However this wasn’t the only step that needed to be done since I want to load the TRACKING_ID dynamically, this script would only allow that to happen. Below is what my app/client.js looked like after making this change.

import { init } from 'sapper/runtime.js';
import { routes } from './manifest/client.js';
import App from './App.html';
import { googleAnalytics } from './google-analytics.js';

init({
    target: document.querySelector('#sapper'),
    routes,
    App
});

// Here is my Google Analytics script that only get set if I have a TRACKING_ID environment variable set at build time.
if (process.env.TRACKING_ID) googleAnalytics(process.env.TRACKING_ID);

In order to set this environment variable on the client side, we need to do this in webpack (the build system). We now open webpack/client.config.js and look for the plugins section and in here we should find a webpack.DefinePlugin, within this plugin is where we can add our environment variable.

Here is the change I made in my webpack/client.config.js:

new webpack.DefinePlugin({
    'process.browser': true,
    'process.env.NODE_ENV': JSON.stringify(mode),
    'process.env.TRACKING_ID': JSON.stringify(process.env.TRACKING_ID || '')
}),

I hope this has helped you in setting up Google Analytics with Sapper. And make sure you come and join us in the Svelte gitter channel.