The AdSense integration that actually works

The AdSense integration that actually works

May 3, 2026 · adsensemonetizationads

AdSense feels intimidating because Google's docs cover every possible ad placement, format, and rule. For a typical content site, you don't need most of it. You need:

  1. The publisher loader script in <head>.
  2. An ads.txt file at your domain root.
  3. Approval from AdSense.
  4. Ad slots on your pages.

That's it. Done correctly, the integration is about 20 minutes of work. The hard part is getting approved (which Google does at their own pace) and waiting through that. The integration itself is simple.

Here's the full pattern.

Step 1: Get a publisher ID

Sign up at adsense.google.com. Add your site. Google asks you to add their script to verify ownership. The script looks like:

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXXXXXXXX" crossorigin="anonymous"></script>

Your publisher ID is the ca-pub-XXXXXXXXXXXXXXXX part. Save it. You'll use it in two places.

Step 2: Add the loader script to <head> of every page

Drop the script tag into the <head> of every page on your site. For Next.js or any framework with a root layout, that's a one-line addition. For static HTML, it goes in every .html file.

Important: the script must be in <head>, not <body>. AdSense's reviewer specifically checks for this; a script in body will fail review.

For a single-page application (SPA), the <head> is the static index.html's head — not anything React renders. Putting the script in a React component won't satisfy AdSense's reviewer because they don't execute JavaScript.

Step 3: Create ads.txt at your domain root

This is the most-skipped step and it costs you serious revenue.

ads.txt is the IAB "Authorized Digital Sellers" file. It lives at https://your-domain.com/ads.txt and tells programmatic ad buyers which sellers are authorized to monetize your inventory. Without it, automated bidders treat your inventory as "unauthorized seller" and bid less (or not at all). AdSense estimates the impact at 30-50% of revenue.

The file content for AdSense is one line:

google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0

Breaking down each field:

  • google.com — the SSP (Supply-Side Platform) being authorized.
  • pub-XXXXXXXXXXXXXXXX — your publisher ID, without the ca- prefix (this is the format in ads.txt, even though the script uses ca-pub-).
  • DIRECT — you have a direct relationship with Google (vs. reselling).
  • f08c47fec0942fa0 — Google's fixed TAG ID. Same value for every AdSense publisher.

Place the file at public/ads.txt for Next.js / Vite / Astro projects. Verify after deploy with:

curl https://your-domain.com/ads.txt

Should return the single line as text/plain.

Step 4: Wait for AdSense approval

This is the slow part. Google's reviewer evaluates whether your site has substantive content, a clear purpose, and proper navigation. Typical wait: 2-7 days for the first decision.

Common rejection reasons:

  • Low value content. This is the most common one for SPAs because the rendered HTML is just a script tag and an empty <div>. The fix is server-side rendering or pre-rendering so the HTML response contains real content text.
  • Insufficient content. A site with one page is harder to approve than a site with substantive pages, a blog, or documentation.
  • Under construction. Sites with placeholder text or "coming soon" sections.

If you get a rejection, fix the cited issue and request re-review. Each cycle is another 2-7 days.

Step 5: Create ad units once approved

Once approved, AdSense → Ads → By ad unit → Create new ad unit. Each unit gets a 10-digit slot ID.

For a typical content site, three units cover most placement needs:

  • Top of post (after the title): 728×90 leaderboard or responsive
  • In-content (mid-post): responsive
  • End of post (before footer): 728×90 or responsive

For sidebars on wide layouts:

  • Sidebar: 160×600 wide skyscraper or 300×600 half page

Step 6: Insert ad slots in your templates

Each ad slot is an <ins> element with a tiny script that pushes the slot to AdSense's queue:

<ins class="adsbygoogle"
     style="display:block; width:100%; max-width:728px; height:90px"
     data-ad-client="ca-pub-XXXXXXXXXXXXXXXX"
     data-ad-slot="1234567890"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>

The data-ad-format="auto" and data-full-width-responsive="true" attributes let AdSense pick the best size for the available space. Use these unless you have a specific reason to fix the dimensions.

The optimization: hide on small screens

Sidebar ads in particular should be hidden below a certain viewport width. Cramming a 160×600 ad next to mobile content makes the page unusable.

Tailwind makes this trivial:

<aside class="hidden xl:block w-[180px]">
  <ins class="adsbygoogle" ...></ins>
</aside>

hidden xl:block means the slot only renders on viewports ≥1280px. Mobile and tablet users get a clean reading experience.

What you'll earn

For a content site at typical CPMs ($1-3), each 1,000 page views earns roughly $1-3 in ad revenue. This scales linearly with traffic, so:

  • 1,000 monthly page views: $1-3
  • 10,000: $10-30
  • 100,000: $100-300
  • 1,000,000: $1,000-3,000

These numbers wildly depend on niche (finance and software pay better; lifestyle and entertainment pay less), region (US/UK traffic pays more than other geos), and time of year (Q4 is much higher than Q1).

For most MVPs, AdSense is supplementary income, not primary revenue. Don't build for ads; ship the product, add ads as a passive layer once approved.

Anti-patterns

Stuffing too many ad slots. Past 3-4 per page, AdSense itself will downgrade you, and your users will bounce.

Loading the AdSense script on pages that don't show ads. Kills perf for no benefit. If you have an admin dashboard or a checkout flow, conditionally skip the script there.

Forgetting ads.txt. Silently kills 30-50% of revenue. Always check after deploy.

Re-requesting approval before fixing the cited issue. AdSense reviewers note repeat applications. Fix the issue first, document the fix in your re-review note.

Ad blockers in dev. Ad blockers strip the AdSense script silently in your local browser. If you're testing whether ads load and they don't appear, check your ad blocker before assuming the integration is broken.

What this site did

vibecodersguidetomvp.help has the AdSense loader in <head>, an ads.txt at the root, and two side-column ad slots on the carousel that hide on viewports below 1280px.

The first AdSense review came back "Needs attention — low value content" because the SPA's HTML response was just an empty shell. The fix is the pre-rendering pattern from sub-skill 13 of the skill bundle: a Puppeteer post-build script that renders the SPA, dumps the resulting DOM, and writes it back to dist/index.html. The carousel still works the same in the browser, but the initial HTML response now contains real content text. Re-requested approval.

That's the whole pattern. Loader script, ads.txt, real content in the initial HTML response, approval, ad slots. Twenty minutes of integration work plus however long Google takes to approve. Don't make it harder than it is.

Did this land for you?

← All posts