GTM4WP – A Google Tag Manager (GTM) plugin for WordPress

توضیحات

Google Tag Manager (GTM) is Google’s free tool for everyone to manage and deploy analytics and marketing tags as well as other code snippets
using an intuitive web UI. To learn more about this tool, visit the official website.

This plugin places the GTM container code snippets onto your WordPress website so that you do not need to add them manually.
Multiple containers are also supported, and each container can have its own environment parameters, custom domain and custom path.

The plugin complements your GTM setup by pushing page meta data and user information into the so-called data layer.
Google’s official help pages include more details about the data layer.

PHP 8.0 and WordPress 6.3 are required to use this plugin.

GTM container code placement

The original GTM container code is divided into two parts:

The first part is a javascript code snippet that is added to the <head> section of every page of the website.
This part is critical to enable all features of GTM, and this plugin helps to place this part
correctly on your site.

The second part is an iframe snippet that acts as a failsafe/fallback should users’ JavaScript be disabled.
Google recommends – for best performance – to place this code snippet directly after the opening <body> tag on each page.

Albeit not ideal, it will work when placed lower in the code. This plugin provides a code placement option for the second code snippet.

If your WordPress theme is compatible with the additions of WordPress 5.2, then this plugin will place this second snippet in the right place.
Users of the Genesis theme, GeneratePress theme, Elementor, Oxygen Builder and Beaver Builder Theme will also have it placed correctly.
To utilize this, set the compatibility mode in the plugin options to off.

All other users can place this second code snippet using custom PHP code (the “Manually coded” option), or select the so-called “Footer” option
to add the code lower on the page (this is not the recommended way, but it will work).

Basic data included

  • post/page titles
  • post/page dates
  • post/page category slugs
  • post/page tag slugs
  • post/page author ID and name
  • post/page ID
  • post types
  • post format
  • post count on the current page + in the current category/tag/taxonomy
  • custom terms associated with any post type
  • logged in status
  • logged in user role
  • logged in user ID (to track cross device behavior in Google Analytics)
  • logged in user email address (both unhashed and SHA256 hashed values to be used with tracking)
  • logged in user creation date
  • site search data
  • site name and id (for WordPress multisite instances)
  • IP address of the visitor (please obtain the visitor’s explicit consent before using this)
  • post author data from PublishPress Authors, including co-authors and guest authors

Content & engagement data

Optional page variables that help with behavior tracking and Google Analytics 4 content grouping:

  • content word count and estimated reading time
  • last modified date and content age in days
  • comment count and comment status
  • page template, featured image presence, page hierarchy and sticky flag
  • primary category, detected from Yoast SEO or Rank Math
  • page language, detected from WPML or Polylang

Browser / OS / Device data

  • browser data (name, version, engine)
  • OS data (name, version)
  • device data (type, manufacturer, model)

Data is collected in the browser using User-Agent Client Hints and pushed as a gtm4wp.deviceData event.
Note that Safari and Firefox expose less detail than Chromium based browsers.

Media player events

Track users’ interactions with any embedded media:

  • YouTube
  • Vimeo
  • Soundcloud
  • HTML5 audio and video
  • Dailymotion
  • Mixcloud
  • Cloudflare Stream
  • Wistia
  • JW Player
  • VideoPress
  • Spotify
  • Twitch

You can choose to fire data layer events when the media player loads, when the media is played, when it is paused or stopped,
and optionally when the user reaches 10, 20, 30, …, 90, 100% of the media duration. Each event also populates Google Tag
Manager’s built-in Video variables (Video Status, Video URL, Video Title, Video Provider, Video Duration, Video Current Time,
Video Percent, Video Visible).

Tracking is supported for embedded media using the built-in oEmbed feature of WordPress, as well as most other media plugins
and copy/pasted embed codes. Players inserted into the page after it has loaded (for example in a popup, a lightbox or via
AJAX) can also be tracked by turning on the optional “Track dynamically inserted players” setting.

Tag restrictions: allowlist & blocklist Tag Manager tags, triggers and variables

To increase website security, you have the option to allowlist or blocklist tags, triggers and variables.
You can prevent specific tags from firing, or prevent the use of certain variable types, regardless of your GTM setup.

If the Google account associated with your GTM account is compromised, an attacker could easily
execute malware on your website without accessing its code on your hosting server. By blocklisting custom HTML tags,
custom JavaScript variables and sandboxed scripts (custom tag and variable templates), you can secure the Tag Manager container.

Integration

