Zum Inhalt springen
Woodander Doku
DE

Tag Manager

Read a Google Tag Manager container, plan a migration, and change tags, triggers and variables under Manual, Hybrid or Autonomous mode.

18 endpoints. Each one is a REST endpoint under https://woodander.com/api/v1 and an MCP tool with the same name and arguments. See the overview for authentication, rate limits and errors.

gtm_list_containers

GET /api/v1/gtm/containers

Your Google Tag Manager accounts and containers, which site each one is chosen for, its mode, and the Tag Manager permissions you gave Woodander.

MCP tool gtm_list_containers Scope read:gtm Plan Pro and above

Parameters

No parameters.

Example request

bash
curl "https://woodander.com/api/v1/gtm/containers" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_list_containers",
        "arguments": {}
    }
}

Example response Example

json
{
    "data": [
        {
            "public_id": "GTM-AB12CD",
            "name": "example.com",
            "account": "Example",
            "site": "example.com",
            "mode": "hybrid",
            "usage": [
                "web"
            ]
        }
    ],
    "meta": {
        "total": 1,
        "permissions": {
            "read": true,
            "edit": true,
            "publish": false
        }
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_list_workspaces

GET /api/v1/sites/{site}/gtm/workspaces

The workspaces of the site's container and the one Woodander reads (its own "Woodander" workspace when it exists, else the Default Workspace).

MCP tool gtm_list_workspaces Scope read:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).

Example request

bash
curl "https://woodander.com/api/v1/sites/example.com/gtm/workspaces" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_list_workspaces",
        "arguments": {
            "site": "example.com"
        }
    }
}

Example response Example

json
{
    "data": {
        "site": "example.com",
        "container": "GTM-AB12CD",
        "workspaces": [
            {
                "id": "7",
                "name": "Default Workspace"
            },
            {
                "id": "9",
                "name": "Woodander"
            }
        ],
        "in_use": {
            "id": "9",
            "name": "Woodander",
            "fingerprint": "1697623",
            "is_woodander": true
        }
    },
    "meta": {
        "source": "gtm_snapshot"
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_get_container

GET /api/v1/sites/{site}/gtm/container

The container snapshot: tags, triggers and variables in plain words, enabled built-in variables and the versions. Served from a cache keyed by the workspace fingerprint; refresh=true asks Google again.

MCP tool gtm_get_container Scope read:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
refresh query boolean No Read from Google instead of the cached snapshot (uses the shared quota).

Example request

bash
curl "https://woodander.com/api/v1/sites/example.com/gtm/container" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_get_container",
        "arguments": {
            "site": "example.com"
        }
    }
}

Example response Example

json
{
    "data": {
        "site": "example.com",
        "mode": "hybrid",
        "container": {
            "public_id": "GTM-AB12CD",
            "name": "example.com"
        },
        "workspace": {
            "id": "9",
            "name": "Woodander",
            "is_woodander": true
        },
        "tags": [
            {
                "id": "3",
                "name": "Google tag - G-ABC123",
                "type": "googtag",
                "details": [
                    {
                        "label": "Type",
                        "value": "Google tag"
                    },
                    {
                        "label": "ID",
                        "value": "G-ABC123"
                    },
                    {
                        "label": "Fires on",
                        "value": "All Pages"
                    }
                ],
                "firing_trigger_ids": [
                    "2147479553"
                ],
                "paused": false
            }
        ],
        "triggers": [],
        "variables": [],
        "built_in_variables": [
            "Page URL",
            "Event"
        ],
        "versions": [
            {
                "id": "4",
                "name": "Launch",
                "tags": 3,
                "deleted": false
            }
        ],
        "fetched_at": "2026-10-18T10:00:00+00:00"
    },
    "meta": {
        "stale": false,
        "source": "gtm_snapshot"
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422invalid_requestA parameter is not valid (range, type, cursor).
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_analyze_tracking

GET /api/v1/sites/{site}/gtm/analysis

Compares the container with a tracking plan (default page_view, sign_up, begin_checkout, purchase): missing events, duplicates (two Google tags or GA4 configurations with the same measurement id, an event sent twice), tags without or with broken triggers, undefined variables, unused triggers, and sign-ups or purchases sent on a click.

MCP tool gtm_analyze_tracking Scope read:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
events query string No Your plan: GA4 event names separated by commas, e.g. page_view,sign_up,test_started,purchase.

Example request

bash
curl "https://woodander.com/api/v1/sites/example.com/gtm/analysis" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_analyze_tracking",
        "arguments": {
            "site": "example.com"
        }
    }
}

