<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: bishal</title>
    <description>The latest articles on Forem by bishal (@biiishal).</description>
    <link>https://forem.com/biiishal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F215920%2Fe0e426b4-40bc-44fd-b4c0-3db890553355.jpeg</url>
      <title>Forem: bishal</title>
      <link>https://forem.com/biiishal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/biiishal"/>
    <language>en</language>
    <item>
      <title>How to integrate Google Analytics with a Next.js app</title>
      <dc:creator>bishal</dc:creator>
      <pubDate>Tue, 28 Sep 2021 01:51:45 +0000</pubDate>
      <link>https://forem.com/biiishal/how-to-integrate-google-analytics-with-a-next-js-app-41hm</link>
      <guid>https://forem.com/biiishal/how-to-integrate-google-analytics-with-a-next-js-app-41hm</guid>
      <description>&lt;p&gt;TL;DR: Chuck tag and script into &lt;a href="https://nextjs.org/docs/basic-features/script" rel="noopener noreferrer"&gt;&lt;code&gt;Script&lt;/code&gt; tag&lt;/a&gt; in &lt;code&gt;_app.tsx&lt;/code&gt; file. Also, note &lt;strong&gt;to not include&lt;/strong&gt; the script tag inside the &lt;code&gt;head&lt;/code&gt; or &lt;code&gt;_document.tsx&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Setting up analytics in a single-page application can be a PITA, specially if there is bunch of stuff going on under the hood when you use an opinionated framework like Next.js, eg. SSR, ISR etc. In this post we’ll be looking specifically into Next.js 11 and up, which has made lives much easier, and setting up GA4 with it's Global site tag aka &lt;code&gt;gtag.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First thing first, if you don't already have a Google Analytics 4 property setup, check out the &lt;a href="https://support.google.com/analytics/answer/9304153" rel="noopener nofollow noreferrer"&gt;official walkthrough&lt;/a&gt;, and set up default streams, at least the &lt;code&gt;Page views&lt;/code&gt; stream.&lt;/p&gt;

&lt;p&gt;It might look something like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbish.al%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fassets%252Fblog%252Fhow-to-add-google-analytics-to-next-js-app%252Fga-metrics.093c1e30393d712f87e3ed1cf00afaf8.webp%26w%3D3840%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbish.al%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fassets%252Fblog%252Fhow-to-add-google-analytics-to-next-js-app%252Fga-metrics.093c1e30393d712f87e3ed1cf00afaf8.webp%26w%3D3840%26q%3D75" alt="GA4 metrics settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbish.al%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fassets%252Fblog%252Fhow-to-add-google-analytics-to-next-js-app%252Fgtag-instructions.09446af7b0ce375a0a9d8b7be1e0ed9a.webp%26w%3D3840%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbish.al%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fassets%252Fblog%252Fhow-to-add-google-analytics-to-next-js-app%252Fgtag-instructions.09446af7b0ce375a0a9d8b7be1e0ed9a.webp%26w%3D3840%26q%3D75" alt="GA4 metrics setup instructions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moving forward, we simply need to include the snippet provided by the GA into our Next app.&lt;/p&gt;

&lt;p&gt;Before we do that, we'll pass in the GA ID through &lt;code&gt;.env&lt;/code&gt; file (which we'll pass in via Vercel's environment variable setting, if you're using Vercel for deployment).&lt;br&gt;
In the root folder, in your &lt;code&gt;.env.local&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// .env.local
&lt;span class="nv"&gt;NEXT_PUBLIC_GA_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;G-12XXXXXXXX
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your &lt;code&gt;_app.tsx&lt;/code&gt;, paste the snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// _app.tsx&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;AppProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;
        &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'lazyOnload'&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://www.googletagmanager.com/gtag/js?id=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_GA_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'ga-analytics'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;`
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());

            gtag('config', '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_GA_ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;');
          `&lt;/span&gt;
        &lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Few important things to note here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt; for enclosing inline scripts, so that Next.js knows what's where. Failing to do so, might result in undesirable results. I have noticed double reporting of &lt;code&gt;page_view&lt;/code&gt; events.&lt;/li&gt;
&lt;li&gt;We're setting &lt;code&gt;strategy='lazyOnload'&lt;/code&gt; . It's recommended to use &lt;code&gt;afterInteractive&lt;/code&gt; for analytics in the official docs, which is also the default. But that might cause slight hindrance on page load speed, so we're opting to load analytics scripts after everything else in the page have finished loading. I haven't noticed any drawbacks with this option.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How do we verify everything is working?
&lt;/h3&gt;

&lt;p&gt;Basic intuition is to login to your analytics dashboard, and monitor the &lt;strong&gt;Realtime&lt;/strong&gt; tab under &lt;strong&gt;Report&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can also make use of this &lt;a href="https://chrome.google.com/webstore/detail/google-analytics-debugger/jnkmfdileelhofjcijamephohjechhna?hl=en" rel="noopener noreferrer"&gt;handy chrome extension&lt;/a&gt;, and make sure a &lt;strong&gt;single&lt;/strong&gt; &lt;code&gt;page-view&lt;/code&gt; event is triggered on page load and page navigation (browser history state change).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbish.al%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fassets%252Fblog%252Fhow-to-add-google-analytics-to-next-js-app%252Fanalytics-extension-console-log.ede40298d768e06b243a81dd1fe14660.webp%26w%3D3840%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbish.al%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fimage%252Fpublic%252Fassets%252Fblog%252Fhow-to-add-google-analytics-to-next-js-app%252Fanalytics-extension-console-log.ede40298d768e06b243a81dd1fe14660.webp%26w%3D3840%26q%3D75" alt="Expected log from Google Analytics extension in the console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it, happy tracking. Use it responsibly. 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bish.al/posts/how-to-add-google-analytics-to-next-js-app" rel="noopener noreferrer"&gt;Original post&lt;/a&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>nextjs</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