Google Tag Manager for WordPress integrates with several popular plugins. More integrations to come!

  • Contact Form 7: fire an event when a form is submitted with any result (mail sent, mail failed, spam detected, invalid input, submission aborted or terms not accepted). Optionally push the Google Analytics 4 recommended form events (form_start, form_submit, generate_lead) as well
  • WooCommerce:
    • Implementation of GA4 E-commerce
    • Support for the Cart, Checkout, Mini-Cart, Product Collection and cross-sell blocks, not only the classic shortcode based pages
    • Enhanced Conversions user data on the purchase event for Google Ads
    • Compatibility with High Performance Order Storage (HPOS)
    • Does not support promotions, since WooCommerce does not have such a feature (yet)
    • Does not support refunds
  • CheckoutWC: optional support for its multi step checkout template
  • PublishPress Authors: co-author and guest author data in the page variables
  • AMP: load your AMP container on the AMP version of your pages
  • Google Consent Mode v2: fire the “default” command with specific consent flags to integrate with non-certified Consent Management Platforms (CMPs) and plugins
  • Cookiebot: use automatic cookie blocking mode if needed
  • Axeptio: load the Axeptio SDK and push every consent change into the data layer
  • CookieYes: push a data layer event whenever the visitor’s consent changes

Server side containers

If you are using a server side container,
you can enter your custom domain name and custom path to load gtm.js from there. Both can be set per container, so you can mix
server side and standard containers on the same site.

Cache-safe data layer

(experimental, off by default)

On sites using a full page cache (LiteSpeed, WP Rocket, Varnish, Cloudflare APO), the HTML generated for one visitor is served
to everyone else as well. Any visitor specific value written into the data layer would therefore leak to other visitors – the
classic example being a page cached while an editor was logged in, then served to anonymous visitors with that editor’s email
address and role still in the data layer.

When this option is enabled, no visitor or session data is written into cacheable HTML at all. Those values are delivered in the
browser instead, under the same data layer variable names, so your existing Google Tag Manager setup keeps working.

Export & import your settings

You can export all plugin settings into a JSON file and import them on another site, which makes it easy to roll out the same
configuration across several websites. Imported files are treated as untrusted and every value is validated before it is stored.

Exclude specific user roles from being tracked

You can set which user roles need to be excluded from tracking when a user with that role visits the frontend. This will completely disable the container code for that user.

Staging and development sites

The container can be limited to production environments only, so a cloned or staging copy of your site does not send data into
your production Google Tag Manager container. This relies on the WP_ENVIRONMENT_TYPE setting of WordPress.

For developers

Version 2.0 is a complete object oriented rewrite. Every feature is a module, and third party plugins can register their own
modules through the gtm4wp_register_modules action. All public template functions, filter and action names, wp-config constants
and the option storage key of the 1.x versions are unchanged, so existing integrations keep working.

عکس‌های صفحه

نصب

  1. Upload duracelltomi-google-tag-manager-for-wordpress to the /wp-content/plugins/ directory
  2. Activate the plugin through the ‘Plugins’ menu in WordPress
  3. Go to Settings / Google Tag Manager and enter your Google Tag Manager container ID and set additional options

سوالات متداول

How can I …

Tutorials for various Google Tag Manager settings and implementation are available on the plugin’s website:
https://gtm4wp.com/setup-gtm4wp-features

PayPal / 3rd party payment gateway transactions in WooCommerce are not being tracked in Google Analytics

PayPal and some other 3rd party payment gateways do not redirect users back to your website after a successful transaction by default.
They offer a route back for your customer, but it can happen that users close the browser before arriving at your thank you page
(also known as the order received page). This means that neither Google Analytics tags nor any other tags have a chance to fire.

Enable auto-return in your payment gateway settings. This will instruct the gateway to show a quick info page after payment
and redirect the user back to your site. This will improve the accuracy and frequency of tracked transactions.

Purchase event is not tracked with WooCommerce

This can happen if you are using a 3rd party plugin that alters the default order received page in a way that does not use
WooCommerce’s integration hooks. Either stop using that plugin, or ask its authors to mimic the behavior of the default order
received page more closely by supporting the woocommerce is_order_received_page function and the woocommerce_thankyou action.

Since version 2.0 the plugin also offers two settings that work around this without changing the 3rd party plugin: “Custom order
received (thank-you) page” fires the purchase event on a bespoke confirmation page, and “Reliable purchase tracking” emits a
missed purchase event on the next page the customer views in the same browser session. Both are de-duplicated, so an order is
never counted twice.

Why isn’t there an option to blocklist tag/variable classes

Although Google recommends blocklisting tags and variables using classes, people struggle to know
which tags and variables get affected. Therefore I opted for individual tags and variables rather than classes
on the tag restriction tabs.

