How to Track Custom GA4 Events in Next.js with @next/third-parties (sendGAEvent)
21
공유

Next.js gives you @next/third-parties/google to drop Google Analytics 4 in with one line. But the moment you go past a basic pageview — firing custom events like sign_up or post_publish — the docs go quiet and you hit a few silent traps. Here's a production-ready setup that actually fires GA4 custom events reliably.

1. Add GoogleAnalytics (the easy part)

1 2 3 4 // app/layout.tsx (App Router) or pages/_app.tsx (Pages Router) import { GoogleAnalytics } from '@next/third-parties/google'; <GoogleAnalytics gaId="G-XXXXXXXXXX" />

This auto-sends page_view. The hard part is everything after.

2. Fire a custom event with sendGAEvent

1 2 3 import { sendGAEvent } from '@next/third-parties/google'; sendGAEvent('event', 'sign_up', { method: 'github' });

Call it where the action succeeds — a React Query onSuccess, an OAuth callback, a submit handler.

3. Gotcha #1 — events silently vanish before gtag.js loads

sendGAEvent pushes to window.dataLayer. If it runs before the GA script created that array, the event is dropped with only a console warning. Pre-create the queue so early events survive:

1 2 window.dataLayer = window.dataLayer || []; sendGAEvent('event', name, params);

gtag.js replays the existing dataLayer on load, so a pre-seeded queue is safe.

4. Gotcha #2 — dev & preview traffic pollutes your prod property

By default, localhost and Vercel preview deploys send events into your real GA4 property. Gate it:

1 2 3 export const GA_ENABLED = process.env.NODE_ENV === 'production' && process.env.NEXT_PUBLIC_VERCEL_ENV !== 'preview';

(Vercel exposes NEXT_PUBLIC_VERCEL_ENV only if Automatically expose System Environment Variables is on.)

5. A reusable, type-safe helper

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import { sendGAEvent } from '@next/third-parties/google'; export type GAEventName = 'sign_up' | 'login' | 'post_publish' | 'post_view'; export function trackEvent( name: GAEventName, params: Record<string, string | number | boolean | null | undefined> = {}, ) { if (typeof window === 'undefined' || !GA_ENABLED) return; window.dataLayer = window.dataLayer || []; // gotcha #1 const clean = Object.fromEntries( // drop null/undefined Object.entries(params).filter(([, v]) => v != null), ); sendGAEvent('event', name, clean); }

Now every call is typo-proof: trackEvent('post_publish', { public_status: true, tag_count: 4 }).

6. Don't forget — register custom dimensions in GA4

A custom parameter like method or public_status won't show up in reports until you register it as a custom dimension (GA4 Admin → Custom definitions). It's not retroactive — add it before you collect data.

Gotcha checklist

  • Pre-seed window.dataLayer → events aren't dropped.
  • Gate to production → no dev/preview noise.
  • Register custom dimensions → params actually appear.
  • Fire on success callbacks, not on click → you don't count failures.

Closing

One <GoogleAnalytics> tag, a typed trackEvent wrapper, three gotchas handled. Open GA4 Realtime and your custom events should appear within seconds.

댓글을 작성하려면로그인이 필요합니다.

관련 글