Google Tag Manager
Access the Google Tag Manager API with managed OAuth authentication. Manage GTM accounts, containers, workspaces, tags, triggers, variables, environments, and container versions.
Quick Start
# List all GTM accounts
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://api.maton.ai/google-tag-manager/{native-api-path}
Maton proxies requests to tagmanager.googleapis.com and automatically injects your OAuth token.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Google Tag Manager OAuth connections at https://api.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=google-tag-manager&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'google-tag-manager'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2025-12-08T07:20:53.488460Z",
"last_updated_time": "2026-01-31T20:03:32.593153Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "google-tag-manager",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple Google Tag Manager connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
Security & Permissions
- Access is scoped to the GTM accounts and containers the connected Google account has permissions for.
- All write operations require explicit user approval. Before creating, updating, or deleting tags, triggers, variables, or publishing versions, confirm the target resource and intended effect with the user.
- Publishing a container version makes changes live. Always confirm with the user before publishing.
API Reference
Resource Path Pattern
GTM API v2 uses hierarchical paths:
accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/{resource}/{resourceId}
Accounts
List Accounts
GET /google-tag-manager/tagmanager/v2/accounts
Response:
{
"account": [
{
"path": "accounts/6353461358",
"accountId": "6353461358",
"name": "My Company",
"features": {
"supportUserPermissions": true,
"supportMultipleContainers": true
}
}
]
}
Get Account
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}
Containers
List Containers
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers
Response:
{
"container": [
{
"path": "accounts/6353461358/containers/251407136",
"accountId": "6353461358",
"containerId": "251407136",
"name": "example.com",
"publicId": "GTM-XXXXXXX",
"usageContext": ["web"],
"tagIds": ["GTM-XXXXXXX"],
"features": {
"supportTags": true,
"supportTriggers": true,
"supportVariables": true,
"supportVersions": true,
"supportEnvironments": true,
"supportWorkspaces": true,
"supportFolders": true,
"supportTemplates": true,
"supportBuiltInVariables": true,
"supportZones": true
}
}
]
}
Create Container
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers
Content-Type: application/json
{
"name": "New Container",
"usageContext": ["web"]
}
Valid usage contexts: web, android, ios, amp
Delete Container
DELETE /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}
Workspaces
List Workspaces
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces
Response:
{
"workspace": [
{
"path": "accounts/6353461358/containers/251407136/workspaces/2",
"accountId": "6353461358",
"containerId": "251407136",
"workspaceId": "2",
"name": "Default Workspace"
}
]
}
Create Workspace
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces
Content-Type: application/json
{
"name": "My Feature Workspace",
"description": "Working on new tracking features"
}
Get Workspace Status
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/status
Create Version from Workspace
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}:create_version
Content-Type: application/json
{
"name": "v2.0",
"notes": "Added new tracking tags"
}
Delete Workspace
DELETE /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}
Tags
List Tags
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/tags
Get Tag
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/tags/{tagId}
Create Tag
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/tags
Content-Type: application/json
{
"name": "Custom HTML Tag",
"type": "html",
"parameter": [
{
"type": "template",
"key": "html",
"value": "<script>console.log('hello');</script>"
}
],
"firingTriggerId": ["{triggerId}"]
}
Common tag types: html (Custom HTML), ua (Universal Analytics), gaawc (GA4 Config), gaawe (GA4 Event), gclidw (Conversion Linker), img (Custom Image)
Example:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"name": "GA4 Config Tag",
"type": "gaawc",
"parameter": [
{"type": "template", "key": "measurementId", "value": "G-XXXXXXXXXX"}
],
"firingTriggerId": ["2147479553"]
}).encode()
req = urllib.request.Request('https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/tags', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Update Tag
PUT /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/tags/{tagId}
Content-Type: application/json
{
"name": "Updated Tag Name",
"type": "html",
"parameter": [...],
"firingTriggerId": ["{triggerId}"],
"fingerprint": "{current_fingerprint}"
}
Include the current fingerprint value to ensure you're updating the latest version.
Delete Tag
DELETE /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/tags/{tagId}
Triggers
List Triggers
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/triggers
Create Trigger
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/triggers
Content-Type: application/json
{
"name": "All Pages",
"type": "pageview"
}
Common trigger types: pageview, domReady, windowLoaded, customEvent, click, linkClick, formSubmit, timer, scrollDepth
Example with filter:
python <<'EOF'
import urllib.request, os, json
data = json.dumps({
"name": "Click on CTA Button",
"type": "click",
"filter": [
{
"type": "equals",
"parameter": [
{"type": "template", "key": "arg0", "value": "{{Click Classes}}"},
{"type": "template", "key": "arg1", "value": "cta-button"}
]
}
]
}).encode()
req = urllib.request.Request('https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/triggers', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Update Trigger
PUT /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/triggers/{triggerId}
Content-Type: application/json
{
"name": "Updated Trigger",
"type": "pageview",
"fingerprint": "{current_fingerprint}"
}
Delete Trigger
DELETE /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/triggers/{triggerId}
Variables
List Variables
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/variables
Create Variable
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/variables
Content-Type: application/json
{
"name": "Data Layer Variable",
"type": "v",
"parameter": [
{"type": "integer", "key": "dataLayerVersion", "value": "2"},
{"type": "template", "key": "name", "value": "myDataLayerVar"}
]
}
Common variable types: v (Data Layer), j (JavaScript Variable), jsm (Custom JavaScript), c (Constant), k (Cookie), u (URL), f (DOM Element)
Update Variable
PUT /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/variables/{variableId}
Content-Type: application/json
{
"name": "Updated Variable",
"type": "v",
"parameter": [...],
"fingerprint": "{current_fingerprint}"
}
Delete Variable
DELETE /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/variables/{variableId}
Built-In Variables
List Built-In Variables
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/workspaces/{workspaceId}/built_in_variables
Response:
{
"builtInVariable": [
{
"path": "accounts/6353461358/containers/251407136/workspaces/2/built_in_variables",
"type": "pageUrl",
"name": "Page URL"
},
{
"type": "pageHostname",
"name": "Page Hostname"
},
{
"type": "pagePath",
"name": "Page Path"
},
{
"type": "referrer",
"name": "Referrer"
},
{
"type": "event",
"name": "Event"
}
]
}
Environments
List Environments
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/environments
Create Environment
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/environments
Content-Type: application/json
{
"name": "Staging",
"description": "Staging environment for testing"
}
Delete Environment
DELETE /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/environments/{environmentId}
Container Versions
List Version Headers
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/version_headers
Get Version
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/versions/{versionId}
Get Live Version
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/versions:live
Publish Version
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/versions/{versionId}:publish
Delete Version
DELETE /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers/{containerId}/versions/{versionId}
User Permissions
List User Permissions
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/user_permissions
Response:
{
"userPermission": [
{
"path": "accounts/6353461358/user_permissions/05842032124443686272",
"accountId": "6353461358",
"emailAddress": "user@example.com",
"accountAccess": {
"permission": "admin"
},
"containerAccess": [
{
"containerId": "251407136",
"permission": "publish"
}
]
}
]
}
Create User Permission
POST /google-tag-manager/tagmanager/v2/accounts/{accountId}/user_permissions
Content-Type: application/json
{
"emailAddress": "newuser@example.com",
"accountAccess": {
"permission": "user"
},
"containerAccess": [
{
"containerId": "{containerId}",
"permission": "read"
}
]
}
Permission levels: noAccess, read, edit, approve, publish (container); noAccess, user, admin (account)
Pagination
List endpoints use token-based pagination with pageToken parameter:
GET /google-tag-manager/tagmanager/v2/accounts/{accountId}/containers?pageToken={nextPageToken}
Response includes nextPageToken when more results exist.
Code Examples
JavaScript
const response = await fetch(
'https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
console.log(data.account);
Python
import os
import requests
# List accounts
response = requests.get(
'https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
accounts = response.json().get('account', [])
# List containers for first account
if accounts:
account_id = accounts[0]['accountId']
containers_resp = requests.get(
f'https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts/{account_id}/containers',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
print(containers_resp.json())
Notes
- All resources use hierarchical paths:
accounts/{id}/containers/{id}/workspaces/{id}/... - The
fingerprintfield is used for optimistic concurrency control; include it in update requests - Updates (PUT) require the full resource body, not just changed fields
- The
usageContextfor containers can beweb,android,ios, oramp - Built-in trigger ID
2147479553is the "All Pages" trigger available in all containers - Publishing a version makes it live immediately on all sites using the container
- Workspaces provide draft isolation; changes are committed by creating a version
- IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jqor other commands, environment variables like$MATON_API_KEYmay not expand correctly in some shell environments
Error Handling
| Status | Meaning |
|---|---|
| 400 | Bad request (invalid parameters, malformed resource body) |
| 401 | Invalid or missing Maton API key |
| 403 | Forbidden (insufficient GTM permissions) |
| 404 | Resource not found |
| 409 | Conflict (fingerprint mismatch on update) |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Google Tag Manager API |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
google-tag-manager. For example:
- Correct:
https://api.maton.ai/google-tag-manager/tagmanager/v2/accounts - Incorrect:
https://api.maton.ai/tagmanager/v2/accounts