How to Set Up GA4 on a Next.js Site (the 2026 way)

Google Analytics 4 is still the default for web analytics, and it's free. Here's a clean way to wire it into a Next.js app without bloating your bundle or guessing whether it works.

1. Create a GA4 property and data stream

In the Google Analytics admin, create a GA4 property, then a Web data stream for your domain. You'll get a Measurement ID that looks like G-XXXXXXXXXX. That's the only public identifier you need on the client.

2. Load gtag.js the Next.js way

Use the built-in next/script component with the afterInteractive strategy so the tag loads without blocking your page. Put your Measurement ID in an environment variable (NEXT_PUBLIC_GA_ID) rather than hardcoding it, so staging and production stay separate.

3. Track route changes

GA4's automatic page_view works for the first load, but Next.js client-side navigation doesn't trigger a full page load. Fire a page_view on route change (via the App Router's usePathname) so your pageviews aren't undercounted.

4. Send the events that matter

Pageviews alone won't tell you much. Map your funnel to GA4 events:

  • sign_up when an account is created
  • purchase with value (a number, not a string) and currency (an ISO‑4217 code like "USD", not "$") for revenue
  • any custom key event specific to your product

Prefer Google's recommended event names (sign_up, login, begin_checkout, purchase, generate_lead) before inventing your own — the recommended names unlock standard reports and Ads integration. Avoid the reserved prefixes ga_, google_, firebase_ and reserved names like session_start or user_engagement; GA4 silently drops them. Keep names consistent with whatever canonical taxonomy you use elsewhere so reports line up across tools.

5. Verify with DebugView

This is the step everyone skips. Open GA4's DebugView, load your site, and watch events arrive in real time. If sign_up doesn't show up when you submit the form, your tracking is broken — and DebugView tells you immediately, instead of you discovering it a week later in an empty report.

6. Mark the events that matter as key events

In GA4, a key event (what GA4 used to call a "conversion") is just an event you've flagged as important — e.g. sign_up, purchase, generate_lead. Mark your 1–3 most important events in Admin → Events → toggle "Mark as key event". You need at least one key event before GA4's Advertising section unlocks, and you can have up to 30 per property. Keep the list short and intentional.

7. Set data retention to 14 months

GA4 defaults event-level data retention to 2 months. Bump it to the max: Admin → Data settings → Data retention → 14 months, and enable "Reset user data on new activity." This only affects Explorations, funnels, and the Data API's freshness window — not your standard aggregated reports — and it is not retroactive, so do it now before you need the history.

8. Link Google Ads and turn on auto-tagging

If you run paid ads, this is the step that makes paid traffic attribute correctly. Admin → Product links → Google Ads links → Link, and make sure auto-tagging is on in Google Ads (it appends the gclid that lets GA4 classify Paid Search / Cross‑network properly). Without this, paid clicks get misfiled as organic or referral and your channel report lies to you.

9. Three credentials — don't mix them up

GA4 has three different identifiers/keys for three different jobs:

  • Measurement ID (G-XXXXXXXXXX) — public, client-side. The only thing the gtag snippet needs to send pageviews/events.
  • Measurement Protocol API secret — a stream-scoped secret for server-side event sending (/mp/collect). You only need this if you send events from your backend. VibesAnalytics does not require it.
  • Data API credentials (the OAuth grant when you connect_provider, or a service-account JSON) — for reading report data back out. This is what powers your dashboard.

Also note: the numeric Property ID (e.g. properties/123456789) is not the same as the G- Measurement ID. The Data API uses the numeric Property ID; the gtag uses the G- one.

10. Consent Mode v2 (EEA/UK) and the June 2026 change

If you have any EEA/UK traffic, implement Consent Mode v2: default the four signals (ad_storage, analytics_storage, ad_user_data, ad_personalization) to denied and update them to granted on acceptance. Heads-up for the future: from June 15, 2026, Consent Mode (within Google Ads) becomes the single control for Ads data and ad_storage is the governing parameter — Google Signals narrows to controlling only how your GA4 data associates with signed-in users for behavioral reporting. Plan consent around ad_storage.

Common misconfigurations that produce bad data

  • Data retention left at 2 months → Explorations and funnels truncated.
  • Google Ads not linked / auto-tagging off → paid traffic misclassified.
  • Missing UTMs on non-Google campaigns → traffic lands in Unassigned/Direct.
  • No key events configured → the Advertising section stays locked.
  • Internal/self-referral domains not excluded → inflated referral traffic.
  • Consent signals missing in the EEA → shrinking, modeled data.
  • Google Signals on a low-traffic property → heavy thresholding (rows withheld when user counts are small; the Data API gives you no warning that this happened).
  • Confusing the numeric Property ID with the G- Measurement ID.

A note on resilience

GA4 runs client-side, so ad blockers and consent choices will drop some events. Treat GA4 as one (important) input, not the source of truth. Pairing it with first-party owned events gives you a baseline that survives blockers.