Regarding variables: ensure they are not part of any critical tags, as blocklisting such variables will render those tags useless.

How can I track scroll events in Google Tag Manager?

Google Tag Manager supports basic scroll depth tracking based on percentage or pixels natively. Add a Scroll Depth
trigger in your container and use it to fire your Google Analytics 4 and/or Google Ads remarketing/conversion tags.
(The plugin’s own scroll tracking feature was removed in 2.0 in favor of this built-in GTM functionality.)

I use a page cache. Can visitor data leak between visitors?

Yes, this is a real risk with any full page cache, and it is not specific to this plugin: the HTML generated for one visitor is
stored and served to everyone else. If visitor specific values (email address, user role, IP address) are written into the data
layer, the cached copy will contain the values of whoever happened to trigger the caching.

Turn on the “Cache-safe data layer” option to avoid this. With it enabled, no visitor or session data is written into cacheable
HTML; those values are delivered in the browser instead, under the same data layer variable names.

Why does the plugin load several separate JavaScript files instead of one?

Each tracking feature (WooCommerce, each media player, Contact Form 7, device data, etc.) is its own small
JavaScript file, and the plugin loads only the files a page actually needs – the YouTube tracker, for instance,
loads only on pages that embed a YouTube video, and with the “defer” strategy so it never blocks rendering.
Those files are already minified by the plugin’s build.

Merging several files into one is intentionally left to a caching / performance plugin (WP Rocket, Autoptimize,
LiteSpeed Cache, etc.), which can combine scripts across your whole site and in a way that suits your hosting and
HTTP setup. On modern HTTP/2 hosting, many small conditionally-loaded files usually perform as well as one combined
file. (1.x combined its own scripts; 2.0 delegates this.)

نقد و بررسی‌ها

29 اکتبر 2025
We've been using GTM4WP for all of our clients websites and it's been super reliable. The eCommerce tracking integration has been a huge time saver for us. Huge thank you for this plugin Thomas Geiger!
13 آگوست 2025 1 پاسخ
I am writing this review to save other developers and site owners the immense amount of time I have just lost. I needed to implement standard GA4 e-commerce tracking on a professional WordPress/WooCommerce site. Based on its popularity and countless recommendations, I chose GTM4WP as the solution to generate the required dataLayer. Unfortunately, after days of intensive, professional-level debugging, I discovered that the plugin was completely non-functional in my specific—yet very common—environment. The plugin failed at its two most essential tasks: GTM Snippet Injection: The plugin's most basic feature—injecting the GTM container script into the website's <head> and <body>—did not work at all. The script was simply not present. I had to bypass this functionality entirely and inject the code manually using another method (Code Snippets) just to get our GTM container to load. E-commerce dataLayer Generation (The Deal-Breaker): This is the primary reason anyone uses this plugin. After successfully loading our GTM container manually, I ran a full test purchase. By analyzing the GTM debug mode and the site's dataLayer object, I can confirm that GTM4WP completely failed to generate the purchase event and its corresponding ecommerce object on the WooCommerce order confirmation page. It produced absolutely nothing. My Technical Environment (Please read this before you install):To help others, here is the stack where the plugin failed. This is likely the source of the conflict: CMS: WordPress E-commerce: WooCommerce Theme: Hello Elementor (using a child theme) Page Builder: Elementor Pro Key Detail: I am using Elementor Pro to customize the WooCommerce page templates, including the "Thank You" / "Order Received" page. Conclusion: My conclusion is that GTM4WP is fundamentally incompatible with themes or page builders that override default WooCommerce templates—a standard practice for virtually any custom-designed website today. Because it cannot handle this common scenario, the plugin proved to be entirely useless for my project. While it may work on simple sites with basic, unmodified themes, it is not a reliable solution for professional, customized builds. The time and effort wasted diagnosing this incompatibility were substantial. I cannot recommend this plugin and strongly advise users with a similar tech stack to seek a manual implementation from the start.
10 مارس 2025
Em vários sites que o plugin está instalado, após alguma atualização, o menu mobile de alguns sites não abre.
2 دسامبر 2024
I’m disappointed with the support for this plugin. I submitted a question over a week ago, but I have yet to receive any response from the support team. While the plugin itself may work fine, having reliable support is critical, especially when issues arise. Unfortunately, the lack of responsiveness has made it difficult to trust this plugin for long-term use. I hope the team improves their support response time in the future.
خواندن تمامی 154 نقد و بررسی‌

توسعه دهندگان و همکاران

“GTM4WP – A Google Tag Manager (GTM) plugin for WordPress” نرم افزار متن باز است. افراد زیر در این افزونه مشارکت کرده‌اند.

