---
title: "GTM Kit 2.13.0: keep GTM off the pages that need it off, and a new event push seam"
date: 2026-05-26
author: "GTM Kit"
categories:
  - name: "Announcements"
    url: "/category/announcements.md"
---

# GTM Kit 2.13.0: keep GTM off the pages that need it off, and a new event push seam

GTM Kit 2.13.0 adds a URL exclusion list so you can stop the container from loading on specific pages, and introduces a client-side push seam that every GTM Kit event now flows through.

If you upgrade and change nothing, nothing changes. The exclusion list is empty by default, and the new push seam pushes events exactly as before until an add-on tells it otherwise. Read on for what each one is for.

## What changed

### Exclude pages from GTM

There are pages where you do not want the Google Tag Manager container to load at all. Third-party checkout iframes that run their own tracking. Partner-hosted subpages. In-app webview routes. Internal preview screens. Until now, GTM Kit loaded the container on every frontend page, and the only way out was a custom filter.

The new **Exclude pages from GTM** section on Settings → Container gives you a deny-list of URL patterns. Add a pattern, and GTM Kit holds back everything on a matching page: the head loader script, the `noscript` iframe, and the supporting data layer scripts. They withhold together, so a matched page gets no GTM Kit output at all.

Two matching modes:

- **Glob (default).** Use `*` and `?` against the start of the path. `/checkout-iframe/*` matches everything under that path. Paste a full URL into a row and it collapses to its path on save.
- **Regex (opt-in).** For power users who need it. A pattern that fails to compile is rejected when you save, and if a bad pattern ever reaches the frontend it is treated as no match. The container stays on rather than risk blanking out tracking site-wide.

Matching is on the URL path only (query strings are ignored), case-insensitive, with trailing slashes normalised. The decision depends only on the request path, so it behaves correctly behind full-page caches like Cloudflare, Varnish, and LiteSpeed.

### A push seam in front of every event

GTM Kit now routes every event it emits, whether rendered server-side in PHP or pushed from the WooCommerce, EDD, and Contact Form 7 integration scripts, through a single client-side helper: `window.gtmkit.events.push()`.

On its own this changes nothing. Events push immediately, in the same order, with the same payloads as before. What it gives you is one place where event flow can be intercepted in the browser, on cached and uncached pages alike, without wrapping the global `window.dataLayer.push` (so your consent management platform keeps working).

This is the groundwork for client-side event deferral: holding consent-sensitive events such as `add_to_cart` and `purchase` until a visitor accepts marketing or analytics, while consent-neutral events like `page_view` keep firing. The deferral queue itself, with per-event control and a timeout fallback, is a GTM Kit Premium feature arriving in a coming release. The seam that makes it possible is free and ships today.

## Developer notes

- **New JS API:** `window.gtmkit.events.push(event, name)` sits in front of every GTM Kit event push. A companion `window.gtmkit.events.registerDeferralSink(fn)` lets an add-on receive events that should be held back instead of pushed. When no add-on defines `window.gtmkit.events.shouldDefer`, the seam pushes immediately and free-user behaviour is unchanged.
- **New PHP filter:** `gtmkit_excluded_url_patterns` lets you edit the effective list of exclusion patterns programmatically.
- **New PHP filter:** `gtmkit_is_url_excluded` is the final per-request override on whether the current URL is excluded.
- **Behaviour change to an existing filter:** `gtmkit_container_active` now receives the computed container-active value instead of a hardcoded `true`. Callbacks that pass the value through unchanged automatically honour the new URL exclusion. Callbacks that hardcode `return true;` still force the container on, as before.
- The global `window.dataLayer.push` is never reassigned, wrapped, or Proxied.

## Upgrade notes

No action needed for most installs. The exclusion list starts empty, so the container loads everywhere it did before. The push seam is transparent until an add-on hooks into it.

If you currently filter `gtmkit_container_active` to switch the container off on certain pages, the new exclusion list is a config-only way to do the same thing, and your existing filter still runs. If your callback returns the incoming value through unchanged, it now reflects the URL exclusion automatically.