Next.js 14(app router)에서 GA4, GTM, @next/third-parties 사용하기

ClydeHan·2024년 6월 27일
9

들어가며

Next.js 14에서 GA4 사용하기

외주 프로젝트의 클라이언트가 페이지 내 요소별 클릭의 집계를 위해 GTM와 GA4를 사용해달라고 요구했다. 대부분의 자사 웹이 있는 기업들은 데이터 통계를 위하여 GA4와 GTM을 필수적으로 사용하고 있다.

이번 포스트에서는 Next.js 14(App Router)에서 Google Analytics 4(GA4)와 Google Tag Manager(GTM)를 사용하는 방법에 대해 주로 다룰 것이다. GA4와 GTM에 대해 자세히 설명하려면 글이 꽤 길어지기 때문에, 이번에는 각 키워드가 무엇인지 간단히 짚고 넘어가고 다음 포스트에서 하나씩 집중적으로 다룰 예정이다.

🚨 이번 포스트도 마찬가지로 코드 예시의 클라이언트와 관련된 코드 조각들은 생략한다.

💡 Next.js 14의 app router를 기준으로 설명과 코드 예시를 작성했으며, GA4, GTM 플랫폼 가이드, 디버깅은 이번 포스트에서 다루지 않는다.


GA4, GTM 개요

GA4 로고

Google Analytics 4(GA4)

GA4는 웹사이트와 앱에서 사용자 행동을 추적하고 분석하는 최신 버전의 Google Analytics이다. 이벤트 기반 데이터 모델을 사용하여 사용자 상호작용을 더 세부적으로 추적하며, 웹과 앱의 데이터를 통합하여 분석할 수 있다.

GTM 로고

Google Tag Manager(GTM)

GTM은 다양한 태그(예: Google Analytics, Facebook Pixel 등)를 한 곳에서 관리하고 배포할 수 있는 태그 관리 시스템이다. 이를 통해 개발자 없이도 마케팅 팀이 직접 태그를 추가하거나 수정할 수 있다.


서드 파티 라이브러리(@next/third-parties)

서드 파티 라이브러리 npm 트렌드

📈 @next/third-parties(서드 파티 라이브러리)는 꾸준히 다운로드되며 지속적으로 업데이트되고 있다.

개념

@next/third-partiesNext.js 애플리케이션에서 다양한 서드 파티 라이브러리를 쉽게 통합하고 성능을 최적화할 수 있도록 도와주는 라이브러리이다. 이를 통해 개발자는 Google Analytics, Google Tag Manager 등의 서드 파티 도구를 간편하게 설정할 수 있다.

💡 서드 파티(Third-Party)
서드 파티는 "제3자"를 의미한다. 소프트웨어 개발에서 서드 파티 라이브러리는 애플리케이션 개발자가 아닌 다른 개발자나 회사가 만든 외부 라이브러리를 의미한다. 예를 들어, Google Analytics, Facebook SDK, YouTube API 등이 있다.


주요 기능

  • 최적화된 로드: 성능을 저하시키지 않는 방식으로 서드 파티 스크립트를 로드한다.

  • 간편한 통합: 컴포넌트 형태로 제공되어 쉽게 서드 파티 기능을 추가할 수 있다.

  • 일관된 사용 방식: 다양한 서드 파티 라이브러리를 일관된 방식으로 통합한다.


서드 파티 패키지가 필요한 이유

  • 복잡성 감소: 서드 파티 라이브러리는 다양한 서드 파티 스크립트를 관리하는 복잡성을 줄여준다. 각 스크립트의 로드 및 초기화를 단순화하여 개발자의 부담을 덜어준다.

  • 성능 최적화: 서드 파티 스크립트의 로드 방식을 최적화하여 페이지 로드 속도를 개선한다. 예를 들어, 필요한 경우에만 스크립트를 로드하거나 지연 로딩을 사용한다.

  • 일관된 코드베이스: 다양한 서드 파티 라이브러리를 일관된 방식으로 통합하여 코드의 가독성과 유지보수성을 높인다.

  • 편리한 관리: 서드 파티 라이브러리를 사용하면 새로운 서드 파티 도구를 쉽게 추가하거나 기존 도구를 업데이트할 수 있다.


제공하는 컴포넌트

Google Tag Manager

Google Tag Manager를 페이지에 추가하여 다양한 태그와 이벤트를 관리할 수 있다.

  • GoogleTagManager 컴포넌트: GTM 스크립트를 자동으로 로드하고 초기화한다.
  • sendGTMEvent 함수: 사용자 상호작용 이벤트를 GTM 데이터 레이어에 전송한다.

Google Analytics

Google Analytics4를 페이지에 추가하여 사용자 행동을 추적하고 분석할 수 있다.

  • GoogleAnalytics 컴포넌트: GA4 스크립트를 자동으로 로드하고 초기화한다.
  • sendGAEvent 함수: 사용자 상호작용 이벤트를 GA 데이터 레이어에 전송한다.

