Server-Side Analytics with Jamstack Sites
By: Vonage Dev
Tags: Nuxtjs, Analytics, Netlify, Jamstack

Jamstack sites don’t have a backend. That makes their ability to gather analytics particularly vulnerable to blockers. Let’s fix that problem.

This example includes a Netlify Function that will send our events off to Google Analytics, and a Netlify Redirect rule.

The Problem

Trackers and tracking pixels are HTML code designed to capture user behaviour or visits when they visit a website or open an email. It is useful for tracking usage of your website, and sometimes conversions.

The problem is, that some trackers are slow and often invasive. Ad-blockers were first dreamt up to stop ads and tracking pixels slowing down webpage performance, or to improve a user’s experience, but have subsequently been expanded to improve privacy for users.

A side-effect was, that a lot of site owners lost visibility of what worked and didn’t work on their sites. Physical tracking characteristics can still be used to track certain metrics, e.g. adding an article’s identifier on a sign-up link to see where the sign-up originated.

This still doesn’t help us accurately determine if our content is being viewed, a key requirement to determine conversion.

The Solution

Server-side analytics has become a popular way to track user activity. It doesn’t have the scope of traditional analytics (it can’t easily track on-page interactions), but it can capture important details, like unique page views.

Hosting platforms such as Netlify, or Edge providers like Cloudflare and Fastly, offer Server-side analytics as part of their solutions. But, when using a provider for analytics, you’re often restricted in how you can warehouse that information, limiting internal reporting.

For that reason, some like to roll their own server-side analytics. For this, Google has some quick starts for some languages, and for others there are packages like universal-analytics .

Here, we’ll roll our own using universal-analytics and a Netlify Function.

Netlify Function

Netlify Functions are basically AWS Lambda functions, without the AWS. The AWS developer experience leaves A LOT to be desired, and Netlify have turned user experience into a business model. Netlify Functions are no exception, allowing folks to write JavaScript or Go to a configured directory, and publish it in a few steps. The endpoint is derived by the file or folder name, and it can use the dependencies from the parent application, or be responsible for its own.

A super simple function might look like this:

Once deployed, you would be able to access it at a URL like this one: https://your-app.netlify.app/.netlify/functions/hello-world

But you can also continue to do things after you send a response back, like this:

Now, we could use this functionality to send off our analytics to Google.

Note: If you’re adding dependencies to a function, you’ll need to add the @netlify/plugin-functions-install-core plugin to your netlify.toml configuration. This plugin will ensure all the function's dependencies are installed when the function is deployed.

We need to install universal-analytics first, so make sure you're in your function's directory before you run the following command.

Ensure that you have a Google Analytics ID, and add that to your Netlify Environment Variables.

Now, we can use it in our function.

Now, from your browser, you can send off data from the URL straight to Google: https://your-app.netlify.app/.netlify/functions/hello-world?dp=/my-custom-page

Data you can send off includes-but isn’t limited to-these parameters:

Here is a full list of acceptable parameters.

Add the “Image”

Calling this script alone, with something like a router middleware or AJAX request, might be enough in a lot of instances for decent reporting, but it could still be recognised as an XHR request by a browser or browser ad-blocker, and blocked.

A (typically over-engineered) solution that I decided to use was similar to a tracking pixel method. But, because we return a visible structural image, ad-blockers have completely ignored it so-far.

We’re going to return an SVG image from the Netlify Function and place it on a page using an image tag.

Let’s use this image.

The source for this image can be found here:

Now, to return the image from our function:

Add it to your site using the URL we used before:

With any luck, it’ll look like this:

Redirect Rule

So, the most devious inventive part of my evil plan idea might be this next bit. I was slightly paranoid that an ad-blocker might sense a non-image URL with query string parameters as little suspect as an image source, and block it anyway.

Enter Netlify Redirects.

Using the netlify.toml in the root of your project, you can proxy one path with another.

Now, you can use an image path to include your smiley face.

You can encode the query string however you like, just remember to decode it inside the function.

Conclusion

Analytics is a superpower for marketing and content creators. It allows us to better serve the community, by tuning our goals based on the data we can collect.

There are often privacy and speed concerns around trackers. But as long as you’re acting in good faith, as I believe we are, analytics benefits viewers as much as anyone else.

This is a nice little way to achieve server-side analytics (which blockers can’t block), when you don’t have a server-side at your disposal.