Google AdSense is one of the easiest ways to monetize a website. But if you’re using Next.js with the App Router, setting it up properly requires a few key steps.

Here’s how we added AdSense to vibeberry.io - with full control, clean architecture, and production-ready integration.

1. Create an AdSense Account

Start by signing up at adsense.google.com/start.

You’ll need to:

  • enter your domain (must be live and working)
  • fill out basic business or personal info
  • wait for Google to review your site

Once you’re in, AdSense will ask you to verify your site by adding a script and an ads.txt file.

2. Add the Script and ads.txt

Create the Script Component

We created a reusable AdSense script loader and placed it here:

src/components/third-parties/GoogleAdsense.tsx

import { FC } from 'react';
import Script from 'next/script';

const GoogleAdsense: FC<{ pId: string }> = ({ pId }) => (
  
);

export default GoogleAdsense;

Load It in Production via a Centralized Service Component

To manage all third-party scripts cleanly, we created a wrapper component:

src/components/third-parties/RootLayoutServices.tsx

It loads services like AdSense, Analytics, Speed Insights, etc. - but only in production:

const RootLayoutServices: FC = () => {
  return process.env.NODE_ENV === 'production' ? (
    <>
      
      {/* Other third-party services */}
    >
  ) : null;
};

Then we included it at the bottom of our main layout:

// src/app/layout.tsx


  {/* app content */}

✅ This ensures your scripts only run live, never during local development.

Add public/ads.txt

Create this file:
public/ads.txt

And include:

google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0

Replace pub-1234567890123456 with your Publisher ID, found under AccountAccount information in AdSense.

This tells Google you’re allowed to show ads on your domain.

3. Create a Manual Ad Unit

After your site is approved:

  • Go to AdsBy ad unit
  • Choose Display Ads
  • Set the format (we use responsive)
  • Copy the generated data-ad-slot value

We prefer manual units over Auto Ads for better layout control.

manual units list

4. Create a Custom Ad Slot Component

We placed our ad slot component here:
src/components/third-parties/AdSlot.tsx

'use client';

import { useEffect } from 'react';

const AdSlot = ({ slot }: { slot: string }) => {
  useEffect(() => {
    try {
      (window.adsbygoogle = window.adsbygoogle || []).push({});
    } catch (e) {
      console.error(e);
    }
  }, []);

  return (
   
  );
};

export default AdSlot;

You can now place wherever needed in your UI.

5. Handle App Router Navigation

Since we’re using Next.js App Router, AdSense and Analytics won’t automatically detect route changes. We fixed this with:
src/components/third-parties/AnalyticsRouter.tsx

'use client';

import { useEffect, useRef } from 'react';
import { usePathname } from 'next/navigation';

export default function AnalyticsRouter() {
  const path = usePathname();
  const first = useRef(true);

  useEffect(() => {
    if (first.current) {
      first.current = false;
      return;
    }

    window.gtag?.('event', 'page_view', {
      page_path: path,
      page_location: window.location.href,
    });
  }, [path]);

  return null;
}

This ensures AdSense/GA4 continue to track page views correctly as users navigate between routes.

6. Respect Consent Requirements (EU, US)

If you serve users in the EU, California, or other regions with privacy laws, you must obtain user consent before showing personalized ads.

You can:

  • Use a Consent Management Platform (CMP)
  • Or implement manual logic using gtag('consent', ...)

Without consent, Google may block personalized ads or fall back to lower-paying non-personalized ones.

7. Console Warning (You Can Ignore It)

During development or even in production, you may see this browser console warning:

warning preview

It’s harmless and caused by how Next.js handles scripts. Your ads will still load and work perfectly - you can safely ignore it.

Recap

Here’s what we did on vibeberry.io:

  • ✅ Registered an AdSense account
  • ✅ Verified the site with a script and ads.txt
  • ✅ Created manual display ad units
  • ✅ Centralized all scripts in RootLayoutServices
  • ✅ Displayed ads only in production
  • ✅ Handled route changes with App Router
  • ✅ Respected consent rules for personalized ads

Final Thoughts

Setting up AdSense on a modern Next.js project can feel confusing at first - especially with the App Router and all the privacy requirements. But once you break it down into steps, it’s totally manageable.

If you have any questions or run into something tricky - drop a comment below. Thanks for reading - and good luck with your integration!