How to Fix ads.txt Issues: AdSense Setup Guide for WordPress and Static Websites
That red “Earnings at risk” banner in AdSense — one or more of your sites is missing an ads.txt file — is the most fixable warning in publishing. This guide covers what the file does, your publisher ID, installation on every stack this site itself uses (WordPress, Jekyll, GitHub Pages, Netlify, plain static), every common warning, and multi-network maintenance. It ends with a generator that writes your core records from your publisher ID.
1. What ads.txt is
ads.txt (Authorized Digital Sellers, an IAB standard) is a plain-text file at your domain root (example.com/ads.txt) declaring which companies may sell your ad inventory, with each seller’s relationship to you. Advertisers’ crawlers read it before bidding; mismatches mean reduced demand or warnings — not exactly a ban, but money left on the table.
2. Your publisher ID, precisely
In AdSense: Account → Settings → Account information. You need the pub-XXXXXXXXXXXXXXXX number. The canonical AdSense record is:
google.com, pub-0246183054140429, DIRECT, f08c47fec0942fa0
That last field is Google’s certification authority ID — identical for every AdSense publisher; only the pub- number changes. (The ID above is this site’s own, shown so you can see a real record. Replace it with yours — or use the generator in §12.)
DIRECT means you own the account. RESELLER lines (ad networks selling on your behalf) come later, from each network’s documentation — never invent them.
3. Create the file
One plain-text file named exactly ads.txt (lowercase, .txt extension, UTF-8, no BOM), starting with your Google line. One record per line, # for comments. This site’s live root file is a working example of the minimal correct form.
4. WordPress installation
- Simplest: an ads.txt manager plugin (it writes the file for you and survives theme updates).
-
Manual: SFTP the file to the WordPress root (same folder as
wp-config.php), then visityoursite.com/ads.txtto confirm. - Caching trap: purge all caches (plugin, CDN, host) after uploading — most “I uploaded it but AdSense still warns” cases are stale cache serving a 404 or old copy.
5. Jekyll and GitHub Pages
Place ads.txt in the Jekyll source root so it copies verbatim to _site/ads.txt (no front matter needed — front matter would process it; raw passthrough is what you want). Verify the built file, commit, push, and check the live URL. This site runs exactly this pattern: root ads.txt → build output → served at domain root.
6. Netlify (and similar static hosts)
Publish ads.txt from your publish directory (dist/ in this site’s pipeline — the deploy step copies it explicitly so it can never be forgotten). Watch for two Netlify-specific gotchas: redirect rules that catch /*.txt or force trailing slashes (ads.txt must serve at exactly /ads.txt with HTTP 200 and text/plain), and branch deploys where you verified the wrong URL.
7. AdSense warnings, translated
| Warning | Meaning | Fix |
|---|---|---|
| Earnings at risk — missing file | Crawler got 404 at /ads.txt
|
Publish per §§4–6, purge cache, wait recrawl |
| Unauthorized seller | Impressions attributed to an ID not in your file | Add the missing DIRECT/RESELLER line from that network’s docs |
| No content (empty file) | File exists but parses to zero records | Remove BOM/HTML; one record per line, plain text |
| Wrong domain | File fixed on www but AdSense lists apex (or reverse) |
Serve identical file on both; set the AdSense site entry to match |
Recrawl typically takes 24–72 hours. Past a week with a verified-correct file, the problem is serving (redirects, blocks), not content — re-uploading the same bytes changes nothing.
8. Test accessibility properly
- Browser:
https://yourdomain.com/ads.txtreturns the file, HTTP 200,Content-Type: text/plain. -
http://version andwwwvariant: same content, no redirect chains (one 301 maximum, ideally none). -
curl -s -D - https://yourdomain.com/ads.txt -o /dev/null— read the status and headers yourself at least once. - robots.txt must not disallow the file, and bot-protection (Cloudflare challenge modes, aggressive WAF rules) must not challenge Google’s crawler on this path.
9. Mistakes that cause most warnings
Uploading to a subdirectory (/public/ads.txt instead of root), editing in Word/Docs (smart quotes, BOM, .docx renamed to .txt), theme/plugin overwrites on WordPress updates, CDN caching the 404 from before the fix, and fixing www while AdSense monitors the apex. Check all five before anything exotic.
10. Multi-network maintenance
Each additional network (AdMob uses app-ads.txt for apps — same syntax, app stores instead of web; Meta Audience Network, other resellers) adds its lines from official docs only. Review the file quarterly: remove networks you left (stale RESELLER lines invite unauthorized selling on your name), and keep a one-line changelog comment at the top with the last review date.
11. App publishers: app-ads.txt in 30 seconds
Same syntax, different discovery: app stores (not crawlers) locate it via the developer-website URL on your store listing. This site serves one covering AdMob (google.com, pub-…, DIRECT) plus the Meta Audience Network line. If your store listing points at a different domain than the file lives on, verification fails no matter how correct the content is.
12. Generator: core records from your publisher ID
Enter your pub- ID. This writes the universal Google lines (web + app); add network RESELLER lines from official docs afterward.
# paste your pub ID above, then Generate
Verify: serve the output at /ads.txt (web) and /app-ads.txt (apps), then run §8 checks. Lines use Google's fixed certification ID f08c47fec0942fa0.
Related reading: programmatic advertising (ads.txt/sellers.json fraud checks), website cost guide, hosting vs VPS, and hire a digital marketing expert.


