How to Install Google Tag Manager in WordPress Without Breaking It
Last month I audited a B2B lead-gen company running EUR 7,000 a month across Google and Meta. Their WordPress site had three GTM-related plugins installed. One was active, two were deactivated but still had leftover code in the database. The active plugin injected the container snippet inside <body> but never added the <noscript> fallback. Worse, a theme update two months earlier had silently disabled the plugin's output hook, so the container had not loaded at all for eight weeks. GA4 showed a 61 percent drop in sessions starting mid-April. Nobody noticed until I pulled the report.
This is not unusual. Across the WordPress tracking audits I have done in the past year, plugin-based GTM installs are the single most common source of silent failures. The plugin works on day one. Then a theme update changes the hook priority, a caching plugin strips the snippet, or a security plugin blocks inline scripts — and your tracking goes dark without a single error message.
There is a better way to install Google Tag Manager in WordPress. It takes ten minutes, survives theme changes, and does not depend on a third-party plugin that may not be maintained next quarter.
Where to Add Google Tag Manager Code in WordPress
Google's official installation instructions are explicit. The GTM snippet has two parts:
- A
<script>block that goes as high as possible inside<head>. - A
<noscript>iframe that goes immediately after the opening<body>tag.
Both are required. The <script> loads the container asynchronously. The <noscript> provides a fallback for environments where JavaScript is disabled or blocked.
The question every WordPress site owner hits: where to put Google Tag Manager code in WordPress when the theme does not expose <head> and <body> directly?
You have three options. I recommend the first. I tolerate the second. I actively discourage the third.
Option 1: Add the Snippet to Your Child Theme (Recommended)
This is the cleanest method and the one I use on every WordPress project. You edit two places in your child theme's functions.php — one hook for <head>, one for <body>.
// Add GTM <script> to <head>
add_action('wp_head', function () {
?>
<!-- Google Tag Manager -->
<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=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
<!-- End Google Tag Manager -->
<?php
}, 1);
// Add GTM <noscript> immediately after <body>
add_action('wp_body_open', function () {
?>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<?php
});
Replace GTM-XXXXXXX with your container ID. The wp_head hook with priority 1 ensures the script loads before other plugins' scripts. The wp_body_open hook fires right after <body>, exactly where Google says the <noscript> belongs.
Why a child theme matters
If you add this code to the parent theme's functions.php, the next theme update overwrites it. A child theme inherits the parent's functionality but keeps your customisations safe across updates. If you are running WordPress without a child theme, creating one takes five minutes and should be standard practice regardless of tracking.
The wp_body_open caveat
The wp_body_open hook was introduced in WordPress 5.2 (May 2019). If your theme predates that release, the hook will not fire. Check your theme's header.php for wp_body_open(). If it is missing, add <?php wp_body_open(); ?> immediately after <body> in your child theme's header.php.
Option 2: Use a Reputable Plugin (With Caveats)
If you cannot edit theme files — perhaps you are on a managed host that restricts file access, or your team has no developer — a plugin is the next best option.
Google's own Site Kit plugin supports Tag Manager integration and is maintained by Google. It is the only GTM plugin I recommend without reservation.
Third-party plugins like "Insert Headers and Footers" or "GTM4WP" work, but they introduce a dependency you do not control. I have audited sites where:
- A plugin update changed the hook priority, moving the GTM snippet below a consent banner script that had not loaded yet — breaking consent-aware tag firing.
- A plugin conflict caused the snippet to render twice, loading the container two times per page and doubling every GA4 event.
- A plugin was abandoned by its developer and became incompatible with a WordPress core update.
If you go the plugin route, verify the output after every WordPress core, theme, and plugin update. View source and confirm the GTM snippet appears exactly once in <head> and the <noscript> appears immediately after <body>. Thirty seconds of checking prevents a month of corrupted data.
Option 3: Hardcode Into header.php (Not Recommended)
Some guides tell you to paste the snippet directly into your theme's header.php. This works until the theme updates and overwrites your changes. Unless you are running a fully custom theme that you control and never update from a vendor, avoid this approach.
Why Most WordPress Google Tag Manager Plugins Fail Silently
The fundamental problem is that WordPress plugins operate within WordPress's hook system, and that system has no guarantee of execution order stability across updates. When you install Google Tag Manager in WordPress via a plugin, you are trusting that:
- The plugin hooks into
wp_headandwp_body_openat the right priority. - No other plugin or theme changes those priorities.
- The caching layer does not strip or defer the inline script.
- The plugin developer continues maintaining compatibility with WordPress core.
Any one of those can break. And when they do, Google Tag Manager stops loading — but WordPress does not throw an error. Pages render normally. You just stop collecting data.
This is what makes Google Tag Manager not working in WordPress so insidious. There is no visible failure. The symptom is a slow data decline that looks like a traffic drop, not a tracking outage. By the time someone investigates, weeks of data are gone.
If your GA4 numbers dropped unexpectedly and you cannot explain it from campaign changes, run through my Google Analytics Audit Checklist for GA4. Step one is always confirming the container actually loads.
Verifying the Installation
After you add the snippet — by any method — verify it works before you walk away.
1. View page source
Load any page on your site, right-click, and select "View Page Source." Search for GTM-. You should find the <script> block in <head> and the <noscript> block immediately after <body>. If either is missing, the installation is incomplete.
2. GTM Preview mode
In your GTM workspace, click Preview and enter your site URL. The Tag Assistant panel should connect and show container events firing. If it does not connect, the container is not loading — go back and check the snippet placement.
3. Check for duplicate containers
Search the page source for your container ID. It should appear exactly twice — once in the <script> and once in the <noscript>. If it appears four times, you have a duplicate installation. This is common when a plugin-based install and a manual install coexist.
4. Test through caching
Clear your site cache (via your caching plugin, CDN, or hosting panel), then reload. If the snippet disappears after a cache rebuild, your caching layer is stripping it — typically because it is deferring or combining inline scripts.
Caching and Security Plugins: The Hidden Conflicts
Two categories of WordPress plugins routinely interfere with GTM.
Caching plugins (WP Rocket, W3 Total Cache, LiteSpeed Cache) can defer, combine, or minify inline JavaScript. GTM's snippet is designed to load asynchronously on its own — it should not be deferred further or combined with other scripts. In WP Rocket, exclude googletagmanager.com from the "Delay JavaScript execution" feature.
Security plugins (Wordfence, Sucuri) sometimes implement Content Security Policy headers that block inline scripts or external script sources not on an allow-list. If your CSP does not include https://www.googletagmanager.com as a permitted script source, the browser silently blocks the container from loading.
| Plugin type | Common conflict | Fix |
|---|---|---|
| Caching | Defers or combines GTM inline script | Exclude googletagmanager.com from JS optimisation |
| Caching | Serves stale HTML missing the snippet | Purge cache after adding the snippet |
| Security | CSP blocks inline scripts | Add googletagmanager.com to script-src directive |
| Minification | Breaks GTM snippet syntax | Exclude inline GTM script from minification |
After Installation: What to Configure Inside GTM
Getting the container onto your WordPress site is step one. What you configure inside it determines whether your tracking actually works. At minimum, you need:
- A Google Tag (formerly GA4 Configuration Tag) with your Measurement ID. This sends pageviews to GA4 on every page load.
- Event tags for your key conversions — form submissions, purchases, demo bookings — fired by data layer pushes or GTM triggers that match the actual user actions.
- Consent Mode v2 defaults if you serve users in the EU or UK. Without these, your tags either fire without consent (a compliance risk) or do not fire at all (a data loss). I cover the full implementation in Google Consent Mode v2: Implementation Guide.
If your WordPress site runs WooCommerce, your data layer needs to push ecommerce events — view_item, add_to_cart, purchase — in the format GA4 expects. Without it, your conversion tags fire but send empty parameters, and revenue reports show zero even though orders are coming in.
When to Go Server-Side
A standard WordPress GTM installation runs entirely in the browser. That works, but browser-side tracking faces growing headwinds: Safari ITP caps JavaScript cookies at seven days, ad blockers affect roughly 32 percent of US internet users, and privacy regulations require consent before many tags can fire.
If your WordPress site drives meaningful ad spend, a server-side GTM container running on your own subdomain recovers data that the browser path loses. The web container sends events to your server container, which forwards them server-to-server, immune to ad blockers, with first-party cookies that persist beyond ITP's caps.
The Five-Minute Sanity Check
If you already have Google Tag Manager in WordPress and just want to confirm it is working, here is the fastest path:
- Open your site in Chrome. Press F12 to open DevTools. Go to the Console tab.
- Type
google_tag_managerand press Enter. If you see an object, GTM is loaded. If you seeundefined, it is not. - Go to the Network tab. Filter by
gtm.js. Reload the page. You should see exactly one request. Zero means no container. Two or more means duplicate loading. - Check the Elements tab. Search for your container ID. Confirm it appears in
<head>(the script) and after<body>(the noscript).
If any check fails, your tracking is broken and everything downstream — GA4 reports, ad platform conversions, automated bidding — is working with incomplete data. If that sounds like your situation, I can audit your full setup and tell you exactly what to fix.
FAQ
Do I need a plugin to install Google Tag Manager in WordPress?
No. The most reliable method is adding the GTM snippet directly to your child theme's functions.php using the wp_head and wp_body_open hooks. This approach survives theme updates, does not depend on third-party plugin maintenance, and gives you full control over snippet placement.
Where exactly should the Google Tag Manager code go in WordPress?
The GTM script block goes inside the head section as high as possible, and the noscript fallback goes immediately after the opening body tag. In WordPress, you achieve this by hooking into wp_head with a low priority number and wp_body_open in your child theme's functions.php file.
Why is Google Tag Manager not working on my WordPress site?
The most common causes are caching plugins stripping or deferring the inline script, theme updates overwriting the snippet, security plugins blocking the external script via Content Security Policy headers, or a plugin conflict that prevents the GTM hook from firing. Check your page source to confirm the snippet appears exactly once in the correct locations.
Can caching plugins break Google Tag Manager?
Yes. Caching plugins like WP Rocket and W3 Total Cache can defer, combine, or minify the GTM inline script, which prevents the container from loading correctly. Exclude googletagmanager.com from JavaScript optimisation settings and purge your cache after adding the snippet to ensure it renders properly.
Should I install GTM through a plugin or directly in the theme?
Directly in a child theme is more reliable because it removes the dependency on a third-party plugin that may not be maintained or may conflict with other plugins after updates. If you cannot edit theme files, Google's Site Kit plugin is the safest plugin option because Google maintains it directly.
Not sure your WordPress tracking is actually collecting data? Get in touch — I will audit your setup and tell you exactly what is broken and how to fix it.