Next.js에 google analytics 적용하기

date
Jun 17, 2022
slug
how-to-apply-ga-to-next.js
status
Published
tags
Next.js
summary
원리를 이해하며 next.js에 ga를 적용시켜보자 😎
type
Post
Updated At
Aug 1, 2022 01:18 AM
Created At
Jun 15, 2022 12:59 PM

개요

최근에 Next.js 기반의 개인 블로그, 개인 프로젝트를 진행하면서 google analytics를 적용해야 하는 경우가 생겨 이를 정리해본다.

Google Analytics에서 속성 적용하기

우선 아래의 사진과 같이 계정을 만들고 속성을 만든 다음 스트림을 만들어주고 스트림 URL에 본인웹사이트의 URL을 넣어주면 준비는 끝난다. 처음 만들었을 때에는 연동이 되어있지 않으니 당연히 활성화 상태가 아니다. 이때 측정 ID를 삽입해야하니 해당 ID를 기억하도록 하자.
notion image
태그하기의 대한 안내를 살펴보면 아래의 코드를 적용 시키면 된다고 나와있다.
<script async src="https://www.googletagmanager.com/gtag/js?id=[측정ID]"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', '[측정ID]');
</script>
해당 코드를 Next.js 프로젝트에 적용시켜보자 🙂

Next.js에서 태그 설정하기

gtag script를 불러오는 Scripts컴포넌트 만들기

아래와 같이 써드파티 스크립트를 적용해주는 Scripts 라는 컴포넌트를 만들어 준다.
import Script from 'next/script'
import BLOG from '@/blog.config'

const Scripts = () => (
  <>
    {BLOG?.googleAnalytics?.enable === true && (
      <>
        <Script
          src={`https://www.googletagmanager.com/gtag/js?id=${BLOG.googleAnalytics.config.measurementId}`}
        />
        <Script strategy="lazyOnload" id="ga">
          {`window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', '${BLOG.googleAnalytics.config.measurementId}', {
              page_path: window.location.pathname,
            });`}
        </Script>
      </>
    )}
  </>
)

export default Scripts
headscript를 추가할 수도 있지만 Next.js에서 제공하는 Script 라는 컴포넌트를 사용하였다. 해당 컴포넌트를 사용하면 strategy 속성을 통해 third-party script간의 우선순위를 설정해 주고, 로딩을 최적화 시켜줄 수 있다.
위의 코드에서는 첫 Script 태그에는 strategy를 afterInteractive로 설정해주었고 (default 값이다.), 두번째 Script 태그에는 lazyOnload으로 설정해 주었다. 각각의 속성에 대해 살펴보면 다음과 같다.
  • afterInteractive : 해당 스크립트를 client-side인 경우에 적용한다.
  • lazyOnload : 다른 모든 리소스가 적용이 되었을 때 적용한다.
이렇게 설정을 해줌으로써 gtag가 정의 된 뒤에 해당 gtag를 적용하는 스크립트를 실행하도록 우선순위를 설정해 줄 수 있다.

페이지 이동을 감지하는 Gtag컴포넌트 만들기

Next.js기반의 프로젝트는 SPA(single-page-application)이기에 페이지 이동에 대해서 GA에서 감지를 못한다. 그래서 임의적으로 페이지가 변경될 때 이벤트 핸들러를 정의해서 실행시켜 주어야한다.
components/Gtag.js
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import * as gtag from '@/lib/gtag'

const Gtag = () => {
  const router = useRouter()
  useEffect(() => {
    const handleRouteChange = url => {
      gtag.pageview(url)
    }
    router.events.on('routeChangeComplete', handleRouteChange)
    return () => {
      router.events.off('routeChangeComplete', handleRouteChange)
    }
  }, [router.events])
  return null
}
export default Gtag
useEffect hook을 통해 해당 컴포넌트가 로드될 때 router변화에 대한 이벤트 핸들러를 걸어준다.
libs/gtag.js
import BLOG from '@/blog.config'
export const GA_TRACKING_ID = BLOG.googleAnalytics.config.measurementId

// https://developers.google.com/analytics/devguides/collection/gtagjs/pages
export const pageview = url => {
  window.gtag('config', GA_TRACKING_ID, {
    page_path: url
  })
}

// https://developers.google.com/analytics/devguides/collection/gtagjs/events
export const event = ({ action, category, label, value }) => {
  window.gtag('event', action, {
    event_category: category,
    event_label: label,
    value: value
  })
}

_app.js 컴포넌트에 적용하기

만들어준 컴포넌트를 _app.js 안에 적용시켜주면 끝난다!
import 'prismjs/themes/prism.css'
import 'react-notion-x/src/styles.css'
import 'katex/dist/katex.min.css'
import '@/styles/globals.css'
import '@/styles/notion.css'
import BLOG from '@/blog.config'
import dynamic from 'next/dynamic'
import { LocaleProvider } from '@/lib/locale'
import Scripts from '@/components/Scripts'

const Gtag = dynamic(() => import('@/components/Gtag'), { ssr: false })

function MyApp({ Component, pageProps }) {
  return (
    <>
      <Scripts />
      <LocaleProvider>
        <>
          {BLOG.isProd && BLOG?.googleAnalytics?.enable === true && <Gtag />}
          <Component {...pageProps} />
        </>
      </LocaleProvider>
    </>
  )
}

export default MyApp
이때 한가지 주의해야 할 점은 Gtag 컴포넌트의 경우 client-side 인 경우에만 동작해야 하므로 (window객체에 gtag를 사용하기 때문) Next.js에서 제공하는 dynamic을 사용했다.

마치며

사실 인터넷에 나와 있는거 복붙 하면 끝나긴 하는데, 하나 하나 이해하는 걸 중요하게 여기는 나로써는 한번 쯤 정리 해볼 만한 내용 이였다고 생각한다. 웹 서비스의 경우 대부분 붙이기도 하고.