(Next.js) Google Analytics 이식하기

호두파파·2022년 5월 23일
17

Next.js

목록 보기
6/6


들어서며

Google Analystic 등 웹(앱) 서비스를 이용하는 유저의 행동을 분석하는 마케팅 툴을 팀 프로젝트에 이식하게 되었다. 이중 내가 당담했던 툴들을 Google Analytics와 Google Adsence, 네이버 프리미엄 로그 분석이었다.

이 중 Google의 마케팅 툴을 이식하는 방법에 대해 포스팅을 진행하려 한다.


Google Analytics

구글 에널리스틱스는 웹(앱)에 대한 방문자의 데이터를 수집해서 분석함으로써 온라인 비즈니스의 성과를 측정하고 개선하는데 사용하는 로그분석 툴이다.

Next.js 프로젝트에 Google Analytics 이식하기

React 프로젝트에서 GA를 이식할때 많이들 react-ga라이브러리를 사용하고는 한다. 그러나, GA가 업그레이드 되면서 이전 GA의 베이스가 되었던 유니버셜 에널리스틱스 속성을 사용하려면 GA 계정에서 별도 세팅을 해주어야 한다. 이에 따라 GA 추적 코드 형식도 UA-XXXXXXXX-X에서 G-XXXXXXXXXX로 변경되었다.

유럽권에서 개인정보를 활용한 마케팅에 대해 규제를 진행하고 있어 향후 구글은 기존의 방식을 버리고 새로운 방식으로 마케팅 지원을 할 수 있도록 방향을 전환하고 있다. 따라서, 변화에 대응할 수 있도록 보수적으로 이식을 진행하고자 라이브러리 없이 GA를 이식하는 방향으로 작업을 진행했다.

Step 1. .env 파일에 GA 추적 코드 복사하기

.env.local

NEXT_PUBLIC_GOOGLE_ANALYTICS="code"

Step 2. _app.js 파일에 GA 추적 코드 추가하기

Next.js에서 태그나 태그 안에 들어갈 내용들을 커스텀할 때는 주로 _document.js파일을 사용한다. 아마 대부분 포스팅에서도 엘리먼트에 GA 관련 코드를 이식하기 위해 _document.js를 커스텀 하고 있을 것이다.

하지만, vercel/Next.js의 샘플 코드를 확인하면 _app.js에서 커스텀을 진행하고 있다.

직접 프로젝트에서 _document.js파일에 이식을 진행해보면 린트에서 다음과 같이 경고하는 것을 확인할 수 있다.

아마 이것은 Next 11이 릴리즈 되고나서 추가된 next/Script 때문인것으로 보이는데, Next.js 공식 홈페이지는 이에 관해서 이렇게 설명하고 있다.

Next.js는 SSR(ServerSideRendering) 구현하고 있는 프레임웍이고 서버단에서 실행되는 코드에서 window객체를 참고하는 코드를 실행하면 window is not defined란 에러를 띄운다.

관련 포스팅 보기

 // ga 관련 태그  
window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', '${gtag.GA_TRACKING_ID}', {
    page_path: window.location.pathname,
  });

따라서, 윈도우를 참조하고 있는 코드가 클라이언트 단에서 안정적으로 실행될 수 있도록 개선된 것으로 보인다.

_app.js와 next/Script

vercel에서 제안하는 샘플 코드는 아래와 같다.

import { useEffect } from 'react'
import Script from 'next/script'
import { useRouter } from 'next/router'
import * as gtag from '../lib/gtag'

