Performance Analysis : NextJS Script Component for Google Analytics

Performance Analysis : NextJS Script Component for Google Analytics

ยท

3 min read

Introduction

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.

Anime Mad Scientist GIFs | Tenor

Experiment - The Setup

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.

Experiment - The Execution

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.

First Run

Second Run

Third Run

Fourth Run

Fifth Run

Sixth Run

Seventh Run

Eight Run

Ninth Run

Tenth Run

Observations

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.

Resources

Deployment Urls

Webpagetest runs

Conclusion

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 :)

ย