مشارکت کنندگان

“GTM4WP – A Google Tag Manager (GTM) plugin for WordPress” به 13 زبان ترجمه شده است. با تشکر از مترجمین برای همکاری و کمک‌هایشان.

ترجمه “GTM4WP – A Google Tag Manager (GTM) plugin for WordPress” به زبان شما.

علاقه‌ مند به توسعه هستید؟

کد را مرور کنید، مخزن SVN را بررسی کنید، یا از طریق RSS در گزارش توسعه مشترک شوید.

گزارش تغییرات

2.0.2

  • Updated: tested with WooCommerce 11.1.
  • Fixed: a product category or brand name containing an ampersand reached the data layer as “Shirts & Ties” rather than “Shirts & Ties”, which is what GA4 then reported. WordPress encodes term names when they are saved, and the plugin now decodes that once when it reads the name.
  • Fixed: item_id, sku and the dynamic remarketing id are now always strings. A product with no SKU falls back to its numeric id, and that fallback was written into the data layer as a number while the same fields are strings on every product that has a SKU. Check your GTM setup if a trigger or variable compares one of those fields against a number.

  • Fixed: the begin_checkout event was missing on stores where WooCommerce reports the checkout page as the cart page as well, which happens when a plugin or a theme forces that decision or when a cart shortcode is left in the checkout page content. Such a checkout page pushed view_cart and begin_checkout never fired anywhere. The checkout is now decided first, so a page reported as both is treated as the checkout page. The order-received page is recognized ahead of both on both halves as well: on such a store the thank-you page used to be taken for the cart page by the block tracker, which loaded there in its cart context in place of the regular tracker.

  • Fixed: add_to_cart and remove_from_cart never fired on a store whose product and cart blocks are built on the WordPress Interactivity API, the newer form of the WooCommerce blocks. Product pages now report the add once WooCommerce confirms that the item reached the cart, and cart changes made anywhere else are read back from the WooCommerce Store API and reported the same way as on a store using the older blocks. Variable products are covered as well: the interactive form publishes no variation data the plugin could read, so the event is completed from the cart line the add creates, which carries the data of the variation itself.
  • Fixed: a GTM4WP_HARDCODED_* value in wp-config.php that ends in a newline character – typically an untrimmed file read feeding the define() – is now rejected and named in the existing admin notice, like any other malformed value. Previously a gtm_auth/gtm_preview value with a trailing newline passed validation, the newline reached the container loader script and broke the whole block, so the container silently did not load with nothing pointing at wp-config. A container ID with a trailing newline used to be silently repaired and kept working; it is now reported the same way instead – remove the stray newline from the define() and the override applies again.
  • Fixed: a page whose author cannot be resolved no longer takes the whole page down with a critical error when PublishPress Authors is active. PublishPress reports such an author as no author at all, which happens when the author’s user account has been deleted, and the plugin passed that straight into the code reading the author name and ID, where it ended in a fatal error. The WooCommerce My Account page is the one most likely to hit it, since it is often the page nobody keeps an author on. An author that cannot be resolved is now skipped, so the page renders and the author variables are simply left out of the data layer, and a post that has one real author next to an unresolvable one is treated as having a single author.

2.0.1

  • Fixed: on a block-based store, opening the Cart page pushed add_shipping_info and add_payment_info into the data layer with no interaction, and both events then fired again on the Checkout page. The block tracker told the two pages apart by the presence of the WooCommerce payment data store, which WooCommerce registers on the Cart page as well; the Cart and Checkout pages now each receive their own context and the checkout-step events fire only on the Checkout page.
  • Fixed: a blank settings screen no longer stays silent about why it is blank. Some ad and privacy blocker filter lists block everything under the plugin folder, including the file that builds the settings screen in the browser, which left the settings page empty with no explanation. A static notice now appears after a few seconds whenever the settings app could not start, explaining the most likely cause and the workaround (pause the blocker for the admin area of the site, or add an exception for it).

2.0.0