Example response Example

json
{
    "data": {
        "site": "example.com",
        "plan": [
            {
                "event": "page_view",
                "status": "ok",
                "tags": [
                    "Google tag - G-ABC123"
                ]
            },
            {
                "event": "sign_up",
                "status": "missing",
                "tags": []
            }
        ],
        "issues": [
            {
                "code": "missing_events",
                "severity": "warning",
                "message": "Events of the tracking plan that no tag sends.",
                "items": [
                    "sign_up"
                ]
            }
        ],
        "counts": {
            "tags": 1,
            "triggers": 0,
            "variables": 0
        }
    },
    "meta": {
        "source": "gtm_snapshot"
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422invalid_requestA parameter is not valid (range, type, cursor).
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_scan_site

GET /api/v1/sites/{site}/gtm/scan

Reads one live page of your site and finds tags hard-coded in its HTML: gtag.js / GA4 (G-), Google Ads (AW-), Meta Pixel, Microsoft Clarity, Hotjar, LinkedIn Insight, TikTok Pixel and an existing GTM snippet. Changes nothing.

MCP tool gtm_scan_site Scope read:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
url query string No A page of this site (path or full https URL). Default: the start page.

Example request

bash
curl "https://woodander.com/api/v1/sites/example.com/gtm/scan" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_scan_site",
        "arguments": {
            "site": "example.com"
        }
    }
}

Example response Example

json
{
    "data": {
        "site": "example.com",
        "url": "https://example.com/",
        "status": 200,
        "found": [
            {
                "vendor": "ga4",
                "label": "Google Analytics 4 (gtag.js)",
                "id": "G-ABC123",
                "evidence": "gtag.js"
            },
            {
                "vendor": "meta_pixel",
                "label": "Meta Pixel",
                "id": "1234567890",
                "evidence": "fbq init"
            }
        ],
        "gtm_snippets": [
            "GTM-AB12CD"
        ]
    },
    "meta": {
        "changes_site": false
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422invalid_requestA parameter is not valid (range, type, cursor).
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_plan_migration

GET /api/v1/sites/{site}/gtm/migration-plan

Site → GTM: the tags that would replace the snippets hard-coded on the page, as ready inputs for gtm_create_tag, plus warnings. Never publishes and never edits the site: remove the snippets in the site's code and publish together with that deploy, or everything is counted twice.

MCP tool gtm_plan_migration Scope read:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
url query string No A page of this site. Default: the start page.

Example request

bash
curl "https://woodander.com/api/v1/sites/example.com/gtm/migration-plan" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_plan_migration",
        "arguments": {
            "site": "example.com"
        }
    }
}

Example response Example

json
{
    "data": {
        "site": "example.com",
        "container": "GTM-AB12CD",
        "scan": {
            "url": "https://example.com/",
            "found": []
        },
        "steps": [
            {
                "action": "gtm.create_tag",
                "vendor": "meta_pixel",
                "input": {
                    "name": "Meta Pixel - base code",
                    "type": "html",
                    "html": "<script>...</script>",
                    "firing_trigger_ids": [
                        "2147479553"
                    ]
                },
                "reason": "Replaces the hard-coded Meta Pixel (1234567890)."
            }
        ],
        "already_in_gtm": [
            "Google tag - G-ABC123"
        ],
        "manual": [],
        "warnings": [
            "While a snippet stays in the site’s code and the same tag is live in Tag Manager, every visit and event is counted twice. Publish the version only together with the deploy that removes the snippets from the site."
        ]
    },
    "meta": {
        "publishes": false,
        "source": "gtm_snapshot"
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422invalid_requestA parameter is not valid (range, type, cursor).
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_list_changes

GET /api/v1/sites/{site}/gtm/changes

The last 50 change requests for the site's container: proposals, changes waiting for the owner's confirmation, queued, done, failed and rejected ones, each with its diff.

MCP tool gtm_list_changes Scope read:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).

Example request

bash
curl "https://woodander.com/api/v1/sites/example.com/gtm/changes" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_list_changes",
        "arguments": {
            "site": "example.com"
        }
    }
}

