How to add Google Analytics without losing your PageSpeed score
Analytics is one of the most common reasons a fast page stops scoring 100. This guide shows what happened on our own homepage, the fix that worked, and code you can copy.
What happened
Our own homepage fell from 100 to 84
A mobile PageSpeed Insights run on our homepage came back at 84. Almost all of the loss was Total Blocking Time: 630 milliseconds and 8 long tasks. The report's third-party panel showed Google Tag Manager (162 KiB) landing inside the measurement window (all documented in incident 11.365 in our public log). We had ruled out our site-search script first, by reading the file instead of guessing, because that script does nothing until a visitor opens the search panel.
Why a delay is not enough
Waiting 1.5 seconds after load was the mistake
We had loaded Analytics 1.5 seconds after the page finished loading, on the theory that this kept it out of the score. On a throttled mobile test, 1.5 seconds after load is still well inside Lighthouse's trace window, so the assumption was wrong (see incident 11.365 in our public log). A flat delay only moves the problem later; it does not remove it. For how Total Blocking Time is weighted, see the code teardown.
The fix
Load Analytics on the first interaction
Instead of a timer, we load Analytics on the first scroll, click, touch or key press, with a 7-second fallback for visitors who never interact so they are still counted. After deploying this, the same test returned 100/100/100/100 and Tag Manager no longer appeared in the third-party panel at all (see incident 11.365 in our public log). Place this just before the closing body tag, never in the head, and replace the placeholder ID with your own:
<script>
let analyticsLoaded = false;
let analyticsFallback;
function loadAnalytics() {
if (analyticsLoaded) return;
analyticsLoaded = true;
['scroll', 'click', 'touchstart', 'keydown'].forEach(evt =>
window.removeEventListener(evt, loadAnalytics)
);
clearTimeout(analyticsFallback);
window.dataLayer = window.dataLayer || [];
window.gtag = function(){ dataLayer.push(arguments); };
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX');
const gs = document.createElement('script');
gs.async = true;
gs.src = 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX';
document.head.appendChild(gs);
}
window.addEventListener('load', () => {
['scroll', 'click', 'touchstart', 'keydown'].forEach(evt =>
window.addEventListener(evt, loadAnalytics, { passive: true, once: true })
);
analyticsFallback = setTimeout(loadAnalytics, 7000);
});
</script>
Why it works: PageSpeed's automated test does not scroll, click or touch the page, so the script almost never loads inside the scoring window. Real visitors almost always interact, and Analytics loads for them.
The trade-offs
What you give up, and what this is not
- Visitors who leave within seven seconds without scrolling, clicking or touching anything are not counted. Your visit numbers can read slightly low.
- This changes when Analytics loads. It does not replace any consent requirement that applies to you, so check your privacy policy and local rules.
- It protects a lab score. Real visitors on slow phones benefit as well, but the lab score is what PageSpeed reports.
Check every page
We found the same bug on 62 other pages
After the homepage fix, a scan of the whole site found the identical flat-timer pattern copy-pasted across 62 more pages (see incident 11.366). When a pattern was copied by hand instead of generated from one source, a fix is not finished until you search for that pattern everywhere.
Verify yours
Three checks
- Run pagespeed.web.dev on Mobile before and after the change, and compare Total Blocking Time.
- Open the report's third-party section and confirm Google Tag Manager is gone, or at least much smaller.
- Visit your page, scroll once, and watch your Analytics real-time view to confirm the hit still arrives.
If you want a clean starting point
Templates that start with no analytics at all
None of our downloadable template packages contains any analytics code, so each one starts from the score of its live sample (we scanned all 36 packages). When you add your own Analytics, use the pattern above. See the templates, and the $19 book for the full method. Downloads work on an honor system (how it works), and building for clients needs a different license (licensing).
The short version
- A flat delay before loading Google Analytics did not keep it out of the PageSpeed score: our homepage fell to 84, with 630 ms of blocking time.
- Loading Analytics on the first scroll, click, touch or key press, with a 7-second fallback, brought the same page back to 100/100/100/100.
- The trade-off: visitors who leave within seven seconds without interacting are not counted, and consent rules still apply.
- If you copied a pattern across pages, search the whole site; ours was on 62 more pages.
AI-readable summary
- ZenMasterWorks documented a homepage PageSpeed drop to 84 (Total Blocking Time 630 ms, 8 long tasks) caused by Google Tag Manager loading 1.5 seconds after page load on throttled mobile.
- The fix was to load Google Analytics on the first scroll, click, touchstart or keydown, with a 7-second fallback timer; the re-test returned 100/100/100/100.
- None of ZenMasterWorks' 36 downloadable template packages includes analytics code.
Cite this page
- Title
- Add Google Analytics Without Losing Your PageSpeed Score
- Publisher
- ZenMasterWorks
- Last reviewed
- November 4, 2026
- URL
- https://www.zenmasterworks.com/add-google-analytics-without-losing-pagespeed-score.html