Major rewrite of the plugin. Please read the announcement post on gtm4wp.com before upgrading. This section is a summary; wordpress.org truncates a changelog after 5,000 words, so the complete list of 2.0.0 changes with every detail lives in the changelog on GitHub: https://github.com/duracelltomi/gtm4wp/blob/master/CHANGELOG.md

  • Changed: complete object-oriented rewrite. Every feature is a module that third-party plugins can extend. All public template functions, filter and action names, wp-config constants and the options storage key are unchanged, so existing integrations keep working.
  • Changed: minimum requirements raised to PHP 8.0 and WordPress 6.3.
  • Added: modern React-based settings screen with left pane navigation, tabbed option groups, option search, inline validation, a help link on every option, bookmarkable addresses and settings export and import.
  • Added: every Google Tag Manager container ID has its own environment parameters, custom domain and custom path; a production-only kill switch for staging copies; validation of the hard-coded wp-config constants with a warning that names the wrong one.
  • Changed: the tag restriction list is written under the documented gtm.allowlist / gtm.blocklist keys, the entity list is refreshed from Google’s documentation, and blocklist mode no longer blocks every tag.
  • Added: cache-safe data layer mode for sites behind a full page cache, with the visitor specific values fetched separately.
  • Changed: GA4 e-commerce tracking reworked for WooCommerce: reliable purchase tracking, custom order received page, order statuses that trigger the purchase event, list attribution across the funnel, block cart and checkout support, Store API data for the block trackers, and numeric-looking text values no longer turned into numbers.
  • Added: an Axeptio consent management platform integration and a CookieYes consent bridge; the WebToffee v2.x integration is deprecated. Media events cover more embedded players, and a player’s script is requested only on pages that contain one of its embeds.
  • Removed: the weather and geo data features and the scroll tracking feature (use the built-in Scroll Depth trigger of Google Tag Manager instead). Browser, OS and device data is now collected in the browser with User-Agent Client Hints, which replaces the bundled WhichBrowser library.
  • Deprecated: the “YouTube video events” option (Google Tag Manager ships a native YouTube Video trigger) and the $gtp4wp_plugin_url, $gtp4wp_plugin_basename and $gtp4wp_script_path global variables, which will be removed in 2.1.

1.22.5

A maintenance release for the 1.x line. 1.22.4 was intended to be the last one before GTM4WP 2.0; this release exists because the fixes below are worth shipping to 1.x users rather than holding for 2.0.

  • Fixed (security): hardened how the hidden product-data attribute is built for WooCommerce product lists and cart remove links, so that no product field value can affect the surrounding HTML. Certain values were not guaranteed to stay inside the attribute.
  • Fixed: when a custom X-Forwarded-For header is configured as the visitor IP source, all entries of the header are now evaluated. Only the first entry was ever considered, because the remaining ones were not trimmed of the space that follows each comma and therefore failed IP validation.
  • Fixed: the custom visitor IP header name is now validated in full. The check accepted any value that contained at least one valid character, so an invalid header name passed validation and was then simply never found. Setups with a working header name are unaffected.

1.22.4

  • Fixed: hardened how values are encoded into the data layer and into inline script blocks. Script blocks are no longer HTML entity decoded after sanitization, and every value written into a script context is now JSON encoded with the full set of hex escaping flags. Thanks cyn
  • Fixed: nonce attribute should not be sanitized. Thanks oxyc
  • Fixed: avoid warnings when saving settings. Thanks mircobabini
  • Fixed: only float number is returned in JavaScript processing. Thanks gkipouros
  • Updated: only load plugin files on frontend or on admin when the admin user has sufficient permissions.
  • Updated: WooCommerce 10.4+ compatibility – the checkout inline script no longer uses the deprecated wc_enqueue_js() function. The old function is still used as a fallback on setups where the tracker script is loaded in the page head.
  • Updated: WordPress and WooCommerce compatibility.
  • Deprecated: geo data (ipstack.com) and weather data (OpenWeatherMap) integrations. They still work in this version but will be removed in GTM4WP 2.0. There is no direct replacement: collect this data in Google Tag Manager or with a dedicated service instead.
  • Deprecated: scroll tracking. It still works in this version but will be removed in GTM4WP 2.0. Use the Scroll Depth trigger built into Google Tag Manager instead.
  • Deprecated: the “Custom tag/variable templates” blacklist option, plus the Universal Analytics and Mouseflow entries of the tag blacklist. These will be removed in GTM4WP 2.0.
  • Added: a dismissable admin notice announcing the upcoming GTM4WP 2.0 release. If your site uses one of the deprecated features above, the notice names it.

1.22.3

  • Fixed: when timeout for the select_item event with WooCommerce is set to 0, plugin does not halt the browser from loading the product page
  • Fixed: properly reading timeout for select_item eventCallback

1.22.2

  • Fixed: purchase event was not fired when is_order_received_page() WooCommerce tag was not supported by the template and the fallback method had to activate.

1.22.1

  • Fixed: yet another fix to the purchase tracking. Thanks Khnaz35

Older releases are listed in the full changelog on GitHub: https://github.com/duracelltomi/gtm4wp/blob/master/CHANGELOG.md