Deploying Server-Side Google Tag Manager on Cloud Run
Moving marketing event processing out of the browser and into the backend
Server-Side Google Tag Manager (server-side GTM) is a new product from Google Marketing Platform. It moves marketing event processing off the user’s browser to a backend server that you control.
The standard deployment method for server-side GTM consists of automatically setting up an App Engine Flexible application. App Engine is a fully-managed platform-as-a-service deployment solution from Google Cloud Platform (GCP). Users can provision a server by filling out a form in Google Tag Manager UI when creating a new container.
At Square, we process over 4.5 billion tracking events per month. How we choose to scale server-side GTM and manage these servers in our infrastructure was a critical decision. There are restrictions on our GCP projects that prevent us from using App Engine Flexible. We explored a few different container scaling platforms but ultimately chose GCP Cloud Run.
In this post, we give a walkthrough of the architecture, discuss our automated deployment process, and share our thought process in choosing Cloud Run. Lastly, we provide a guide on how to set up server-side GTM on Cloud Run for your team.
Server-Side GTM Cloud Run Architecture
GCP Cloud Run came up as an alternative due to its similarity to App Engine. Both are managed platforms for scaling applications. All that Cloud Run requires is a Docker container image.
Mark Edmondson did an excellent write up on his exploration of deploying server-side GTM on Cloud Run in August 2020. Cloud Run is easy to set up but achieves this by abstracting away many configuration details. At the time, the server-side GTM Docker container required precise routing for two distinct types of requests which is not possible on Cloud Run.
Since then, there have been key updates to the server-side GTM container. Now, developers need to set up two types of containers, Tagging and Preview. This adds complexity to the deployment process, but gives developers better control over their server-side environment.
With the new configuration, the Tagging container handles all requests. It proxies requests that include a preview header to the Preview container which is responsible for serving the preview UI.
Each of the two types of containers are grouped into Cloud Run services which automatically scale based on request load. The Preview service does not scale beyond one instance. Both types of containers use the same image. They only behave differently based on environment variables defined at the time of provisioning.
Automating Deployment with Terraform
We used the Cloud Run UI in our initial discovery, but found this process too manual. At Square, we have server-side GTM deployed in three environments: development, staging, and production. A key benefit of using Cloud Run is the ease in automating deployment and configuration of server-side GTM.
Square utilizes Terraform as our infrastructure-as-code tool. This allows us to apply changes across all environments with a single configuration, minimize human error, and utilize the benefits of git for version tracking. It’s easy to define settings like container configs, request timeouts, instance type, and instance memory.
Where we do need to make environment specific changes, we add simple logic like the following:
memory = (var.service_name == "tagging" && var.environment == "production") ? "512Mi" : "256Mi"
The Terraform code above only sets the memory allocated to 512 MiB in our production environment Tagging service. Our other services will only be handling a fraction of the traffic and don’t need as many compute resources.
A Perfect Fit
Square has customized cloud environments which can prevent out-of-the-box managed solutions like App Engine Flexible from working. On the opposite-end, highly customizable solutions like Kubernetes in our data centers or Google Kubernetes Engine come with more options than necessary and take significant engineering time to set up and manage.
Cloud Run sits in-between. Like the App Engine process, set up through the UI remains simple; the ability to deploy and update with Terraform fits perfectly into Square’s engineering processes; and this adds the option to migrate to Cloud Run for Anthos, adding the operational flexibility of Kubernetes.
As server-side event processing solutions become commonplace in the industry—especially with the move toward data privacy—mid-to-large sized companies will need to customize their deployment to fit in with their marketing and engineering stacks. We expect managed solutions like Cloud Run to be a perfect middle-ground that will meet the needs of many marketing engineering teams. This will allow companies to scale and configure their servers alongside the growth of their business.
How To Deploy through the Google Cloud Platform UI
To try server-side GTM on Cloud Run for yourself, we recommend first exploring deployment with the UI. Take the following steps.
Create a Tagging container
Create a new server container in the Google Tag Manager UI. Once you have done so, select Manually provision tagging server and keep the Container Config handy.
If you already have a server container deployed on App Engine Flexible, you can use the same container config.
Enable Cloud Run
Then navigate to GCP Cloud Run. Enable the Cloud Run API if you haven’t already. Click on CREATE SERVICE in the Cloud Run top navigation bar.
Create the Preview Service
1. Service settings
- Deployment platform: Cloud Run (fully managed)
- Service Name:
preview
2. Configure the service's first revision
Select Deploy one revision from an existing container image and enter this Docker image published by Google for the container image URL
Advanced Settings
Click on Advanced Settings to expand this section
Under the Container Tab set *Autoscaling - Maximum number of instances: 1
Under the Variables Tab add two environment variables
CONTAINER_CONFIG
: your container config from the tag manager UIRUN_AS_PREVIEW_SERVER
:true
Note that the second environment variable, RUN_AS_PREVIEW_SERVER
is what designates this service as preview.
3. Configure how this service is triggered
- Ingress: Allow All Traffic
- Authentication: Allow unauthenticated invocations
The Preview service needs to accept requests from the Tagging service which will be unauthenticated.
Click create. You will be redirected to the Preview service you just created. From there, you should copy the URL which is randomly generated. You can also add a custom domain and copy that value instead.
You can test that your Cloud Run service is working by navigation to your URL + /healthy
. This should return ok
.
Create the Tagging Service
Navigate back to Cloud Run. Click on CREATE SERVICE in the Cloud Run top navigation bar.
1. Service settings
- Deployment platform: Cloud Run (fully managed)
- Service Name:
tagging
2. Configure the service's first revision
Select Deploy one revision from an existing container image and enter this Docker image published by Google for the container image URL. Note that this is the same image you used to create the preview service.
Advanced Settings
Click on Advanced Settings to expand this section
Under the Container tab set Memory allocated to 512 MiB
The memory setting of 512 MiB is to mimic the App Engine Instance settings. Edit the autoscaling as per your preference. You can set a minimum of one instance to prevent cold-start latencies if your service scales down to zero. Neither memory or autoscaling are hard requirements for the tagging server and it’s for you to decide how you want to balance performance versus minimizing cloud costs.
Under the Variables tab
CONTAINER_CONFIG
: your container config from the tag manager UI (this is the same as the Preview service)PREVIEW_SERVER_URL
:the URL of the Preview service you just provisioned
Note that the second environment variable, PREVIEW_SERVER_URL
is what designates this service as tagging.
3. Configure how this service is triggered
- Ingress: Allow All Traffic
- Authentication: Allow unauthenticated invocations
Measurement data sent from the client-side of your website will make requests directly to the Tagging service.
Click create. You will be redirected to the Tagging service you just created. From there, you should copy the URL which is randomly generated. You can also add a custom domain and copy that value instead.
You can test that your Cloud Run service is working by navigation to your URL + /healthy
. This should return ok
.
Update Tagging server URL
Return to your tag manager UI. Under container settings, add your Tagging service URL. Return to the tag manager workspace and click on the Preview button. If the preview UI opens up, your deployment was a success!