Git Version Control for Google Tag Manager: Using GTM CLI in CI/CD Pipelines

Learn how to automate GTM container exports with GTM CLI and GitHub Actions for full audit trails and compliance.

Justus

Justus

owntag Founder

published February 9, 2026

If you work in an enterprise environment with strict compliance requirements, you might have come across this challenge - at least I have a couple times working with large client companies:

Your organization needs to document every piece of code running on your website—including what’s inside Google Tag Manager.
Auditors want to know exactly what tags were live on a specific date, and “just check the GTM version history” doesn’t always cut it, e. g. if Git has been designated the system of record or – as is quite typical at least in German companies – there’s a general lack of trust for everything Google-related.

Here’s one of the many possible approaches to a solution:
Automated exports of your GTM container configuration, committed to your Git repository alongside your application code.
Of course, whoever’s working in GTM can make changes and publish new versions independently from the website’s dev team, but that’s a topic for another blog post.

The Compliance Challenge

Many organizations—especially in finance, healthcare, and the public sector—have regulatory requirements that mandate:

  1. Full audit trails of all code deployed to production
  2. The ability to reconstruct exactly what was running at any point in time
  3. Change documentation that ties back to approval workflows
  4. Having all of the above fully automated

Google Tag Manager’s built-in version history is great, but in it exists in isolation.
It’s not part of your Git history, can’t be truly linked to pull requests or tickets besides mentioned them in version names, and isn’t included in your compliance reports. For organizations that need a single source of truth for everything running in production, this is a gap.

The Solution: GTM CLI + GitHub Actions

With GTM CLI, you can programmatically export your live GTM container configuration as JSON and integrate this into your existing CI/CD workflows. Every time your GTM container is published, a GitHub Action can automatically:

  1. Fetch the current live container configuration
  2. Commit it to your repository
  3. Create a traceable record in your Git history

Setting It Up

Prerequisites

  • A Google Cloud service account with read access to your GTM container
  • The service account key stored as a GitHub secret
  • GTM CLI installed in your CI environment

Step 1: Create a Service Account

In your Google Cloud Console, create a service account and download the JSON key file. Then, in Google Tag Manager, grant this service account “Read” access to your container under Admin → User Management. You can choose to do this on the account level or the container level, whatever feels more appropriate for your use case.

Step 2: Store the Credentials in GitHub

Add your service account JSON key as a repository secret named GTM_SERVICE_ACCOUNT_KEY.

You’ll also want to store your GTM Account ID and Container ID as secrets or variables:

  • GTM_ACCOUNT_ID
  • GTM_CONTAINER_ID

Step 3: Create the GitHub Action

Create .github/workflows/gtm-export.yml:

yaml
name: Export GTM Container

on:
  # Allow manual triggers from GitHub UI
  workflow_dispatch:
  # Run when pushing to or merging into main
  push:
    branches:
      - main

jobs:
  export-gtm:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      # Install GTM CLI - replace 1.5.6 with the latest version or the one you want to use
      - name: Install GTM CLI
        run: npm install -g @owntag/gtm-cli@1.5.6

      - name: Authenticate with GTM
        run: |
          echo '${{ secrets.GTM_SERVICE_ACCOUNT_KEY }}' > /tmp/sa-key.json
          gtm auth login --service-account /tmp/sa-key.json

      - name: Export live container version
        run: |
          gtm versions live \
            --account-id ${{ vars.GTM_ACCOUNT_ID }} \
            --container-id ${{ vars.GTM_CONTAINER_ID }} \
            --output json > gtm/container-live.json

      - name: Extract version metadata
        id: version
        run: |
          VERSION_ID=$(jq -r '.containerVersionId' gtm/container-live.json)
          VERSION_NAME=$(jq -r '.name' gtm/container-live.json)
          echo "version_id=$VERSION_ID" >> $GITHUB_OUTPUT
          echo "version_name=$VERSION_NAME" >> $GITHUB_OUTPUT

      - name: Commit changes
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add gtm/container-live.json

          # Only commit if there are changes
          if git diff --staged --quiet; then
            echo "No changes to GTM container"
          else
            git commit -m "Update GTM container export (v${{ steps.version.outputs.version_id }}): ${{ steps.version.outputs.version_name }}"
            git push
          fi

      - name: Cleanup credentials
        if: always()
        run: rm -f /tmp/sa-key.json

What This Does

Whenever you push to (or merge into) the main branch—or trigger it manually from the GitHub Actions UI—this workflow:

  1. Authenticates with Google Tag Manager using your service account
  2. Exports the current live container configuration as JSON
  3. Commits any changes to your repository with a meaningful commit message that includes the GTM version number and name

The result is a Git history that looks somewhat like this:

a]4f2e1d Update GTM container export (v27): Using Meta Pixel ID as constant
b]8c3a9f Update GTM container export (v26): Added scroll tracking triggers
c]1e7d4b Update GTM container export (v25): GDPR consent mode updates

Each commit corresponds to a GTM version publish, creating a clear audit trail.

Reviewing Changes with Git Diff

One of the most powerful aspects of this approach is the ability to review tag changes using standard Git tools. When someone publishes a new GTM version, you can see exactly what changed:

git diff HEAD~1 gtm/container-live.json

Not as nice as GTM’s Web UI, but what we’re doing here isn’t for day-to-day work. Or review changes in a pull request before merging. This brings the same code review practices you use for application code to your tag management.

Outlook

For organizations that need comprehensive audit trails, automated GTM exports can solve a real compliance gap.
However useful or necessary these exports might be in day-to-day work, its nice to be compliant without reinventing the wheel and spending a ton of dev effort on it.

GTM CLI makes this straightforward—what would be a complex custom integration becomes a few lines in a GitHub Action.

If you’re dealing with compliance requirements around tag management, give this approach a try.
Obviously this works for your GTM web containers as well as Server Side Google Tag Manager where arguably it’s even more useful because external auditors aren’t able to see the code you run from the outside.

Ready to go server-side?

Take control of your digital data collection with Server Side Tagging – easily and conveniently hosted with owntag.

App screenshot