日本語

How to serve ads.txt correctly in Next.js (the fastest AdSense-compliant setup and common pitfalls)

alt

You added ads.txt, but AdSense still shows warnings like "Not found" or "Unauthorized."
The file appears in your browser, yet the warning does not disappear in the dashboard.

Next.js is powerful, but ads.txt issues happen easily if one requirement is missed:
the file must be served correctly from the domain root.

In this article, you will learn a reliable ads.txt setup for Next.js (Pages Router and App Router), plus a clear verification flow based on Google and IAB expectations.


What is ads.txt?

ads.txt (Authorized Digital Sellers) is a file that lists authorized sellers of your ad inventory.

Its purpose is to prevent ad fraud and improve transparency.

AdSense does not always require it, but configuration problems can trigger warnings.
Also, reflected status changes can take a few days.

The most important rule is this:

ads.txt must be accessible at https://your-domain.com/ads.txt.


The correct setup in Next.js: place it in public/ads.txt

In Next.js, files in public/ are served directly from the site root.

/public/ads.txt → https://example.com/ads.txt

Procedure

  1. Check the public folder directly under the project.
  2. Create public/ads.txt.
  3. Paste the exact content shown in the AdSense dashboard.
  4. Save it as UTF-8 (without BOM).
  5. Deploy.

This is the safest and lowest-risk approach.


Serving via Route Handler (only if necessary)

You can also serve ads.txt through app/ads.txt/route.ts.

However, this adds extra risk:

  • Cache behavior becomes more complex
  • It is easier to break with middleware side effects
  • Content-Type can accidentally stop being text/plain

Unless you have a strong reason, use public/ads.txt.

Common Pitfalls

1. Middleware catches /ads.txt

When middleware is enabled, /ads.txt may go through it too.

Possible results:

  • Redirect to login screen
  • Locale rewrite
  • Forced www/non-www conversion

Countermeasures

Exclude /ads.txt in your middleware matcher.


2. Multi-step redirects

If redirects chain (for example www -> non-www -> HTTPS), fetching can become unstable.

Check with curl

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

What to verify:

  • Final status is 200
  • Redirects are minimal

3. Content-Type is not text/plain

Sometimes HTML is returned instead of plain text.

Check:

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

Make sure the header includes Content-Type: text/plain.


4. Delayed reflection in AdSense

Google states that updates may take several days to reflect.

If your file is reachable with status 200, give it time before troubleshooting further.


Complete checklist

  • Placed in public/ads.txt
  • Reachable directly at https://your-domain.com/ads.txt
  • curl -I returns final status 200
  • Redirects are minimal
  • Content-Type is text/plain
  • Use "Check for updates" in AdSense
  • Wait a few days

Notes for Vercel deployments

Vercel uses CDN caching.

Static files usually work fine, but reflection can be slower if you use:

  • Aggressive cache settings
  • Edge function routing
  • Route Handler-based delivery

These setups can delay update visibility.


Summary

ads.txt itself is simple.

Problems usually come from interactions between:

  • middleware
  • redirect
  • cache
  • Content-Type

Once these factors overlap, unexpected failures become common.

The conclusion is straightforward:

Place it in public/ads.txt and verify status 200 with curl.

This is the most reproducible way to stay compliant.

Run curl -I now and confirm the basics first.
Simple checks prevent long debugging sessions.

Related posts