Getting your Next.js site indexed and tracked correctly requires two tools: Google Search Console (for indexing and search performance) and Google Analytics 4 (for traffic and behavior data). This guide walks through both setups, step by step.
For most single-domain Next.js sites, URL prefix is the easier choice.
Google offers several verification methods:
| Method | Best for |
|---|---|
| HTML tag | Next.js apps (recommended) |
| HTML file upload | Static hosting with file access |
| DNS record | Domain property type |
| Google Analytics | If GA is already installed |
| Google Tag Manager | If GTM is already installed |
Recommended: HTML tag method.
Copy the meta tag Google provides, then add it to your metadata:
App Router (app/layout.tsx):
export const metadata = {
verification: {
google: "your-verification-code",
},
};
Pages Router (pages/_document.tsx or _app.tsx):
<Head>
<meta name="google-site-verification" content="your-verification-code" />
</Head>
Deploy your site, then click Verify in Search Console.
App Router — generate dynamically with app/sitemap.ts:
import type { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{ url: 'https://yoursite.com', lastModified: new Date(), priority: 1 },
{ url: 'https://yoursite.com/about', lastModified: new Date(), priority: 0.8 },
]
}
Pages Router — place a static file at public/sitemap.xml, or generate one at build time with a script.
Then in Search Console: Sitemaps → enter sitemap.xml → Submit.
App Router — use app/robots.ts:
import type { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: { userAgent: '*', allow: '/', disallow: ['/login', '/dashboard'] },
sitemap: 'https://yoursite.com/sitemap.xml',
}
}
Pages Router — place robots.txt in the public/ folder:
User-agent: *
Allow: /
Disallow: /login
Disallow: /dashboard
Sitemap: https://yoursite.com/sitemap.xml
Google discovers robots.txt automatically once it's live — no manual submission needed, but you can verify it via Search Console's URL Inspection tool.
For important pages you want indexed immediately:
Useful for new pages or after major content updates — don't overuse it, as it's rate-limited.
After creating the Web data stream, Google shows a Measurement ID (format: G-XXXXXXXXXX). Copy it — this is what connects your site to GA4.
Use Next.js's official @next/third-parties package for optimized script loading:
npm install @next/third-parties@latest next@latest
Add the ID to .env.local:
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
App Router (app/layout.tsx):
import { GoogleAnalytics } from '@next/third-parties/google'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<GoogleAnalytics gaId={process.env.NEXT_PUBLIC_GA_ID!} />
</body>
</html>
)
}
Pages Router (pages/_app.tsx):
import Script from 'next/script'
export default function App({ Component, pageProps }) {
return (
<>
<Script
strategy="afterInteractive"
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_ID}`}
/>
<Script id="ga-init" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${process.env.NEXT_PUBLIC_GA_ID}');
`}
</Script>
<Component {...pageProps} />
</>
)
}
useEffect(() => {
const handleRouteChange = (url: string) => {
window.gtag('config', process.env.NEXT_PUBLIC_GA_ID!, { page_path: url })
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => router.events.off('routeChangeComplete', handleRouteChange)
}, [router.events])
If your site is deployed on Vercel, you can add Vercel Analytics alongside GA4 for a lightweight, privacy-friendly view of traffic — no cookies, no env vars needed.
bash
npm install @vercel/analytics
App Router (app/layout.tsx):
tsx
import { Analytics } from '@vercel/analytics/next'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Analytics />
</body>
</html>
)
}
Pages Router (pages/_app.tsx):
tsx
import { Analytics } from '@vercel/analytics/react'
export default function App({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<Analytics />
</>
)
}
Go to your project on the Vercel dashboard → Analytics tab → click Enable. Redeploy your site if it wasn't already deployed after adding the component.
Visit your live site, then check the Analytics tab in your Vercel dashboard — page views should appear within a few minutes (note: unlike GA4, there's no instant "Realtime" view; data can take a short while to populate).
Note: Vercel Analytics is a paid feature beyond the free tier's limited events/month — check current pricing on Vercel before relying on it for a high-traffic site. It complements GA4 rather than replacing it: GA4 gives deep behavioral/demographic data, while Vercel Analytics gives fast, zero-config performance-friendly pageview stats tied directly to your deployment.
| Search Console | GA4 | Vercel Analytics | |
|---|---|---|---|
| Purpose | Indexing & search performance | Deep traffic/behavior data | Simple pageview/performance stats |
| Setup effort | Verify ownership + submit sitemap | Install SDK + env var + Measurement ID | Install SDK, no env var |
| Data location | search.google.com/search-console | analytics.google.com | Vercel dashboard |
| Config needed | Meta tag or DNS record | NEXT_PUBLIC_GA_ID env var | None — auto-configured |