Example response Example

json
{
    "data": [
        {
            "id": 12,
            "action": "gtm.create_tag",
            "risk": "reversible",
            "status": "pending",
            "needs": "apply",
            "summary": "Create tag “GA4 event - sign_up” (GA4 event)",
            "diff": [
                {
                    "op": "+",
                    "kind": "tag",
                    "name": "GA4 event - sign_up",
                    "details": [
                        "Type: GA4 event",
                        "ID: G-ABC123",
                        "Event: sign_up",
                        "Fires on: CE - sign_up"
                    ]
                }
            ],
            "requested_by": "Token “Claude Code”",
            "note": null,
            "error": null,
            "result": null,
            "confirm_url": "https://woodander.com/workspace/seo/tag-manager?site=example.com&change=12",
            "created_at": "2026-10-18T10:00:00+00:00",
            "decided_at": null
        }
    ],
    "meta": {
        "total": 1,
        "site": "example.com"
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_change_status

GET /api/v1/gtm/changes/{id}

One change request (or a queued read) by id: its status (pending, queued, running, done, failed, rejected), what it waits for and the result, e.g. the GTM version id.

MCP tool gtm_change_status Scope read:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
id path integer Yes The id a change or a queued read returned.

Example request

bash
curl "https://woodander.com/api/v1/gtm/changes/12" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_change_status",
        "arguments": {
            "id": 12
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.create_version",
        "risk": "reversible",
        "status": "done",
        "needs": null,
        "summary": "Create version “sign_up tracking” from the Woodander workspace",
        "diff": [],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": {
            "summary": "Create version “sign_up tracking” from the Woodander workspace",
            "ids": {
                "tag_id": "25"
            }
        },
        "confirm_url": null,
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "done",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the read:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
429rate_limitedToo many requests. See the Retry-After header.

gtm_create_tag

POST /api/v1/sites/{site}/gtm/tags

Create a tag in the "Woodander" workspace (never the live Default Workspace). A duplicate (same name, same Google tag id, same GA4 event to the same id) is refused. Manual mode: stored as a proposal the owner applies.

MCP tool gtm_create_tag Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
name body string Yes Tag name, e.g. "GA4 event - sign_up".
type body string Yes googtag = Google tag (GA4 / Ads id), gaawe = GA4 event, html = Custom HTML, awct = Google Ads conversion, gclidw = Conversion Linker. One of: googtag, gaawe, html, awct, gclidw.
google_tag_id body string No googtag: the id it loads, e.g. G-ABC123 or AW-123456.
measurement_id body string No gaawe: the GA4 measurement id the event is sent to, e.g. G-ABC123.
event_name body string No gaawe: the GA4 event name, e.g. sign_up, or one variable reference such as {{Event}} (a variable of the container or a built-in one) to send many events with one tag.
event_parameters body array<object> No gaawe: event parameters, a list of {"name", "value"} (value may be a {{Variable}}).
html body string No html: the Custom HTML.
conversion_id body string No awct: Google Ads conversion id.
conversion_label body string No awct: Google Ads conversion label.
firing_trigger_ids body array<string> No Ids of the triggers that fire it (2147479553 = All Pages). One of firing_trigger_ids or firing_trigger_names is required to create.
firing_trigger_names body array<string> No Trigger names instead of ids, resolved when the change runs (use it for a trigger another change creates first).
paused body boolean No Pause the tag.
notes body string No Notes kept on the tag.

Example request

bash
curl -X POST "https://woodander.com/api/v1/sites/example.com/gtm/tags" \
  -H "Authorization: Bearer wdr_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"example","type":"googtag"}'
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_create_tag",
        "arguments": {
            "site": "example.com",
            "name": "example",
            "type": "googtag"
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.create_tag",
        "risk": "reversible",
        "status": "pending",
        "needs": "apply",
        "summary": "Create tag “GA4 event - sign_up” (GA4 event)",
        "diff": [
            {
                "op": "+",
                "kind": "tag",
                "name": "GA4 event - sign_up",
                "details": [
                    "Type: GA4 event",
                    "ID: G-ABC123",
                    "Event: sign_up",
                    "Fires on: CE - sign_up"
                ]
            }
        ],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": null,
        "confirm_url": "https://woodander.com/workspace/seo/tag-manager?site=example.com&change=12",
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "proposed",
        "mode": "manual",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_update_tag

PATCH /api/v1/sites/{site}/gtm/tags/{id}

Update a tag in the "Woodander" workspace. Fields you send replace those of the tag; the others stay.

MCP tool gtm_update_tag Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
id path string Yes GTM tag id (numeric, see gtm_get_container).
name body string No Tag name, e.g. "GA4 event - sign_up".
google_tag_id body string No googtag: the id it loads, e.g. G-ABC123 or AW-123456.
measurement_id body string No gaawe: the GA4 measurement id the event is sent to, e.g. G-ABC123.
event_name body string No gaawe: the GA4 event name, e.g. sign_up, or one variable reference such as {{Event}} (a variable of the container or a built-in one) to send many events with one tag.
event_parameters body array<object> No gaawe: event parameters, a list of {"name", "value"} (value may be a {{Variable}}).
html body string No html: the Custom HTML.
conversion_id body string No awct: Google Ads conversion id.
conversion_label body string No awct: Google Ads conversion label.
firing_trigger_ids body array<string> No Ids of the triggers that fire it (2147479553 = All Pages). One of firing_trigger_ids or firing_trigger_names is required to create.
firing_trigger_names body array<string> No Trigger names instead of ids, resolved when the change runs (use it for a trigger another change creates first).
paused body boolean No Pause the tag.
notes body string No Notes kept on the tag.

Example request

bash
curl -X PATCH "https://woodander.com/api/v1/sites/example.com/gtm/tags/12" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_update_tag",
        "arguments": {
            "site": "example.com",
            "id": 12
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.update_tag",
        "risk": "reversible",
        "status": "done",
        "needs": null,
        "summary": "Update tag #25",
        "diff": [
            {
                "op": "~",
                "kind": "tag",
                "name": "GA4 event - sign_up",
                "details": [
                    "Event: signup → sign_up"
                ]
            }
        ],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": {
            "summary": "Update tag #25",
            "ids": {
                "tag_id": "25"
            }
        },
        "confirm_url": null,
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "done",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_delete_tag

DELETE /api/v1/sites/{site}/gtm/tags/{id}

Delete a tag in the "Woodander" workspace. Deleting always waits for the owner's confirmation in the Workspace (confirm_url), in every mode.

MCP tool gtm_delete_tag Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
id path string Yes GTM tag id (numeric, see gtm_get_container).

Example request

bash
curl -X DELETE "https://woodander.com/api/v1/sites/example.com/gtm/tags/12" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_delete_tag",
        "arguments": {
            "site": "example.com",
            "id": 12
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.delete_tag",
        "risk": "destructive",
        "status": "pending",
        "needs": "confirm",
        "summary": "Delete tag #25",
        "diff": [
            {
                "op": "-",
                "kind": "tag",
                "name": "Old pixel",
                "details": [
                    "Type: Custom HTML"
                ]
            }
        ],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": null,
        "confirm_url": "https://woodander.com/workspace/seo/tag-manager?site=example.com&change=12",
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "pending_confirmation",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_create_trigger

POST /api/v1/sites/{site}/gtm/triggers

Create a trigger in the "Woodander" workspace. A custom event trigger for an event that already has one is refused.

MCP tool gtm_create_trigger Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
name body string Yes Trigger name, e.g. "CE - sign_up".
type body string Yes Trigger type. One of: pageview, domReady, windowLoaded, customEvent, click, linkClick, formSubmission, historyChange.
event_name body string No customEvent: the dataLayer event it listens for.
filters body array<object> No Conditions, a list of {"variable": "Page Path", "operator": "equals|contains|startsWith|endsWith|matchRegex", "value"}.
notes body string No Notes kept on the trigger.

Example request

bash
curl -X POST "https://woodander.com/api/v1/sites/example.com/gtm/triggers" \
  -H "Authorization: Bearer wdr_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"example","type":"pageview"}'
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_create_trigger",
        "arguments": {
            "site": "example.com",
            "name": "example",
            "type": "pageview"
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.create_trigger",
        "risk": "reversible",
        "status": "done",
        "needs": null,
        "summary": "Create trigger “CE - sign_up” (Custom event)",
        "diff": [
            {
                "op": "+",
                "kind": "trigger",
                "name": "CE - sign_up",
                "details": [
                    "Type: Custom event",
                    "Event: sign_up"
                ]
            }
        ],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": {
            "summary": "Create trigger “CE - sign_up” (Custom event)",
            "ids": {
                "tag_id": "25"
            }
        },
        "confirm_url": null,
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "done",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_update_trigger

PATCH /api/v1/sites/{site}/gtm/triggers/{id}

Update a trigger in the "Woodander" workspace.

MCP tool gtm_update_trigger Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
id path string Yes GTM trigger id (numeric, see gtm_get_container).
name body string No Trigger name, e.g. "CE - sign_up".
event_name body string No customEvent: the dataLayer event it listens for.
filters body array<object> No Conditions, a list of {"variable": "Page Path", "operator": "equals|contains|startsWith|endsWith|matchRegex", "value"}.
notes body string No Notes kept on the trigger.

Example request

bash
curl -X PATCH "https://woodander.com/api/v1/sites/example.com/gtm/triggers/12" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_update_trigger",
        "arguments": {
            "site": "example.com",
            "id": 12
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.update_trigger",
        "risk": "reversible",
        "status": "done",
        "needs": null,
        "summary": "Update trigger #31",
        "diff": [],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": {
            "summary": "Update trigger #31",
            "ids": {
                "tag_id": "25"
            }
        },
        "confirm_url": null,
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "done",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_create_variable

POST /api/v1/sites/{site}/gtm/variables

Create a variable in the "Woodander" workspace.

MCP tool gtm_create_variable Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
name body string Yes Variable name.
type body string Yes v = data layer variable, c = constant, u = URL, k = 1st-party cookie, jsm = custom JavaScript. One of: v, c, u, k, jsm.
data_layer_name body string No v: the dataLayer key, e.g. ecommerce.value.
value body string No c: the constant value.
component body string No u: the part of the URL. One of: URL, HOST, PATH, QUERY, FRAGMENT.
cookie_name body string No k: the cookie name.
javascript body string No jsm: function () { return ...; }
notes body string No Notes kept on the variable.

Example request

bash
curl -X POST "https://woodander.com/api/v1/sites/example.com/gtm/variables" \
  -H "Authorization: Bearer wdr_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"example","type":"v"}'
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_create_variable",
        "arguments": {
            "site": "example.com",
            "name": "example",
            "type": "v"
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.create_variable",
        "risk": "reversible",
        "status": "done",
        "needs": null,
        "summary": "Create variable “DLV - value” (Data layer variable)",
        "diff": [],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": {
            "summary": "Create variable “DLV - value” (Data layer variable)",
            "ids": {
                "tag_id": "25"
            }
        },
        "confirm_url": null,
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "done",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_update_variable

PATCH /api/v1/sites/{site}/gtm/variables/{id}

Update a variable in the "Woodander" workspace.

MCP tool gtm_update_variable Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
id path string Yes GTM variable id (numeric, see gtm_get_container).
name body string No Variable name.
data_layer_name body string No v: the dataLayer key, e.g. ecommerce.value.
value body string No c: the constant value.
component body string No u: the part of the URL. One of: URL, HOST, PATH, QUERY, FRAGMENT.
cookie_name body string No k: the cookie name.
javascript body string No jsm: function () { return ...; }
notes body string No Notes kept on the variable.

Example request

bash
curl -X PATCH "https://woodander.com/api/v1/sites/example.com/gtm/variables/12" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_update_variable",
        "arguments": {
            "site": "example.com",
            "id": 12
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.update_variable",
        "risk": "reversible",
        "status": "done",
        "needs": null,
        "summary": "Update variable #40",
        "diff": [],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": {
            "summary": "Update variable #40",
            "ids": {
                "tag_id": "25"
            }
        },
        "confirm_url": null,
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "done",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_create_version

POST /api/v1/sites/{site}/gtm/versions

Turn the "Woodander" workspace into a container version. Not live: publishing is a separate step (gtm_publish_version). Google removes the workspace afterwards; the next change makes a new one.

MCP tool gtm_create_version Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
name body string Yes Version name.
notes body string No What changed and why.

Example request

bash
curl -X POST "https://woodander.com/api/v1/sites/example.com/gtm/versions" \
  -H "Authorization: Bearer wdr_..." \
  -H "Content-Type: application/json" \
  -d '{"name":"example"}'
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_create_version",
        "arguments": {
            "site": "example.com",
            "name": "example"
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.create_version",
        "risk": "reversible",
        "status": "done",
        "needs": null,
        "summary": "Create version “sign_up tracking” from the Woodander workspace",
        "diff": [],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": {
            "summary": "Create version “sign_up tracking” from the Woodander workspace",
            "ids": {
                "tag_id": "25"
            }
        },
        "confirm_url": null,
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "done",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_publish_version

POST /api/v1/sites/{site}/gtm/versions/{version_id}/publish

Make a version live. Guarded: in Manual and Hybrid it returns a pending confirmation (confirm_url) the owner gives in the Workspace; only in Autonomous mode, with a token that also holds publish:gtm and within the daily publish cap, it publishes at once (duplicate check, the previous version kept for rollback, an email to the owner).

MCP tool gtm_publish_version Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
version_id path string Yes The version id (from gtm_create_version or gtm_get_container).

Example request

bash
curl -X POST "https://woodander.com/api/v1/sites/example.com/gtm/versions/12/publish" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_publish_version",
        "arguments": {
            "site": "example.com",
            "version_id": 12
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.publish_version",
        "risk": "publish",
        "status": "pending",
        "needs": "confirm",
        "summary": "Publish version 5",
        "diff": [
            {
                "op": "~",
                "kind": "live version",
                "name": "version 5 “sign_up tracking”",
                "details": [
                    "Becomes live on the site for every visitor"
                ]
            }
        ],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": null,
        "confirm_url": "https://woodander.com/workspace/seo/tag-manager?site=example.com&change=12",
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "pending_confirmation",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.

gtm_rollback

POST /api/v1/sites/{site}/gtm/rollback

Republish the version that was live before the last publish through Woodander (or the version you name). Same guard as gtm_publish_version.

MCP tool gtm_rollback Scope write:gtm Plan Pro and above

Parameters

NameInTypeRequiredDescription
site path string Yes Host of one of your sites with a Tag Manager container chosen for it (see gtm_list_containers).
version_id body string No A version to go back to. Default: the one live before the last publish.

Example request

bash
curl -X POST "https://woodander.com/api/v1/sites/example.com/gtm/rollback" \
  -H "Authorization: Bearer wdr_..."
tools/call
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
        "name": "gtm_rollback",
        "arguments": {
            "site": "example.com"
        }
    }
}

Example response Example

json
{
    "data": {
        "id": 12,
        "action": "gtm.rollback",
        "risk": "publish",
        "status": "pending",
        "needs": "confirm",
        "summary": "Roll back to the version live before the last publish",
        "diff": [],
        "requested_by": "Token “Claude Code”",
        "note": null,
        "error": null,
        "result": null,
        "confirm_url": "https://woodander.com/workspace/seo/tag-manager?site=example.com&change=12",
        "created_at": "2026-10-18T10:00:00+00:00",
        "decided_at": null
    },
    "meta": {
        "outcome": "pending_confirmation",
        "mode": "hybrid",
        "hint": null
    }
}

Errors

HTTPCodeMeaning
401unauthenticatedMissing, invalid, expired or revoked token.
403insufficient_scopeThe token does not have the write:gtm scope.
403plan_requiredThe plan does not include API access.
404not_foundNot found, or not yours.
422validation_failedThe body is not valid; details.errors names the fields.
404gtm_container_not_chosenNo Tag Manager container is chosen for the site.
409google_reconnectGoogle no longer accepts the owner's Tag Manager access.
409duplicateThe change would duplicate a tag, trigger or variable the container already has.
429rate_limitedToo many requests. See the Retry-After header.