Google Tag Manager has a very nifty programmatic API that lets you do almost anything that’s also possible within the GTM UI. I’ve used the API a lot, most notably for my GTM Tools, which might be getting a new release soon, too!

The API was recently updated to its second release version (V2), and in this article I want to go over the additions, removals, and changes that the new version introduced.

First of all, V1 of the API is still fully functional, so you don’t have to migrate until you’re ready. That being said, the new version brings about a number of changes I’m sure you’ll find helpful when working with the API.


The Simmer Newsletter

Subscribe to the Simmer newsletter to get the latest news and content from Simo Ahava into your email inbox!

Biggest changes

The most significant change, in my opinion, is the introduction of workspace as the central focus in almost all interactions with anything on the container level. It’s not just that there’s a new namespace for workspaces in the API, but that you must always reference a workspace when interacting with container assets. This is going to be the biggest hurdle in a migration, I believe. Anything that happens in a workspace (pretty much all UI interactions with a single container draft) must now be accompanied by the workspace ID of the workspace you want to modify. This, in turn, means a round trip via the workspaces API to get the IDs you need.

Another very visible change is the separation of Built-in Variables into its own namespace. Luckily there’s also a simple batching shorthand for enabling / deleting multiple Built-in Variables in a single request.

On a technical level, when using client libraries you now provide the path to the asset as a single parameter (basically path or parent) instead of using multiple named parameters. The new resource representations include the path key, which you can then use to easily chain API commands together.

Finally, and I love this, there’s support for adding notes to pretty much any resource available via the API. Even though the UI doesn’t yet support the notes field as widely, you can now add descriptive text to all assets via the API. Very useful for documenting the container.

(UPDATE: a short while after writing this article, GTM released support for notes in the UI too, yay!)

Detailed changes

What follows is a walkthrough of all the namespaces in the new version of the API, with information on what changed from V1.

1. Accounts

Resource changes: The Accounts resource has the following new fields:

  • path: path of the Account, e.g. accounts/12345
  • tagManagerUrl: direct URL to your account in the GTM API

Method changes: There are no significant changes in Accounts methods.

2. Built-in Variables

This is a completely new namespace in the API. Instead of passing a list of Built-in Variables in the container resource itself, you now need to explicitly enable Built-in Variables in the workspace of your choice. You can read the full description of this new feature here.

Note that if you want to enable multiple Built-in Variables in a single request (strongly recommended), you can use a shorthand batch format to do so.

        parent='accounts/%s/containers/%s/workspaces/%s' % (accountId, containerId, workspaceId),
        type=['clickClasses', 'clickElement', 'clickId', 'clickUrl', 'clickText', 'clickTarget'] )

3. Containers

Resource changes: The Containers namespace hasn’t changed that much. The new fields are the same as with Accounts: path and tagManagerUrl. Fields that were removed from V2 are the redundant timeZoneCountryId and timeZoneId. The enabledBuiltInVariable field has been replaced by the Built-in Variables namespace introduced above.

Method changes: There are no significant changes to the Containers methods.

4. Environments

Resource changes: The main changes to the Environments resource are the following:

  • path: relative path in the API to the given environment

  • authorizationTimestamp: supports both nanos and seconds as values

  • workspaceId: link to preview a given workspace in the environment

  • tagManagerUrl: link to the Environments page in the container

Method changes: The most significant change is that the old environments.reauthorize_environments namespace has been removed in favor of simply adding a reauthorize() method to the main Environments API.

5. Folders

Resource changes: The big changes to the Folders resource are:

  • path: relative API path to the folder

  • workspaceId: ID of the workspace from which the folder was fetched

  • tagManagerUrl: link to the folder in the GTM UI

  • notes: notes about the folder

Method changes: The main changes to the methods are that both folders.entities and folders.move_folders have been replaced with their own dedicated API methods in entities() and move_entities_to_folders(), respectively.

There’s also a new method, revert(), which lets you revert changes to a folder in the given workspace.

6. Tags

Resource changes: The only changes are the inclusion of path, workspaceId and tagManagerUrl. Otherwise the resource representation has remained relatively unchanged.

