Performance Analysis : NextJS Script Component for Google Analytics

Have tinkered with JavaScript majorly | I like to solve problems on Stack Overflow, write blog articles, create a side project or do something creative.
Search for a command to run...

Have tinkered with JavaScript majorly | I like to solve problems on Stack Overflow, write blog articles, create a side project or do something creative.
No comments yet. Be the first to comment.
Introduction Alright, alright, alright !!! I have officially completed three years at Hashnode now. If you have been following my blog for a while, I have this ritual of documenting what all went in the past year at my job. My general process for do...

Introduction Well here we are reflecting on my time at Hashnode the previous year. I have officially completed two years at Hashnode and as a part of ongoing ritual where I document the experience, here is another one.And also, in first quarter of 20...

Introduction This article will touch upon scenarios that I have encountered while working at Hashnode where some code reviews helped us prevent future rework on the same issue by having a broader perspective. Code Review 0 The Problem Sometime back,...

Introduction You're scrolling through Twitter (I still like calling it that) or Medium and you get a nice view of the sidebar as it snaps to the bottom or top of the page if you try to scroll beyond its boundaries. We will re-create the same experie...

One of the things when using the NextJS ecosystem that hasn't yet clicked for me is their Script component.
I have been running some experiments on how I can leverage it for the Google Analytics script like gtag.js.

There are two types of deployment involved here:-
Gtag-Standard - This one uses the _document.tsx file where we are loading the standard script tags with the async attribute as recommended by Google.
import { Html, Head, Main, NextScript } from "next/document";
const Document = () => {
return (
<Html>
<Head>
{/* Global site tag (gtag.js) - Google Analytic */}
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-2VSQZMZCY6"
></script>
<script
dangerouslySetInnerHTML={{
__html: `window.dataLayer = window.dataLayer || []; function gtag()
{dataLayer.push(arguments)}
gtag('js', new Date()); gtag('config', 'G-2VSQZMZCY6');`,
}}
></script>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
};
export default Document;
Gtag-NextJS - This one uses the index.tsx file where we are loading the Script tags with the afterInteractive strategy.
import Script from "next/script";
const Home = () => {
return (
<main className="h-screen flex items-center justify-center">
<h1>Google Analytics Test</h1>
<>
<Script
id="google-analytics-init"
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || []; function gtag()
{dataLayer.push(arguments)}
gtag('js', new Date()); gtag('config', 'G-2VSQZMZCY6');`,
}}
/>
<Script
id="google-analytics"
src={`https://www.googletagmanager.com/gtag/js?id=G-2VSQZMZCY6`}
/>
</>
</main>
);
};
export default Home;
Note - Both of the deployments use the pages router setup.
I referred to the following two resources on how to load the gtag script.

next/third-parties - Google Tag Manager

I ran both of the deployments through the webpagetest's Visual comparison test.

This was done 10 times so that we get a good enough sample space.










From all the above runs, there were two interesting bits that I want to highlight specifically:-
CPU Busy Time - This has been consistently lower for the Gtag-Standard deployment.
Total Blocking Time (TBT) - This has been frequently lower for Gtag-Standard deployment but maybe with more runs this metric averages out to be the same for both the deployments.
Gtag-NextJS - https://gtag-nextjs-script.vercel.app
Gtag-Standard - https://gtag-standard-script.vercel.app
https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV
https://www.webpagetest.org/video/compare.php?tests=231101_AiDc17_7QY,231101_BiDc4K_7SX
https://www.webpagetest.org/video/compare.php?tests=231101_AiDcSM_7YZ,231101_BiDcMY_813
https://www.webpagetest.org/video/compare.php?tests=231101_BiDcP6_81F,231101_BiDcJ0_81G
https://www.webpagetest.org/video/compare.php?tests=231101_BiDcQ9_821,231101_BiDcNP_822
https://www.webpagetest.org/video/compare.php?tests=231101_AiDcTG_80M,231101_AiDcVS_80P
https://www.webpagetest.org/video/compare.php?tests=231101_BiDcXA_82N,231101_BiDcCV_82P
https://www.webpagetest.org/video/compare.php?tests=231101_BiDcH0_830,231101_AiDcPV_818
https://www.webpagetest.org/video/compare.php?tests=231101_AiDc2E_81E,231101_AiDcMT_81F
https://www.webpagetest.org/video/compare.php?tests=231101_AiDcHT_81S,231101_BiDc8G_83C
The whole point of this experiment was to evaluate if using NextJS Script tags, we would get better performance scores when loading Google Analytics JavaScript. But that didn't happen. More or less they are on par with the standard ones. The standard script tag delays the load event and the NextJS Script tag starts after the load event. In either case, I believe, Script Evaluation (of gtag.js) contributes to the TBT metric. I thought maybe loading the gtag script after the browser load event might result in lower TBT but that's not how it works.
Again, I am curious about the best way to load such analytics scripts. They are essential for users but contribute to poor scores for Mobile performance audits. Feel free to let me know if there are incorrect assumptions or gaps in how the above experiment was done.
Thank you for your time :)