Intégrer Google AdSense dans une app Next.js (App Router)
DOG&DEV · 25/01/2025
Intégrer Google AdSense dans une app Next.js (App Router)
Google AdSense permet d’afficher des annonces sur un site et de monétiser le trafic. Dans Next.js 15 avec App Router, l’intégration repose sur le composant Script de Next, un composant global chargé dans le layout, et des blocs d’annonces (AdUnit) réutilisables. Ce guide décrit une mise en place type : chargement conditionnel en prod, formats (auto, rectangle, horizontal, vertical) et rafraîchissement des annonces lors de la navigation.
Prérequis
- Projet Next.js 15 (App Router)
- Compte Google AdSense et site vérifié
- Identifiant client AdSense (
ca-pub-XXXXXXXXXXXXXXXX) et slots (identifiants d’emplacement)
1. Composant global AdSense (Script)
Le script AdSense ne doit en général être chargé qu’en production et une seule fois (dans le layout).
Exemple : components/GoogleAdSense.tsx
import Script from 'next/script';
const isProd = process.env.NODE_ENV === 'production';
const clientId = process.env.NEXT_PUBLIC_ADSENSE_CLIENT_ID;
export function GoogleAdSense() {
if (!isProd || !clientId) return null;
return (
<Script
async
src={`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${clientId}`}
crossOrigin="anonymous"
strategy="afterInteractive"
/>
);
}
Layout (app/layout.tsx) :
import { GoogleAdSense } from '@/components/GoogleAdSense';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="fr">
<head>
<GoogleAdSense />
</head>
<body>{children}</body>
</html>
);
}
Variables d’environnement : NEXT_PUBLIC_ADSENSE_CLIENT_ID=ca-pub-XXXXXXXXXXXXXXXX (préfixe NEXT_PUBLIC_ pour exposition côté client).
2. Composant AdUnit réutilisable
Pour afficher des blocs d’annonces (format auto, rectangle, horizontal, vertical), on crée un composant AdUnit qui rend un <ins class="adsbygoogle"> et déclenche (adsbygoogle = window.adsbygoogle || []).push({}) après le mount et à chaque changement de route (pour recharger les annonces en SPA).
Exemple simplifié : components/AdUnit.tsx
'use client';
import { usePathname } from 'next/navigation';
import { useEffect, useRef } from 'react';
declare global {
interface Window {
adsbygoogle: unknown[];
}
}
const formatStyles: Record<string, React.CSSProperties> = {
auto: { display: 'block' },
fluid: { display: 'block' },
rectangle: { display: 'inline-block', width: 300, height: 250 },
horizontal: { display: 'inline-block', width: 728, height: 90 },
vertical: { display: 'inline-block', width: 160, height: 600 },
};
interface AdUnitProps {
adSlot: string;
adFormat?: 'auto' | 'fluid' | 'rectangle' | 'horizontal' | 'vertical';
style?: React.CSSProperties;
}
export function AdUnit({ adSlot, adFormat = 'auto', style = {} }: AdUnitProps) {
const pathname = usePathname();
const adRef = useRef<HTMLModElement>(null);
const pushAd = () => {
try {
if (typeof window !== 'undefined' && window.adsbygoogle) {
window.adsbygoogle.push({});
}
} catch (e) {
if (process.env.NODE_ENV === 'development') console.error('AdSense push error', e);
}
};
useEffect(() => {
pushAd();
}, [pathname]); // Re-push à chaque changement de page
return (
<div className="ad-container my-4">
<ins
ref={adRef}
className="adsbygoogle"
style={{ ...formatStyles[adFormat], ...style }}
data-ad-client={process.env.NEXT_PUBLIC_ADSENSE_CLIENT_ID}
data-ad-slot={adSlot}
data-ad-format={adFormat}
data-full-width-responsive="true"
/>
</div>
);
}
Props :
adSlot: identifiant du bloc dans AdSense.adFormat:auto(responsive),rectangle(300×250),horizontal(728×90),vertical(160×600).
3. Utilisation dans les pages
Au-dessus du contenu (above the fold) :
import { AdUnit } from '@/components/AdUnit';
export default function MainPage() {
return (
<main>
<AdUnit adSlot="1234567890" adFormat="horizontal" style={{ marginBottom: 20 }} />
<section>
<h1>Bienvenue</h1>
<p>Contenu…</p>
</section>
</main>
);
}
Dans un article :
<article>
<h2>Titre</h2>
<p>Paragraphe…</p>
<AdUnit adSlot="1234567891" adFormat="rectangle" style={{ margin: '20px 0' }} />
<p>Suite…</p>
</article>
Barre latérale :
<aside>
<h2>Liens</h2>
<AdUnit adSlot="1234567892" adFormat="vertical" style={{ marginTop: 20 }} />
</aside>
4. Test et bonnes pratiques
- Les annonces ne s’affichent en général qu’en production (ou sur un domaine autorisé dans AdSense). Tester après déploiement.
- Densité : respecter les règles AdSense (nombre de blocs par page, espacement).
- Performance :
strategy="afterInteractive"pour ne pas bloquer le First Contentful Paint ; placer les blocs sans nuire au Core Web Vitals.
Dépannage
| Symptôme | Piste | Correctif |
|---|---|---|
| Blocs vides | Domaine non approuvé ou script non chargé | Vérifier AdSense, NEXT_PUBLIC_ADSENSE_CLIENT_ID, chargement du script en prod |
| Annonces qui ne se mettent pas à jour en SPA | Pas de re-push au changement de route | Appeler `(adsbygoogle |
| Erreurs console (adsbygoogle) | Script chargé avant le DOM du bloc ou trop tôt | S’assurer que AdUnit est rendu après afterInteractive ; un court délai ou requestAnimationFrame peut aider si besoin |
Ressources
- Tech Verse Daily – Integrating Google AdSense with Next.js App Router
- Documentation Next.js – Script
- Google AdSense – Aide
Cet article s’inscrit dans notre série de guides technique et développement web. Pour un serveur ou une application sur-mesure, contact.