Learnings from a year with Google Tag Manager Server Side

Learnings from a year with Google Tag Manager Server Side

Over the last few years, I’ve written several times about Google Tag Manager, especially when I was at The Next Web as we had an extensive integration. Something we ran into over time was the lack of being able to send events that needed validation or were triggered from the front-end. At the time, I asked the Product team of GTM what their thoughts were about sending server-side events. It wasn’t a primary use case for a publisher, but for many others, it is. For example, you often want to validate data or check if an interaction has happened/passed a milestone (like verifying payment) before you can accept a purchase. In the web version (front-end) of Google Tag Manager, you either had to fire an event by hitting the purchase button or wait until the thank-you page was loaded. But sometimes, that doesn’t guarantee it, and the final confirmation takes place behind the scenes. This is where Google Tag Manager for the server-side will come in.

An intro to Server Side Google Tag Manager

Google Tag Manager server-side was released originally in beta in 2020, and since the early days, we’ve been in their program with RVshare. Server-Side (SS) leverages Google Cloud Platform (GCP) to host a GTM container for you that you then point via your DNS records to it. By doing this, you’re able to assure that any ad/privacy blockers are not blocking the default Google scripts hosted on google.com. But mainly, it will provide you with the ability to receive back-end requests. In our case, this means that we have more flexibility to validate purchases or user signups before we fire a successful event to SS GTM.

Learnings

New roads can be bumpy as you’re still trying to learn what should work and what new beta features might still not be ready for production. That’s why we gathered some learnings on our integrations that I wanted to share.

Server-Side Validation

Although we’ll likely all have to move to a world in which we run server-side containers there are still plenty of reasons why smaller sites don’t have to migrate yet and can avoid the overhead. But if you’re dealing with use cases that require validation, I would urge you to take a look.

Examples are:

  • You want to verify someone’s identification before registering a signup.
  • You want to verify payment information or inventory status before registering a purchase.

Those examples will require validation but will likely already send the user to a thank-you page without knowing if this is actually all approved or not. As a lot of this depends on business logic you want to ensure that your marketing or product analytics tracking in Google Analytics 4 supports this as in my opinion as you want to align your reporting with the business metrics that the rest of the organization cares about.

How to think about this for your setup? What are some of the examples or business rules that are in place for your organization that your current analytics integration might not line up with perfectly? Chances are that you find an opportunity to improve this by using server-side validation and only sending events once it successfully passes.

Managing Server Capacity

GCP and SS GTM on setup will create 3 (small) servers via Kubernetes by default. When you start receiving many events and send them in parallel to many different clients, you’ll start to notice the load on your servers increase. We didn’t realize that autoscale only goes up to 6? by default. Since then, we improved this, but it caused us to lack partial data for a few days after a significant release. So check how many servers your servers can auto-scale to avoid any issues. Realistically, you can quickly push that number up to 20+ without incurring any additional costs as they’re only used with a high CPU event, and they’re automatically being downsized after traffic slows down.

How to do this yourself?

As the procedure for this has changed since we ran the updates for this about six months ago, I recommend reading the instructions for reconfiguring the servers that App Engine creates as it will help you find the right command-line instructions to execute.

Monitoring Request & Server Errors: Slack & Email Alerts

Look at the trend line in the report. Notice the cliff? You never had to deal with this issue previously, as Google managed GTM web containers. But with SS GTM, things can go wrong, quickly and you’ll need alerting to tell you about it. In this case, an error came up on the side of Google Analytics with ec.js, which wouldn’t load for enhanced commerce, causing 5XX errors on the managed servers. That eventually led to conversions not being recorded, as that’s a mission-critical piece of our infrastructure. You can guess the implications.

How to do this yourself?

  1. Go to your Google Cloud Platform project that is associated with your GTM account, your project ID will look something like: ‘gtm-xxx’.
  2. Use the search bar at the top to find the ‘Logging’ product, you can also go there via App Engine which powers the servers for this.
  3. You can find all the requests that are being sent to this server and debug what could be going on.

Saving request & error logs in Google Cloud Storage

Server-side events can come in all shapes and sizes, POST/GET requests, and can contain many things that you care about. In our case, we sent a server-side event on purchase with a full POST body with data. But… this body isn’t shown directly in the logging feature that we just talked about, that we just discovered as only the request URI is shown: GET /request-path. When you’re sending an event to: /request-path?event_name=foo-bar with a body, this quickly can cause issues as you don’t have a place to debug the body. We opted for sending this full request as a JSON file to Google Cloud Storage so that we can evaluate the full request. As this technology is still in development I can’t share much more about it this time.

Special thanks to the team of Marketlytics and Data to Value (Rick Dronkers/Peter Šutarik), as they’re our marketing analytics partners at RVshare.


Moving away from onclick events, data attributes it is

Onclick attributes are amazing to easily sent some data to the dataLayer. It will make sure that on every click the data is being sent, let’s for example look at this:

<a href=”http://example.com” onclick=”dataLayer.push({‘eventCategory’:’Click’, ‘eventAction’:’This Link’, ’eventLabel’:’Anchor Text’});”>Link</a>

Looks valid right? It is and it will work for you. But the problem is that with external links the dataLayer push won’t hit the browser + Google Tag Manager before the browser moves on to the external link (not taken into account links that open in a new tab/window). Which means that you’ll lose the onclick event in Google Tag Manager and won’t be able to record it.

But there is a great alternative, which we switched to for The Next Web when we found out this was happening. Data attributes can be very useful instead. If you’d use them like this:

<a href=”http://example.com” data-eventCategory:’Click’, data-eventAction:’This Link’, data-eventLabel:’Anchor Text’”>Link</a>

Why this works? The link attributes on click will always be sent automatically to Google Tag Manager. So making sure that the data attributes are part of the link and not in a separate dataLayer.push will improve it.

How about React/Angular? With these platforms there is obviously never an actual refresh of the page happening and most likely you can still send a dataLayer push when you’re updating the state of the application. That’s why in most cases you won’t have to go with the technique described in this blog post. Lucky you!

Google Tag Manager

Next step is to create a variable in Google Tag Manager for all three attributes:

Make sure to set the default value to undefined. In this case Google Tag Manager won’t take any actions in the next step if there is no data, which will be defining the Trigger. Repeat this two more times for the Event Action and Event Label variables that we need to use in our Tag.

This trigger will check all incoming links, with a data-event-category attribute that doesn’t equal undefined and that has any values. In the next step for your Tag you can use all three variables that you’ve defined before.

You’re all set! You can now use data-attributes for your links to make sure that you won’t lose any data when the browser isn’t ready to receive dataLayer pushes and you just made your tracking a bit more efficient!