YouTube Embed

YouTube 영상을 페이지에 임베드하여 빠르게 로드하고 표시할 수 있다.

  • YouTubeEmbed 컴포넌트: YouTube 영상을 지연 로딩 방식으로 임베드한다.

Google Maps Embed

Google Maps를 페이지에 임베드하여 위치 정보를 표시할 수 있다.

  • GoogleMapsEmbed 컴포넌트: Google Maps 임베드를 지연 로딩 방식으로 추가한다.

세팅하기

1. 설치

제일 첫번째로 third-parties 라이브러리를 설치한다.

npm install @next/third-parties@latest

2. 설정

app router의 루트 레이아웃(최상위)의 <html>, <body>태그 안에 서드 파티 라이브러리에서 제공하는 GA4와 GTM 컴포넌트에 각각의 ID를 props로 전달한다.

컴포넌트를 "@next/third-parties/google"에서 import 하는 것이 중요하다.

import type { Metadata } from "next";
import "./globals.css";
import { GoogleAnalytics, GoogleTagManager } from "@next/third-parties/google";

export const metadata: Metadata = {
  // 생략
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="ko" className={pretendard.className}>
      <body>
        <main>{children}</main>
        <GoogleTagManager gtmId={process.env.NEXT_PUBLIC_GA_ID} />
        <GoogleAnalytics gaId={process.env.NEXT_PUBLIC_GA_ID} />
      </body>
    </html>
  );
}

🚨 GA4와 GTM에서 각각 계정을 만들어서 ID를 발급받아서 사용해야 한다. 공식 문서에 매우 잘 나와있으니 천천히 따라하면 문제없이 발급 받을 수 있다.


3. 타입선언

환경 변수를 사용했으니, declaration.d.ts 파일을 통하여 프로젝트의 전역 타입 선언을 정의한다. Google Analytics를 사용하는 경우, gtag 함수는 글로벌 window 객체에 추가된다. TypeScript는 기본적으로 window.gtag의 존재를 인식하지 못하기 때문에 window 객체에 gtag 함수를 추가로 선언해준다.

declare namespace NodeJS {
  interface ProcessEnv {
    NEXT_PUBLIC_API_BASE_URL: string;
    NEXT_PUBLIC_APP_URL: string;
    NEXT_PUBLIC_GA_ID: string;
  }
}

interface Window {
  gtag: any;
}

4. 이벤트 추적 상수 정의 (GA_CTA_EVENTS)

constants.tsGA_CTA_EVENTS 객체를 정의한다. Google Analytics(GA4) 이벤트 추적을 위해 사용되는 상수들을 정의한 객체이다. 이 객체는 특정 사용자 상호작용 이벤트에 대한 라벨을 미리 정의하여 일관성 있게 사용할 수 있도록 한다.

export const GA_CTA_EVENTS = {
  onClickBottomBannerCTA: "click_cta_bottom_banner",
  onClickListeningCTA: "click_cta_listening",
  onClickNavigationCTA: "click_cta_navigation",
  onClickGuideCTA: "click_cta_guide",
  onClickAppDownloadCTA: "click_cta_app_download",
} as const;

export type GA_CTA_EVENT = typeof GA_CTA_EVENTS[keyof typeof GA_CTA_EVENTS];
  • onClickBottomBannerCTA: 페이지 하단 배너 클릭 이벤트.
  • onClickListeningCTA: 특정 청취 관련 버튼 클릭 이벤트.
  • onClickNavigationCTA: 네비게이션 메뉴 클릭 이벤트.
  • onClickGuideCTA: 가이드 관련 버튼 클릭 이벤트.
  • onClickAppDownloadCTA: 앱 다운로드 버튼 클릭 이벤트.

🤔 CTA란?
CTA는 "Call to Action"의 약자로, 웹사이트나 앱에서 사용자를 특정 행동으로 유도하는 요소를 의미한다. CTA는 보통 버튼, 링크, 배너 등의 형태로 나타나며, 사용자가 원하는 목표를 달성하도록 유도하는 역할을 한다.


5. 페이지뷰 컴포넌트 (GAPageView)

GAPageView 컴포넌트는 페이지뷰 이벤트를 Google Analytics4(GA4)로 전송하는 역할을 한다. 이 컴포넌트는 페이지 경로가 변경될 때마다 GA4에 페이지뷰 이벤트를 기록하여 사용자가 어떤 페이지를 방문했는지 추적할 수 있게 해준다.

useGAPageView 훅은 페이지 경로(pathname)가 변경될 때마다 GA4로 페이지뷰 이벤트를 전송하는 역할을 한다.

"use client";

