AppRouter 적용한 분들 고생 많으십니다..
이번에 Next.js 13 AppRouter를 적용하여 신규 프로젝트를 진행하고 있습니다.
AppRouter에 대한 레퍼런스가 아직 많지 않아 하나 하나 할 때마다 굉장히 난항을 겪고 있습니다.
혹시 AppRouter를 적용하여 신규 개발을 하시는 분이라면 편하게 댓글 달아주시고 제가 아는 부분이라면 도와드리겠습니다.
혹시나 글에 문제점이 있다면 편하게 말씀해주시면 감사하겠습니다.
AppRouter 프로젝트에서 Meta Pixel 적용하는 방법
신규 프로젝트에 MetaPixel을 적용할 일이 있어 찾아봤는데, Next.js Example에는 PageRouter에 대한 예시만 있었습니다. 그래서 기존 Example 소스와 신규 AppRouter 예시를 활용해서 AppRouter에서 Meta Pixel 적용하는 코드를 작성했습니다.
Next.js의 Pixel 적용 예시
기존 Example 소스에서는 아래와 같이 나와있습니다. Meta Pixel에 pageview 이벤트를 보낼 때, 아래와 같이 next/router의 useRouter를 활용합니다. 기존 useRouter의 events를 활용하여 route가 변할 때마다 pageview 이벤트를 전송합니다.
import { useEffect } from 'react'
import Script from 'next/script'
import { useRouter } from 'next/router'
import * as fbq from '../lib/fpixel'
function MyApp({ Component, pageProps }) {
const router = useRouter()
useEffect(() => {
// This pageview only triggers the first time (it's important for Pixel to have real information)
fbq.pageview()
const handleRouteChange = () => {
fbq.pageview()
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [router.events])
return (
<>
{/* Global Site Code Pixel - Facebook Pixel */}
<Script
id="fb-pixel"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', ${fbq.FB_PIXEL_ID});
`,
}}
/>
<Component {...pageProps} />
</>
)
}
export default MyApp
AppRouter에서의 문제점
하지만 Next.js13 AppRouter에서는 Client에서 활용될 때, next/router의 useRouter를 활용할 수 없게 됐습니다.
이제 next/navigation 로부터 useRouter를 import해와야 하는데요. 이 신규 useRouter에서는 event를 활용할 수 없습니다.
따라서 새롭게 route가 변경되는 이벤트를 측정할 수 있는 방법을 찾아야 합니다.
AppRouter에서의 route change event 감지 방법
Next.js에서 제시한 route 변경 시 event를 발생시키는 소스입니다.
// app/components/navigation-events.js
'use client';
import { useEffect } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';
export function NavigationEvents() {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
const url = pathname + searchParams.toString();
console.log(url);
// You can now use the current URL
// ...
}, [pathname, searchParams]);
return null;
}
// app/layout.js
import { Suspense } from 'react';
import { NavigationEvents } from './components/navigation-events';
export default function Layout({ children }) {
return (
<html lang="en">
<body>
{children}
<Suspense fallback={null}>
<NavigationEvents />
</Suspense>
</body>
</html>
);
}
NavigationEvents라는 신규 컴포넌트를 만들고, usePathname과 useSearchParams를 활용하여 useEffect를 통해 url 변경 시마다 event를 발생시킬 수 있게 했습니다. 그리고 해당 컴포넌트를 Layout 쪽에 넣어서, 전체 페이지에 들어가도록 해놨습니다.
NavigationEvents를 Suspense 안에 넣은 이유는 아래 내용을 참조하시기 바랍니다. AppRouter의 렌더링 방식에 대한 공부도 필요해보입니다.
Note: <NavigationEvents> is wrapped in a Suspense boundary
because useSearchParams() causes client-side rendering up to the closest
Suspense boundary during static rendering
AppRouter에서의 Meta Pixel 적용 방법
// src/common/fpixel.js
export const FB_PIXEL_ID = process.env.NEXT_PUBLIC_FACEBOOK_PIXEL_ID;
export const pageview = () => {
window.fbq("track", "PageView");
};
export const event = (name, options = {}) => {
window.fbq("track", name, options);
};
// src/components/NavigationEvents.tsx
"use client";
import { usePathname, useSearchParams } from "next/navigation";
import { useEffect } from "react";
import * as fbq from "../common/fpixel";
import Script from "next/script";
import { FB_PIXEL_ID } from "../common/fpixel";
export default function NavigationEvents() {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
fbq.pageview();
}, [pathname, searchParams]);
return (
<>
<Script
id="fb-pixel"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '${FB_PIXEL_ID}');
fbq('track', 'PageView');
`,
}}
/>
</>
);
}
위에 있는 Navgation event를 감지하는 컴포넌트에다 MetaPixel 관련 코드를 next/script 를 활용하여 삽입했습니다.
이 컴포넌트를 아래와 같이 layout 쪽에 넣어줬습니다.
// src/app/layout.tsx
import Layout from "@/components/Layout";
import "@/app/globals.css";
import { Suspense } from "react";
import { FB_PIXEL_ID } from "@/common/fpixel";
import NavigationEvents from "@/components/NavigationEvents";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="ko">
<head>
<noscript>
<img
height="1"
width="1"
style={{ display: "none" }}
src={`https://www.facebook.com/tr?id=${FB_PIXEL_ID}&ev=PageView&noscript=1`}
/>
</noscript>
</head>
<body>
<Layout>{children}</Layout>
<Suspense fallback={null}>
<NavigationEvents />
</Suspense>
</body>
</html>
);
}
이렇게 하면 Meta Pixel이 정상적으로 Next.js AppRouter 프로젝트에서 실행되게 됩니다.
Meta Pixel 적용 결과
Meta 이벤트 관리자에 가보면 아래와 같이 정상적으로 PageView를 수신하는 것을 볼 수 있습니다.
느낀점
AppRouter를 적용하면서 페이지마다도 SSR이 필요한 부분을 쉽게 분리할 수 있어서 충분한 메리트가 있는 것 같습니다.
기존 PageRouter를 많이 써보진 않아서 원래도 가능했는지는 잘 모르겠네요..
하지만 AppRouter를 적용하는 데에 있어서, 레퍼런스가 많이 없어 공식 Document를 잘 활용하는 수 밖에 없었습니다. 공식 Documet에서는 입맞에 맞는 내용을 찾기가 조금 힘들어서 시간이 오래 걸리네요.
아무튼 Meta Pixel 적용이 필요하신 분들은 도움이 되셨으면 좋겠습니다.