WP Rocket’s Delay JavaScript execution holds scripts until the visitor’s first interaction: a scroll, a click, a key press, a touch. It is genuinely good for Core Web Vitals. It is also, by default, applied to your analytics tag.
The consequence is that anyone who lands on a page and leaves without interacting is never recorded. No pageview, no session. Your bounced traffic, which is most traffic, simply does not exist in the reports.
Why it survives testing
This is the part that makes it dangerous. When you test the tag yourself you scroll, you click around, you open DevTools. You interact. So the tag fires, the real-time report lights up, and everything looks correct.
The tag is genuinely installed. It genuinely works. It just does not work for the visitors who matter most for measuring reach.
How to check in ten seconds
View source on any page and find the Google tag. If WP Rocket is delaying it, the script will not look like a normal script:
<!-- delayed -->
<script type="rocketlazyloadscript" async
data-rocket-src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX">
<!-- correct -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX">
type="rocketlazyloadscript" and data-rocket-src mean the browser will not execute it until the visitor does something.
The fix
Add the analytics patterns to Delay JavaScript execution → Excluded JavaScript files in WP Rocket’s File Optimization tab:
googletagmanager.com
gtag
dataLayer
All three matter. The first covers the external gtag/js request, the second and third cover the inline configuration snippet that defines gtag() and pushes to dataLayer. Excluding only the external file leaves the inline config delayed, and the tag still does not fire on load.
Clear the cache, reload, and confirm the script now renders as plain <script async src>.
The trap on the way out
If you have custom tracking code of your own, for example an event fired on a form submission, you may be tempted to exclude that file too. Be careful.
We did exactly that, and it made things worse. Our script depended on jQuery, and jQuery was still delayed. Excluding only our script meant it now ran before jQuery existed, hit its if (!window.jQuery) return; guard, and bound nothing at all. Silently. It looked correct in review and tracked zero events.
Either exclude the whole dependency chain, or exclude none of it and have your script wait for what it needs:
function bindWhenReady(attempt) {
attempt = attempt || 0;
if (window.jQuery) { /* bind here */ return; }
if (attempt > 300) return;
setTimeout(function () { bindWhenReady(attempt + 1); }, 100);
}
Submitting a form is itself an interaction, so a tracking script for form submissions loses nothing by being delayed along with everything else.
What this costs you
There is no way to recover the missing data. Sessions that were never recorded are gone. If this has been live for a year, your year-on-year comparison is against a number that was always wrong, and fixing it will look like a sudden traffic spike that you will then have to explain.
Worth checking on every WP Rocket site you run, not just the one you are looking at.