humanmade / hm-gtm
Google Tag Manager Tools for WordPress
Requires
- composer/installers: ^1.0 || ^2.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- 3.1.4
- 3.1.3
- 3.1.2
- 3.1.1
- 3.1.0
- 3.0.0
- 2.1.2
- 2.1.1
- 2.1.0
- 2.0.8
- 2.0.7
- 2.0.6
- 2.0.5
- 2.0.4
- 2.0.3
- 2.0.2
- 2.0.1
- 2.0.0
- 1.1.0
- dev-fix/network-settings-descriptions
- dev-roborourke/release-process
- dev-roborourke/docs-sst-environments
- dev-add-phpcs-ignores
- dev-fix/35/datalayer-variable-name-characters
- dev-fix-incorrect-data-layer-object
This package is auto-updated.
Last update: 2026-10-27 12:18:24 UTC
README
Google Tag Manager template tags and settings tool. Now supports Server Side GTM.
v3 Breaking Changes
There are some breaking changes in v3.0.0:
- data layer no longer passes
post.author_idby default - data layer
post.IDrenamed topost.id - data layer
term.IDrenamed toterm.id - data layer
author.IDrenamed toauthor.id - data layer
user.roleis no longer an array but a comma separated list of roles - data layer
post.<taxonomy>is no longer an array but a comma separated list of term names - data layer
post.author_slugis no longer available by default, usepost.author_nameinstead
Usage
Once the plugin is installed and activated there are 2 places you can configure:
- On the general settings page in admin add your container ID eg.
GTM-123ABC - For a multisite install you can set a network wide container ID on the network settings screen
Server Side GTM
Server-side GTM sends your tag data through a container that you host, instead of straight from the browser to Google. Google explains the container side in its server-side tagging setup guide. This section covers the plugin side.
Plugin settings
Go to Settings > General in the admin. On multisite, the network settings screen has the same fields for a network-wide container.
- Container ID - the web container ID, for example
GTM-XXXXXXX. This is the only required field. - Server container URL - the absolute URL that serves your server container, for example
https://sst.example.com. The plugin loadsgtm.jsand the noscript iframe from this URL instead ofhttps://www.googletagmanager.com. Leave it empty to use Google's default. - Custom code snippet - a replacement for the standard
<head>snippet. Use it if your provider gives you a different one, or to use a GTM environment. - Custom iframe code snippet - a replacement for the
<noscript>iframe. Setting the server container URL is usually enough. - Cookie preservation - you can set a special UUID cookie that lasts a long time, some server side providers allow restoring cookies set by 3rd parties or client side code in this way.
Custom snippets can use these placeholders: %1$s is the container ID, %2$s is the server container URL (or https://www.googletagmanager.com when empty), and %3$s is the data layer name. The iframe snippet only supports %1$s and %2$s.
First-time setup
- Create and configure the server container in GTM. Follow Google's setup guide for the GA4 client, the GA4 tag and its trigger.
- Serve the server container from your own domain. Use a subdomain such as
sst.example.com, or a path on your site such ashttps://example.com/metricsthat a reverse proxy forwards to the container. Both are first-party, which stops browsers and ad blockers treating the requests as third-party. - Enter the container ID and the server container URL in the plugin settings. Use the same URL that you gave the Google tag as
server_container_urlin the web container. - Check the setup with server-side Preview in GTM, and look for
gtm.jsandcollect?v=2requests to your server container URL in the browser Network tab. See Google's preview and debug guide.
Check data before you switch over
Google advises running server-side tagging alongside your existing setup until the numbers match.
- Keep your current client-side tags as they are.
- Create a separate GA4 property for the server-side data.
- Copy your existing tags one at a time so that events go to both properties.
- Compare the two properties. When the server-side data reaches parity, move collection to the server and remove the duplicate tags.
No script fallback
NOTE: This is not needed for block themes.
If your theme is a classic theme, and you wish to support the fallback iframe for devices without javascript, add the following code just after the opening <body> tag in your theme:
<?php wp_body_open(); ?>
GTM environments
GTM environments let you publish a container version to a staging or development site without touching live. Each environment has its own snippet. The snippet adds gtm_auth, gtm_preview and gtm_cookies_win query parameters that point to the environment.
To use one:
- In GTM, go to Admin > Environments, open the Actions menu for the environment, and choose Get Snippet.
- Paste the
<head>snippet into Custom code snippet in the plugin settings. - Paste the
<noscript>snippet into Custom iframe code snippet. - Set the container ID. The plugin needs it even when your snippet has its own.
Replace the container ID and URL in the pasted snippets with placeholders, so that one snippet works with the plugin settings. The plugin replaces %1$s with the container ID, %2$s with the server container URL, and %3$s with the data layer name. If you leave the server container URL empty, %2$s is https://www.googletagmanager.com.
Head snippet:
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= '%2$s/gtm.js?id='+i+dl+'>m_auth=AUTH_TOKEN>m_preview=env-2>m_cookies_win=x';f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','%1$s');</script>
Noscript snippet:
<noscript><iframe src="%2$s/ns.html?id=%1$s>m_auth=AUTH_TOKEN>m_preview=env-2>m_cookies_win=x" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
Replace AUTH_TOKEN and env-2 with the values from your own snippet. Keep the 'script','dataLayer' part as it is, and the plugin swaps in a custom data layer name for you.
Things to know:
- The plugin passes snippets through PHP
sprintf(). A literal%in a snippet must be written as%%. Environment snippets normally have none, becausegtm_authandgtm_previeware plain letters, numbers,-and_. Check any snippet that has URL-encoded values. - The iframe snippet only gets the container ID and URL. Do not use
%3$sin it. - Use a different snippet on each site or environment. The plugin has no API for fetching the environment parameters, so you paste them by hand.
- On multisite, set the network snippets on the network settings screen. Site snippets apply to the site container.
Data Layer
GTM offers a dataLayer which allows you pass arbitrary data that can be used to modify which tags are added to your site.
This plugin adds some default information such as page author, tags and categories and provides a simple filter for adding in your own custom key/value pairs.
<?php add_filter( 'hm_gtm_data_layer', function( $data ) { $data['my_var'] = 'hello'; return $data; } ); ?>
Find out more about using the dataLayer variable here.
You can explore and view the dataLayer variables by previewing your container and using the overlay on your website.
Custom event tracking
In the block editor you can add event tracking to any block via the settings panel in the block sidebar. This calls dataLayer.push() with the event data specified.
All blocks are opted in to support this by default, but you can set block support to false with the following during block registration, or via block.json. For example:
register_block_type( 'my-plugin/my-block', [ 'supports' => [ 'gtm' => false, ], ) );
By default the plugin will look for elements with special data attributes in your markup and listen to the specified event to push events to the data layer.
The data attributes are:
data-gtm-on: enum [click|submit|keyup|focusin|focusout|mouseenter|mouseleave] The JS event to listen for, defaults to 'click'.data-gtm-event: string The name or action of the event eg. "play".data-gtm-category: string Optional group the event belongs to.data-gtm-label: string Optional human readable label for the event.data-gtm-value: number Optional numeric value associated with the event eg. product price.data-gtm-fields: string Optional extra data provided as encoded JSON.data-gtm-var: string Optionally override the default dataLayer variable name for this event.
Example:
<button data-gtm-on="click" data-gtm-event="play" data-gtm-category="videos" data-gtm-label="Featured Promotional Video" > Play video </button>
There is also a helper function to return these data attributes called get_gtm_data_attributes().
To deactivate custom event tracking use the following code:
add_filter( 'hm_gtm_enable_event_tracking', '__return_false' );