const App = ({ Component, pageProps }) => {
  const router = useRouter()
  
  return (
    <>
      {/* Global Site Tag (gtag.js) - Google Analytics */}
      <Script
        strategy="afterInteractive"
        src={`https://www.googletagmanager.com/gtag/js?id=${gtag.GA_TRACKING_ID}`}
      />
      <Script
        id="gtag-init"
        strategy="afterInteractive"
        dangerouslySetInnerHTML={{
          __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', '${gtag.GA_TRACKING_ID}', {
              page_path: window.location.pathname,
            });
          `,
        }}
      />
      <Component {...pageProps} />
    </>
  )
}

next/Script

next/Script는 개발자들이 third-party 스크립트들의 로딩 우선순위를 설정할 수 있어 로딩 성능을 향상시킬 수 있다. next/Head_document.js에서만 사용할 수 있다면, next/Script_app.js에서만 위치시킬 수 있다.

next/Script를 어떻게 적용시킬 것인지(Strategy)에 대한 옵션 값들은 다음과 같다.

  • BeforeInteractive
    페이지가 상호작용하기 전에 가져오거나 실행되어야 할 필요가 있는 중요한 스크립트에 사용하는 옵션이다. 이 옵션이 적용된 스크립트들은 초기 HTML에 삽입되어 자체 번들 JavaScript가 실행되기 전에 실행된다.
  • AfterInteractive (default)
    태그 매니저나 분석툴처럼 해당 페이지의 상호작용 이후에 가져오고 실행되는 스크립트의 경우 사용한다. 이 스크립트들은 클라이언트 사이드에 삽입되어 hydration(html이 그려지고 난 후 이벤트 핸들러가 추가된 시점) 이후에 실행된다.
  • lazyOnload
    SNS 챗 같이 유휴 시간동안 기다릴 수 있는 스크립트의 경우 적용한다.

이외에도 다양하게 적용할 수 있도록 지원하고 있다. 공식문서 살펴보기

Step 3. 조회수 측정하기

  useEffect(() => {
    const handleRouteChange = (url) => {
      gtag.pageview(url)
    }
    router.events.on('routeChangeComplete', handleRouteChange)
    router.events.on('hashChangeComplete', handleRouteChange)
    return () => {
      router.events.off('routeChangeComplete', handleRouteChange)
      router.events.off('hashChangeComplete', handleRouteChange)
    }
  }, [router.events])

위 코드를 _app.js컴포넌트에 위치 시킴으로써 이벤트(유입, 이탈) 유형에 따라 조회수를 측정할 수 있다.


Bonus : Google의 다른 툴 추가 적용하기

만일 GA 뿐만 아니라, 구글 애드센스 등의 다른 툴을 프로젝트에 적용시켜야 한다면 마찬가지로 _app.js
next/Script 컴포넌트를 사용해 적용할 수 있다.

만일 GoogleAds를 붙여야 한다면, GA가 적용된 코드 최하단에 gtag('confing', 'Google ADS코드')를 삽입하면 적용 가능하다. 각 트래킹 코드를 분석해 관련 툴에서 로그를 파싱해 기록한다.

<Script
    id="gtag-init"
    strategy="afterInteractive"
    dangerouslySetInnerHTML={{
    __html: `
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', '${ga.GA_TRACKING_ID}', {
      page_path: window.location.pathname,
      });
      gtag('config', 'GOOGLE_ADS_TRACKINGCODE'); <-
      `,
    }}
  />  

마치며

GA는 마케터였던 과거에도 날 애먹이더니, 이번에도 쉽지 않았다. 여러가지 포스팅에서 이전의 방식으로 GA를 적용하도록 안내하고 있어 적잖히 혼동을 주었기 때문이다.

공식 문서에 안내하는 방식 외에도 GA 등 마케팅 툴을 적용하는 방식은 다양하다. 하지만, 향후 보수성과 퍼포먼스를 고려한다면 공식문서가 제안하는 방향으로 이식을 진행하는 것이 합리적인 결정이라는 생각이 들었다.

이번에도 다시 한 번 더 공식문서의 중요성을 확인했다.


참조 / 읽어보면 좋은 글들

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

2개의 댓글

comment-user-thumbnail
2022년 9월 1일

안녕하세요~ 글 잘 읽었습니다. 궁금한 점이 하나 있는데, 혹시 추적 코드를 const로 주는게 아니라 env에 넣어두는 이유가 있을까요?

1개의 답글