import { sendGAEvent } from "@next/third-parties/google";
import { usePathname } from "next/navigation";
import { useEffect } from "react";

export default function useGAPageView() {
  const pathname = usePathname();  // 현재 페이지 경로를 가져온다.

  useEffect(() => {
    sendGAEvent("page_view", { page_path: pathname });  // 페이지 경로가 변경될 때마다 페이지뷰 이벤트를 전송한다.
  }, [pathname]);  // pathname이 변경될 때마다 useEffect 훅이 실행된다.

  return null;
}

export function GAPageView() {
  useGAPageView();  // useGAPageView 훅을 호출하여 페이지뷰 이벤트를 전송한다.
  return null;
}

🤔 왜 따로 컴포넌트로 만들었는가?
GAPageView 컴포넌트를 GA_CTA_EVENTS처럼 이벤트 객체화 시키지 않고 따로 컴포넌트로 만든 이유는 뭘까? CTA 이벤트와 페이지뷰 이벤트가 발생하는 시점과 트리거 방식이 다르기 때문에 처리 방식도 다르게 구현해야 한다. 페이지뷰 이벤트는 페이지 로드 시점에 자동으로 전송하는 것이 적절한 방법이다.


6. 이벤트 전송 컴포넌트 (GACta)

GACta 컴포넌트는 Google Analytics(GA4)와 Google Tag Manager(GTM)로 클릭 이벤트를 전송하는 버튼 컴포넌트이다. 사용자가 버튼을 클릭할 때마다 sendGAEventsendGTMEvent 함수를 호출하여 이벤트를 기록한다.

"use client";

import { GA_CTA_EVENT } from "@/constants";
import { sendGAEvent, sendGTMEvent } from "@next/third-parties/google";

type GAButtonProps = {
  children: React.ReactNode;
  eventLabel: GA_CTA_EVENT;
} & React.HTMLAttributes<HTMLButtonElement>;

export default function GACta({
  children,
  className,
  eventLabel,
  onClick,
  ...rest
}: GAButtonProps) {
  function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
    sendGAEvent("event", eventLabel);  // GA4에 이벤트 전송
    sendGTMEvent("event", eventLabel);  // GTM에 이벤트 전송
    if (onClick) {
      onClick(e);
    }
  }

  return (
    <button type="button" onClick={handleClick} className={className} {...rest}>
      {children}
    </button>
  );
}

사용하기

위에서 설정한 컴포넌트들과 객체들을 활용하여 실제로 GA4와 GTM 이벤트를 전송할 수 있다.

예제 코드

import GACta from "@/components/common/ga-cta";
import { GA_CTA_EVENTS } from "@/constants";
import { GAPageView } from "@/libs/ga-page-view";
import Link from "next/link";

const APP_URL = process.env.NEXT_PUBLIC_APP_URL;

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <>
      <Link href={APP_URL} target="_black">
        <GACta eventLabel={GA_CTA_EVENTS.onClickNavigationCTA}>
          앱 다운받기
        </GACta>
      </Link>
      <GAPageView />
    </>
  );
}
  • GACta 컴포넌트: 특정 사용자 클릭 이벤트를 GA4와 GTM에 전송하여 클릭 데이터를 추적한다.
  • GAPageView 컴포넌트: 페이지뷰 이벤트를 GA4에 전송하여 사용자의 페이지 방문 데이터를 추적한다.

마치며

google analytics4 로고

이렇게 사용하면 페이지별로 또는 특정 클릭 요소에 대해 사용자가 어떻게 반응하는지에 대한 데이터를 GA4에서 확인할 수 있게 된다. 서드 파티 라이브러리가 없으면 이러한 설정 작업이 복잡하고 어려워서 Next.js 공식 문서에서도 서트 파티 라이브러리를 사용할 것을 권장하고 있다.

GA4 플랫폼 화면

GA4와 GTM은 기능이 매우 많고 처음 사용하는 경우 학습 곡선이 높기 때문에, 이를 다루는 강의도 많이 있다. 다음 포스트에서는 GA4와 GTM에 대한 플랫폼 가이드와 디버깅 등 마케팅 요소 측면에서도 다뤄보고자 한다. 이를 통해 자사 웹사이트에 어떤 사용자가 방문했는지, 어떤 경로를 통해 들어왔는지, 방문 후 어떤 행동을 했는지 등의 데이터를 정리할 수 있다. 이러한 데이터를 바탕으로 다양한 마케팅 전략을 실험해 볼 수 있어 매우 흥미로운 일이 될 것이다.


참고문헌

3개의 댓글

comment-user-thumbnail
2024년 7월 11일

that a great info to share very comprehensive and informative............. great work keep it up...

1개의 답글
comment-user-thumbnail
2024년 7월 11일

that a great info to share very comprehensive and informative............. great work keep it up...

답글 달기