npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gtm-manager-mcp

v0.1.16

Published

Model Context Protocol (MCP) server for managing Google Tag Manager.

Readme

GTM Manager MCP Server

A Model Context Protocol (MCP) server that provides comprehensive Google Tag Manager (GTM) API access. This tool enables full CRUD operations on GTM tags, variables, and triggers with proper authentication and error handling.

Features

Authentication

  • OAuth 2.0 authentication with Google Tag Manager
  • Secure token storage and management
  • Automatic token refresh

Container Operations

  • List all containers in an account
  • Find containers by GTM ID

Tag Management

  • List all tags in a workspace
  • Create custom HTML tags
  • Create native GA4 Configuration/Event tags
  • Update existing tags
  • Update GA4 Event tags in place
  • Delete tags
  • Automatic trigger assignment
  • Pause/unpause tags

Validation & Publish

  • Validate workspace before publishing
  • Create/publish versions

Variable Management

  • List all variables
  • Create Custom JavaScript variables
  • Create Data Layer Variables (DLVs)
  • Update variable code
  • Delete variables

Trigger Management

  • List all triggers
  • Create triggers (Page View, Click, etc.)
  • Create Custom Event triggers (regex supported)
  • Update trigger conditions
  • Delete triggers

Prerequisites

  • Node.js 18.0 or higher
  • npm or yarn package manager
  • Google Cloud Project with Tag Manager API enabled
  • OAuth 2.0 Client ID and Secret
  • Access to target GTM containers

Required OAuth Scopes

For full functionality (CRUD + submit/publish), your OAuth token must include all of:

  • https://www.googleapis.com/auth/tagmanager.readonly
  • https://www.googleapis.com/auth/tagmanager.edit.containers
  • https://www.googleapis.com/auth/tagmanager.edit.containerversions
  • https://www.googleapis.com/auth/tagmanager.publish

If scopes change, re-consent: run npm run auth:url, open the URL, approve, then npm run auth:exchange -- <code>.

Installation

# Local development
npm install
npm run build

# Global install from local checkout
npm i -g .

# Or once published (package name)
# npm i -g gtm-manager-mcp

Google Cloud Configuration

Step 1: Enable Tag Manager API

  1. Navigate to Google Cloud Console
  2. Select or create a project
  3. Go to APIs & ServicesLibrary
  4. Search for "Tag Manager API"
  5. Click Enable

Step 2: Create OAuth 2.0 Credentials

  1. Go to APIs & ServicesCredentials
  2. Click + CREATE CREDENTIALSOAuth client ID
  3. Configure the OAuth consent screen if prompted
  4. Select Application type: Web application
  5. Add Authorized redirect URIs:
    http://localhost:3101/callback (for local development)
  6. Save the generated Client ID and Client Secret

Step 3: Environment Configuration

Copy the example environment file and configure:

cp .env.example .env

Edit .env with your credentials:

# Required: Google OAuth Credentials
GOOGLE_CLIENT_ID=your-client-id-here
GOOGLE_CLIENT_SECRET=your-client-secret-here
GOOGLE_REDIRECT_URI=http://localhost:3101/callback

# Optional: Default GTM Container ID
GTM_ID=GTM-XXXXXXX

Local Callback and Auth (Port 3101)

  1. Start the local callback server:
    npm run serve:callback
    # Health check: http://localhost:3101/health
    # Callback URL (served inline): http://localhost:3101/callback
  2. Get the OAuth URL and authenticate:
    # If installed globally
    gtm-mcp-auth auth:url
    # Or from source
    npm run cli -- auth:url
    # Open the printed URL, sign in, it redirects to http://localhost:3101/callback
  3. Exchange the authorization code for tokens (copy the code from the callback page):
    # If installed globally
    gtm-mcp-auth auth:exchange "<paste-code>"
    # Or from source
    npm run cli -- auth:exchange "<paste-code>"
    # Tokens saved to data/gtm-token.json

If you see "insufficient authentication scopes" on create/publish:

  • Ensure the token includes tagmanager.edit.containerversions and tagmanager.publish (re-auth if needed).
  • Confirm the GTM user has Container permissions: Edit, Approve, Publish (or Admin).

