# Performance Analysis : NextJS Script Component for Google Analytics

## Introduction

One of the things when using the `NextJS` ecosystem that hasn't yet clicked for me is their `Script` component.

%[https://nextjs.org/docs/pages/building-your-application/optimizing/scripts] 

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](https://media.tenor.com/K9yYRKhI6OIAAAAC/steins-gate.gif align="center")

## 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**](https://developers.google.com/tag-platform/gtagjs/install#add_the_google_tag_to_your_website)**.**
    
    ```typescript
    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.
    
    ```typescript
    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.
    
    * [**NextJS Docs**](https://nextjs.org/docs/messages/next-script-for-ga#possible-ways-to-fix-it)
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698832524537/fca4fec4-150b-4cb4-b7ae-e58247def1ac.png align="center")
        
    * **next/third-parties -** [Google Tag Manager](https://github.com/vercel/next.js/blob/1caa58087a428666bb14d40dbc159b9a768b075d/packages/third-parties/src/google/gtm.tsx)
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698832605823/b6a4d252-55a1-4a40-87c3-f7dbcc7e6371.png align="center")
        

## Experiment - The Execution

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698831504846/e7b95bd9-ae10-4718-ac80-672a7c1a738b.png align="center")

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

### First Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698831908344/960b5536-7e54-44a5-b93c-b293504c72fc.png align="center")

### Second Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698831943457/bafe46b2-e489-48df-a340-44c8c4c933e1.png align="center")

### Third Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698831955171/a3e6dd91-2cf4-43cf-8257-4031985e12d1.png align="center")

### Fourth Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698831964737/ff384241-4d85-43ad-b4fb-788e3de4df18.png align="center")

### Fifth Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698831985295/1ad2157d-60aa-42c8-a9b2-e38b43259af2.png align="center")

### Sixth Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698831994392/725faad8-0430-4c81-9fda-cf17b22fd42c.png align="center")

### Seventh Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698832003188/dafdceea-a885-4cc8-be8a-c197bebf8c15.png align="center")

### Eight Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698832011099/d812b276-5679-4ab4-ba2b-6ac503df33d2.png align="center")

### Ninth Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698832029203/d7aa874c-c933-404d-b9fd-bb0403865724.png align="center")

### Tenth Run

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1698832050091/fbe2fd61-1480-448f-b3a9-c936ecf4a9e8.png align="center")

## Observations

From all the above runs, there were two interesting bits that I want to <mark>highlight </mark> 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

* **Gtag-NextJS -** [https://gtag-nextjs-script.vercel.app](https://gtag-nextjs-script.vercel.app)
    
* **Gtag-Standard -** [https://gtag-standard-script.vercel.app](https://gtag-nextjs-script.vercel.app)
    

### Webpagetest runs

* [https://www.webpagetest.org/video/compare.php?tests=231101\_BiDcS6\_7AR,231101\_BiDc6Q\_7AV](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_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_AiDcSM\_7YZ,231101\_BiDcMY\_813](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_BiDcP6\_81F,231101\_BiDcJ0\_81G](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_BiDcQ9\_821,231101\_BiDcNP\_822](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_AiDcTG\_80M,231101\_AiDcVS\_80P](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_BiDcXA\_82N,231101\_BiDcCV\_82P](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_BiDcH0\_830,231101\_AiDcPV\_818](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_AiDc2E\_81E,231101\_AiDcMT\_81F](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    
* [https://www.webpagetest.org/video/compare.php?tests=231101\_AiDcHT\_81S,231101\_BiDc8G\_83C](https://www.webpagetest.org/video/compare.php?tests=231101_BiDcS6_7AR,231101_BiDc6Q_7AV)
    

## 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**](https://web.dev/articles/script-evaluation-and-long-tasks#what_is_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 :)
