Skip to content
    Back to Tips & Tricks
    Practical Setup13

    Practical Guide: Setting Up Server-Side GTM with GitHub CI/CD

    Written by Viktor KvantSenior Web AnalystNovember 27, 20252 min read

    Step-by-step: version-control your sGTM infrastructure with GitHub, Cloud Build, and Cloud Run.

    Here's the step-by-step setup that most guides skip. First, create a GCP project and enable the Cloud Run, Cloud Build, and Artifact Registry APIs. Create a GitHub repository with this structure: Dockerfile (FROM gcr.io/cloud-tagging-10302018/gtm-cloud-image:stable), cloudbuild.yaml, and a terraform/ directory.

    The image needs only one piece of configuration: the CONTAINER_CONFIG environment variable, which holds the container config string from your GTM server container (Admin → Container Settings at tagmanager.google.com) — not just the GTM-XXXXXX ID. Set it with ENV in the Dockerfile or, better, as an environment variable at deploy time. Set up a Cloud Build trigger on your main branch.

    The cloudbuild.yaml should: (1) build the Docker image, (2) push it to Artifact Registry, (3) deploy to Cloud Run with --min-instances=1 (cold starts lose events), --max-instances=5, and --allow-unauthenticated. Also deploy a second, single-instance service from the same image with RUN_AS_PREVIEW_SERVER=true, and set PREVIEW_SERVER_URL on the main service to its URL — otherwise GTM preview mode won't work.

    For DNS, note that a Cloud Run service has no fixed IP address to point an A record at. Either use Cloud Run domain mapping, which tells you which DNS records to create for collect.yourdomain.com, or, for production, put a global external Application Load Balancer with a static IP in front of the service and point an A record at that IP. In your web GTM container, set the server_container_url parameter on the Google tag (transport_url on the older GA4 Configuration tag) to https://collect.yourdomain.com.

    Test by checking the Network tab — requests should go to your subdomain, not google-analytics.com. Verify that the service is healthy with curl -I https://collect.yourdomain.com/healthz.

    Commit everything to GitHub. Now your tracking infrastructure is version-controlled, reviewable, and rollback-ready. When the infrastructure needs to change — image version, scaling, environment variables — it goes through a pull request, just like application code. Tags and triggers themselves still live in the GTM workspace unless you also export the container to the repository via the GTM API.

    For the CI/CD test stage, a custom test harness can send synthetic events to the staging endpoint to validate downstream API calls (such as GA4, Facebook CAPI, or Google Ads) without affecting production data. This catches configuration errors early.

    Author

    Viktor Kvant

    Senior Web Analyst specialising in data ownership, advanced tracking implementations, and translating data into strategic business value.

    Connect on LinkedIn