Using Globally

  • Install globally (from npm): npm i -g gtm-manager-mcp
  • Or install from source (in repo root): npm i -g .
  • Binaries available:
    • gtm-mcp (MCP server over stdio)
    • gtm-mcp-callback (local OAuth callback at http://localhost:3101/callback)
    • gtm-mcp-auth (auth:url, auth:exchange, version:create, version:publish, submit)
  • Optional for active development: npm link instead of global install (remember to npm run build to refresh dist/).

Configure your MCP client to launch gtm-mcp with the project’s env vars.

Codex CLI config example

[mcp_servers.gtm_manager]
command = "bash"
args = ["-lc", "set -a; [ -f .env ] && source .env; exec gtm-mcp"]

Per-project tokens: set GTM_TOKEN_DIR=.gtm in each project’s .env to keep tokens isolated per project.

Quick global auth flow per project:

  1. gtm-mcp-callback (keeps callback server running)
  2. gtm-mcp-auth auth:url → open URL and approve
  3. gtm-mcp-auth auth:exchange "<code>"

Global Codex CLI integration (single env/token)

If you want the MCP server available in every Codex CLI session with a single shared .env and token directory:

  1. Create a wrapper script (adjust paths):
    mkdir -p ~/.local/bin
    cat > ~/.local/bin/gtm-mcp-global <<'SH'
    #!/usr/bin/env bash
    set -euo pipefail
    ENV_FILE="/absolute/path/to/.env"         # update
    TOKEN_DIR="/absolute/path/to/data"        # contains gtm-token.json
    if [ -f "$ENV_FILE" ]; then
      set -a; source "$ENV_FILE"; set +a
    fi
    export GTM_TOKEN_DIR="$TOKEN_DIR"
    exec gtm-mcp "$@"
    SH
    chmod +x ~/.local/bin/gtm-mcp-global
  2. Add to Codex config ~/.codex/config.toml:
    [mcp_servers.gtm]
    command = "/Users/you/.local/bin/gtm-mcp-global"
  3. Restart Codex CLI. In a new session, call the tool (e.g., ask to run gtm_health).

Tip: To reuse an existing token, set GTM_TOKEN_DIR to the directory that already contains gtm-token.json.

See docs/GTM-Manager-Global-Guide.md for a step‑by‑step walkthrough.

API Reference

Health

gtm_health

Check that the server is running and env/tokens are available.

Parameters: None

Returns: Status summary with env flags and token path

gtm_health_plus

Detailed health and permissions summary.

Parameters:

  • format (string, optional): 'json' for JSON output

Returns:

  • token scopes and expiry, active container/workspace, whether publish looks allowed, and missing scopes if any

Authentication

gtm_auth

Get the OAuth authentication URL.

Parameters: None

Returns: Authentication URL to visit in browser

Example:

await gtm_auth()
// Returns: "Visit this URL to authenticate: https://accounts.google.com/..."

gtm_authenticate

Complete authentication with the authorization code.

Parameters:

  • code (string, required): Authorization code from Google OAuth

Example:

await gtm_authenticate({ code: "4/0AY0e-g7..." })

Container Operations

gtm_list_containers

List all containers accessible to the authenticated account.

Parameters:

  • accountId (string, optional): Specific account ID to query

Example:

await gtm_list_containers()

Tag Operations

gtm_list_tags

List all tags in the current workspace.

Parameters:

  • gtmId (string, optional): GTM container ID (uses env default if not provided)
  • format (string, optional): 'json' for JSON output
  • idsOnly (boolean, optional): return IDs only

Example:

await gtm_list_tags({ gtmId: "GTM-ABC123" })

gtm_find_tags

Find tags by name (case-insensitive substring).

Parameters:

  • name (string, required): Name or substring to search for
  • gtmId (string, optional): GTM container ID
  • exact (boolean, optional): Exact match only
  • idsOnly (boolean, optional): Return IDs only

Example:

await gtm_find_tags({ name: 'GA4 Config' })

gtm_create_tag

Create a new HTML tag.

Parameters:

  • name (string, required): Tag name
  • html (string, required): HTML/JavaScript content
  • trigger (string, optional): Trigger type (default: "pageview")

Example:

await gtm_create_tag({
  name: "Analytics Event",
  html: "<script>console.log('Page viewed');</script>",
  trigger: "pageview"
})

gtm_create_ga4_configuration

Create a native GA4 Configuration tag.

Parameters:

  • name (string, required): Tag name
  • measurementId (string, required): GA4 Measurement ID (e.g., G-XXXXXXX)
  • sendPageView (boolean, optional): Send initial page_view (default: true)
  • trigger (string, optional): Trigger type (default: pageview)
  • fieldsToSet (object, optional): Additional fields (name -> value)

Example:

await gtm_create_ga4_configuration({
  name: 'GA4 Config',
  measurementId: 'G-TEST123',
  sendPageView: true,
  trigger: 'pageview',
  fieldsToSet: { debug_mode: 'true' }
})

gtm_create_ga4_event

Create a native GA4 Event tag.

Parameters:

  • name (string, required): Tag name
  • measurementId (string, optional): GA4 Measurement ID (e.g., G-XXXXXXX). Optional when configTagId is provided.
  • configTagId (string, optional): ID of a GA4 Configuration tag to link. Prefer this for Google tag containers.
  • eventName (string, required): Event name (e.g., login, purchase)
  • eventParameters (object, optional): Supports { value }, { var: 'Name' }, { varId: '53' }. With resolveVariables: true, names/IDs are resolved into macros.
  • trigger (string, optional): Trigger type (default: pageview)
  • triggerId (string, optional): Explicit Trigger ID to use (e.g., a Custom Event/Regex trigger)
  • resolveVariables (boolean, optional): Enable var resolution in parameters

Example:

await gtm_create_ga4_event({
  name: 'GA4 Event Login',
  configTagId: '44',
  eventName: 'login',
  eventParameters: { method: 'email' },
  triggerId: '43'
})

Notes:

  • When configTagId is provided, the event references your GA4 Configuration tag (recommended). It maps to the vendor key sendToTag and does not set measurementIdOverride.
  • If you pass trigger: "43" without triggerId, the tool will treat it as an ID automatically.

gtm_update_ga4_event_tag

Update an existing GA4 Event tag in place.

Parameters:

  • tagId (string, required)
  • Optional: name, configTagId, measurementId, eventName, eventParameters, trigger or triggerId, resolveVariables

Example:

await gtm_update_ga4_event_tag({ tagId: '57', configTagId: '44', eventName: '{{Event}}', triggerId: '43' })

gtm_pause_tag / gtm_unpause_tag

Pause or unpause a tag non-destructively.

Parameters:

  • tagId (string, required)

Example:

await gtm_pause_tag({ tagId: '32' })
await gtm_unpause_tag({ tagId: '32' })

gtm_update_tag

Update an existing tag.

Parameters:

  • tagId (string, required): Tag ID to update
  • name (string, optional): New tag name
  • html (string, optional): New HTML content

Example:

await gtm_update_tag({
  tagId: "12",
  html: "<script>console.log('Updated code');</script>"
})

gtm_delete_tag

Delete a tag from the workspace.

Parameters:

  • tagId (string, required): Tag ID to delete

Example:

await gtm_delete_tag({ tagId: "12" })

Variable Operations

gtm_list_variables

List all variables in the current workspace.

Parameters:

  • gtmId (string, optional): GTM container ID
  • format (string, optional): 'json' for JSON output
  • idsOnly (boolean, optional): return IDs only

Example:

await gtm_list_variables()

gtm_find_variables

Find variables by name.

Parameters:

  • name (string, required)
  • exact (boolean, optional)
  • idsOnly (boolean, optional)
  • gtmId (string, optional)

Example:

await gtm_find_variables({ name: 'Page Path (JS)', exact: true })

gtm_create_variable

Create a new Custom JavaScript variable.

Parameters:

  • name (string, required): Variable name
  • code (string, required): JavaScript function code
  • type (string, optional): Variable type (default: "jsm")

Example:

await gtm_create_variable({
  name: "Page Title",
  code: "function() { return document.title; }"
})

gtm_create_dlv

Create a Data Layer Variable (DLV) without writing JS.

Parameters:

  • name (string, required): Display name
  • dlvName (string, required): Data Layer key (e.g., page.path)
  • dataLayerVersion (number, optional): 1 or 2 (default 2)
  • defaultValue (string, optional): Fallback value

Example:

await gtm_create_dlv({ name: 'DLV Page Path', dlvName: 'page.path', dataLayerVersion: 2, defaultValue: '/' })

gtm_update_variable

Update an existing variable.

Parameters:

  • variableId (string, required): Variable ID to update
  • name (string, optional): New name
  • code (string, optional): New JavaScript code

Example:

await gtm_update_variable({
  variableId: "5",
  code: "function() { return document.title.toLowerCase(); }"
})

gtm_delete_variable

Delete a variable from the workspace.

Parameters:

  • variableId (string, required): Variable ID to delete

Example:

await gtm_delete_variable({ variableId: "5" })

Trigger Operations

gtm_list_triggers

List all triggers in the current workspace.

Parameters:

  • gtmId (string, optional): GTM container ID
  • format (string, optional): 'json' for JSON output
  • idsOnly (boolean, optional): return IDs only

Example:

await gtm_list_triggers()

gtm_find_triggers

Find triggers by name (case-insensitive substring).

Parameters:

  • name (string, required): Name or substring to search for
  • gtmId (string, optional): GTM container ID
  • exact (boolean, optional): Exact match only
  • idsOnly (boolean, optional): Return IDs only

Example:

await gtm_find_triggers({ name: 'Custom Event' })

gtm_create_trigger

Create a new trigger.

Parameters:

  • name (string, required): Trigger name
  • type (string, required): Trigger type ("pageview", "click", "formSubmit", etc.)
  • conditions (array, optional): Trigger conditions

Example:

await gtm_create_trigger({
  name: "Contact Form Submit",
  type: "formSubmit",
  conditions: [{
    type: "equals",
    parameter: [{
      type: "template",
      key: "formId",
      value: "contact-form"
    }]
  }]
})

gtm_create_custom_event_trigger

Create a Custom Event trigger (regex supported).

Parameters:

  • name (string, required)
  • eventName (string, required)
  • regex (boolean, optional)

Example:

await gtm_create_custom_event_trigger({ name: 'Login Event', eventName: '^login$', regex: true })

Versions & Validation

gtm_list_versions

List container versions with names/notes.

gtm_validate_workspace

Run pre‑publish checks (missing variables, trigger references, GA4 linkage). Returns issues array when failing.

Error Handling

The MCP server provides detailed error messages for common issues:

Authentication Errors

  • Missing required environment variables: Check your .env file
  • Invalid authorization code: The OAuth code may have expired
  • Token refresh failed: Re-authenticate using gtm_auth

API Errors

  • Container not found: Verify GTM ID and permissions
  • Workspace not found: Container may not have an active workspace
  • Permission denied: Check account access to the container
  • Invalid tag/variable ID: Verify the ID exists in the workspace

Common Solutions

  1. Re-authenticate if you see permission errors
  2. Check GTM permissions in Tag Manager interface
  3. Verify API is enabled in Google Cloud Console

Best Practices

Security

  • Never commit .env files to version control
  • Use environment-specific redirect URIs
  • Regularly rotate OAuth credentials
  • Limit API permissions to required scopes

Workspace Management

  • Always preview changes in GTM interface before publishing
  • Use descriptive names for tags and variables
  • Document complex JavaScript in variables
  • Test in GTM Preview mode before going live
  • Publish changes manually through the GTM web interface

Performance

  • Batch operations when possible
  • Cache container information locally
  • Minimize API calls by listing before updating

Development

Running Tests

npm test

Building from Source

npm run build

Development Mode

npm run dev

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

MIT License - see LICENSE file for details

Support

For issues and feature requests, please use the GitHub issue tracker.