Method changes: The only big change is the introduction of the revert() method, which lets you cancel any changes to the tag in the given workspace.

7. Triggers

Triggers was affected in exactly the same way as Tags. The changes are identical, with the exception of notes now introduced as a writable field for Triggers, too.

8. User Permissions

(Note, this used to be called just Permissions in the previous API version documentation.) Resource changes: The main changes to User Permissions are:

  • path: relative API path to the permission entity, includes the permissionId

  • accountAccess.permission: now a string rather than a list/array

  • containerAccess[].permission: now a string rather than a list/array

Method changes: No significant changes to methods.

8. Variables

Changes to Variables are pretty much on par with what’s done to Tags, so check the relevant section above for more details.

9. Version Headers

The Version Headers API is a new addition to the GTM API. Basically, it’s a shorthand for accessing versions of any given container. Unlike the Versions API itself, Version Headers only returns, surprise surprise, headers. This keeps the API calls really lean, and lets you quickly get the necessary information, such as the version ID.

You can check the documentation for more details on the resource representation.

The API has two methods.

  • latest() returns the version header of the Latest Container Version. The Latest version is the most recently created version in Google Tag Manager, and is very relevant to Workspaces, since Workspaces need to be synchronized with the Latest container version before they can be published or turned into versions themselves.

  • list() returns a list of all container versions in any given container.

10. Versions

(Note, this used to be called Container Versions in the previous API version documentation.) Resource changes: Here are the changes to Versions in the GTM API:

  • path: relative API path to the container version

  • description: used to be called notes in the previous API version

  • builtInVariable: list of Built-in Variables enabled in the version

  • tagManagerUrl: link to the container version in the GTM UI

Note that the macro and rule parameters have been deprecated in the new API version.

Method changes: Here are the main changes to Versions methods:

  • create(): deprecated - container version creation is done via Workspaces

  • list(): deprecated - version list is now done via Version Headers

  • live(): retrieves the container version that is currently live in the container

  • set_latest(): sets the given version as the Latest version in the container - replaces restore() in the previous API version

11. Workspaces

The Workspaces API was introduced in V2 of the GTM API. You will definitely want to follow this link and familiarize yourself with the new API. Understanding how workspaces function in the container is integral to understanding how the GTM API works.

  • create_version() creates a version out of a workspace but only if the version passes all GTM’s syntax and validation checks.

  • getStatus() returns all the conflicting and/or modified entities in the workspace. This is useful if you want to check if the workspace is ready to be turned into a version.

  • resolve_conflict() lets you resolve conflicts in favor of the workspace or the latest version.

  • sync() lets you synchronize the workspace with the latest container version - a necessary step to take before creating the version.

Workspaces are fundamental to many interactions with the API. Basically, when you work with tags, triggers, variables, folders, and built-in variables, you always need to provide the workspace ID with which you are interacting. There’s no single “Container draft” anymore. There’s always a workspace you’re working in.

In addition to having to update your methods, this also means that you need to rethink some of the API flows you have been using thus far. For example, instead of just creating new items in a container, you now need to specify the workspace you want to work with. This means you might first need to list() the available workspaces to get the ID you are looking for. Or perhaps you want to create() a new workspace so that you don’t mess with other people’s unfinished work.


The new API certainly has a lot of stuff to wrap your head around. The introduction of workspaces, for one, is certain to make migration a bit of a headache. However, it would be equally awkward to work with an API that isn’t in sync with the feature set of the UI it is managing. For this reason, I think it makes a lot of sense to upgrade to the latest API version as soon as possible.

Most of the stuff is easy to figure out, such as how to move from accountId= and containerId= to path=accounts/accountId/containers/containerId. In fact, I think changes like this make it easier to work with programming languages that make use of string interpolation (Python, for example). There are some conventions that might take time to understand routinely, such as how to use versionheaders.list instead of versions.list.

One thing that’s a constant feature request from me is that Google would update their error messages. It’s very difficult to understand what’s wrong when all you see in the logs is “400 Bad Request” or “500 Backend Error”.

What do you think about the new API? Have you written tools for the GTM API you want to share? Please do!