Checking if your ads.txt file is being served correctly means verifying more than simply opening /ads.txt in a browser and seeing some text.
A correctly served ads.txt endpoint should normally satisfy several independent checks:
Correct URL
→ /ads.txt
Reachable from the root domain
→ yes
HTTP response
→ successful
Google recommendation
→ 200 OK
Content-Type
→ text/plain
Content
→ valid ads.txt records
Crawler access
→ not blocked
HTTP / HTTPS behavior
→ consistent and reachable
Redirects
→ valid and intentional
A browser can make a broken configuration appear healthy because it automatically follows redirects, caches previous responses and renders error pages that may still return HTTP 200.
Advertising crawlers do not evaluate the page visually. They evaluate:
- the URL;
- HTTP status;
- redirect chain;
- response headers;
- robots.txt accessibility;
- plain-text contents;
- ads.txt syntax.
This guide explains how to verify that a WordPress ads.txt file is being served correctly, how to inspect its HTTP response, how to identify physical and virtual file conflicts, how to troubleshoot redirects, caching, CDN behavior and robots.txt restrictions, and how to distinguish a technically reachable file from a correctly configured authorized-seller declaration.
What does “served correctly” mean for ads.txt?
An ads.txt implementation has several layers.
1. Discovery
→ crawler finds /ads.txt
2. HTTP delivery
→ server successfully returns it
3. File format
→ plain text is served
4. Syntax
→ records can be parsed
5. Business data
→ seller IDs are correct
A problem at any one of these layers can make the implementation ineffective.
A file can load in your browser and still be wrong
Suppose you open:
https://example.com/ads.txt
and see:
google.com, pub-1234567890123456, DIRECT
That is a useful first check.
It does not prove that:
- the response status is correct;
- the MIME type is correct;
- HTTP also resolves correctly;
- the root domain can discover it;
- robots.txt permits crawling;
- the publisher ID is correct;
- a CDN is not serving stale content;
- another physical file is overriding WordPress;
- Google has already recrawled the file.
Step 1: open the standard ads.txt URL
For a normal domain:
https://example.com
the file should be reachable at:
https://example.com/ads.txt
not:
https://example.com/wp-content/ads.txt
https://example.com/files/ads.txt
https://example.com/ads/ads.txt
https://example.com/ads.txt/
The IAB Tech Lab ads.txt specification defines /ads.txt as the standard relative path.
ads.txt belongs at the root domain
The IAB specification defines the root domain using the registrable-domain concept based on the public suffix.
For a normal website such as:
www.example.com
the root domain is typically:
example.com
and the discovery process starts from:
example.com/ads.txt
Do not confuse the WordPress installation directory with the domain root
WordPress may physically live in:
/var/www/example/public/
or
/public_html/
or
/wordpress/
but advertising crawlers care about the public URL:
https://example.com/ads.txt
not where the corresponding data happens to be stored on the server.
ads.txt does not need to be a physical file
The IAB specification explicitly allows the /ads.txt resource to be generated without originating from a physical filesystem file.
That means WordPress can legitimately serve:
/ads.txt
through:
- a rewrite rule;
- a plugin;
- application logic;
- a reverse proxy;
- a dynamically generated response.
The public HTTP behavior matters more than whether:
ads.txt
exists as a literal file on disk.
TheOneWP Ads.txt & App-ads.txt Editor uses this virtual-file approach to expose the saved content at the standard public URLs.
Step 2: check the HTTP status code
Do not stop at the browser.
Inspect the HTTP response directly.
With curl:
curl -i https://example.com/ads.txt
A healthy response may begin with:
HTTP/2 200
content-type: text/plain; charset=UTF-8
followed by the ads.txt content.
Google recommends HTTP 200 OK
Google’s official ads.txt crawler troubleshooting documentation recommends that the ads.txt endpoint return:
200 OK
This is the simplest response for a final canonical ads.txt resource.
The IAB specification accepts successful 2xx responses
The current IAB ads.txt specification describes successful:
HTTP 2xx
responses as readable ads.txt resources.
For practical WordPress deployments, however, returning:
200 OK
for the final resource is the clearest configuration and aligns with Google’s troubleshooting recommendations.
A 404 means the resource was not found
If:
curl -i https://example.com/ads.txt
returns:
HTTP/2 404
the file is not being served at that URL.
Common causes include:
- no physical file exists;
- the WordPress virtual endpoint is not active;
- rewrite rules were not registered;
- the WordPress module is disabled;
- no ads.txt content has been configured;
- the request is reaching the wrong virtual host.
A 200 response can still be a soft 404
A poorly configured server might return:
HTTP 200
while the body contains:
<html>
<h1>Page not found</h1>
</html>
That is not a valid ads.txt response.
Always inspect:
status
+
headers
+
body
Check the response body
The body should contain ads.txt records, comments or supported variable declarations.
A normal seller record has the structure:
advertising-system-domain,
publisher-account-id,
relationship,
optional-certification-id
For example:
example-ad-system.com, 123456, DIRECT
or:
example-ad-system.com, 123456, RESELLER
For the complete setup process, see How to Set Up ads.txt for WordPress.
Step 3: verify the Content-Type
The ads.txt specification defines the resource as plain text.
The expected response header is:
Content-Type: text/plain
A UTF-8 charset can also be declared:
Content-Type:
text/plain; charset=utf-8
Check headers without printing the complete body
You can use:
curl -sS \
-D - \
https://example.com/ads.txt \
-o /dev/null
Look for:
HTTP/2 200
content-type: text/plain
Why not rely only on curl -I?
You will often see:
curl -I https://example.com/ads.txt
recommended for header testing.
This sends an HTTP:
HEAD
request rather than a normal:
GET
request.
Well-configured servers should normally return equivalent metadata, but applications and proxies can occasionally handle HEAD differently.
For definitive testing, use a normal GET request and inspect its headers.
HTML is not valid ads.txt output
If the response starts with:
<!doctype html>
or:
<html>
something is wrong.
Possible causes include:
- WordPress serving a theme template;
- a 404 template returning 200;
- a security challenge;
- a maintenance page;
- a login page;
- a CDN challenge;
- an incorrect redirect destination.
Do not serve ads.txt through a normal WordPress Page
Creating a WordPress Page called:
ads.txt
is not equivalent to serving a proper ads.txt resource if WordPress renders the page using the normal theme.
A theme response may contain:
HTML
header
navigation
footer
scripts
styles
ads.txt needs a plain-text endpoint.
Step 4: inspect redirects
Your browser may silently follow:
http://example.com/ads.txt
↓
https://example.com/ads.txt
↓
https://www.example.com/ads.txt
and show only the final file.
Inspect the chain explicitly.
Use curl to follow redirects
curl -L -i \
http://example.com/ads.txt
The:
-L
option tells curl to follow redirects.
Inspect only the redirect headers
curl -sS \
-L \
-D - \
http://example.com/ads.txt \
-o /dev/null
You might see:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/ads.txt
HTTP/2 200
Content-Type: text/plain
This is a normal HTTP-to-HTTPS redirect pattern.
Redirects inside the same root domain are supported
The ads.txt 1.1 specification allows redirects that remain within the original root-domain scope.
This makes configurations such as:
example.com/ads.txt
↓
www.example.com/ads.txt
possible when correctly implemented.
External redirects have stricter rules
The IAB specification permits only a single redirect outside the original root domain for delegation to another web server.
If that external destination then redirects again, the response should be treated as an error by compliant consuming systems.
Therefore this deserves scrutiny:
example.com/ads.txt
↓
thirdparty.example/ads.txt
↓
other.example/ads.txt
Keep the redirect path simple
For most WordPress websites, the cleanest configuration is:
http://example.com/ads.txt
↓
https://example.com/ads.txt
↓
200 plain text
or:
example.com/ads.txt
↓
www.example.com/ads.txt
↓
200 plain text
A complicated redirect chain provides very little benefit.
Step 5: test the apex domain and www separately
Suppose the main website uses:
https://www.example.com/
Do not test only:
https://www.example.com/ads.txt
Also test:
https://example.com/ads.txt
Google specifically notes that discovery begins from the root domain.
If www hosts the file, the root domain should reach it
A common working architecture is:
https://example.com/ads.txt
↓
301
↓
https://www.example.com/ads.txt
↓
200
If instead:
https://example.com/ads.txt
→ 404
while:
https://www.example.com/ads.txt
→ 200
some crawlers may have difficulty discovering the intended file.
Test all relevant host variants
A useful checklist is:
https://example.com/ads.txt
https://www.example.com/ads.txt
http://example.com/ads.txt
http://www.example.com/ads.txt
Not every version needs to return the file directly.
They should resolve predictably to the canonical implementation where appropriate.
Step 6: test both HTTP and HTTPS
Google’s ads.txt crawler documentation recommends ensuring that the resource is reachable through both:
HTTP
and
HTTPS
This does not mean maintaining separate files.
A normal secure website should usually redirect:
HTTP
↓
HTTPS
Example
http://example.com/ads.txt
↓
301
https://example.com/ads.txt
↓
200
That provides one canonical ads.txt response while still allowing the HTTP URL to resolve.
Check HTTPS certificate behavior
If:
https://example.com/ads.txt
fails because of:
- expired certificate;
- hostname mismatch;
- broken TLS chain;
- unsupported TLS configuration;
the file is not reliably accessible even if HTTP works.
Use curl to detect TLS problems
curl -v \
https://example.com/ads.txt
Do not use:
-k
as your normal verification method because that tells curl to ignore certificate validation errors.
If the endpoint only works with:
curl -k
fix the TLS configuration.
Step 7: confirm robots.txt does not block ads.txt
Open:
https://example.com/robots.txt
and review the crawl directives.
Google warns that an ads.txt resource can be ignored when crawling is disallowed by robots.txt.
Example of a problematic rule
User-agent: *
Disallow: /ads
That path can match:
/ads.txt
and interfere with crawler access.
Also check crawler-specific rules
A robots.txt file could contain:
User-agent: Googlebot
Disallow: /
or another rule affecting the crawler involved in discovery.
The exact effect depends on the crawler and rule set.
For the wider role of robots.txt, see What Is robots.txt and Why Does It Matter for SEO?.
WordPress can serve robots.txt virtually too
Just as ads.txt does not need to be a physical file, WordPress can provide a virtual robots.txt response.
Physical and virtual resources can interact differently with the web server.
See WordPress’s Virtual robots.txt vs. a Physical File for the same architectural distinction applied to robots.txt.
Step 8: verify the file is actually plain text
A normal ads.txt body might look like:
# Authorized advertising systems
example-ad-system.com, 123456, DIRECT
another-system.example, abc789, RESELLER
It should not contain:
<p>
<br>
<div>
<html>
<script>
<style>
Do not paste rich-text formatting into ads.txt
Google specifically recommends using plain text because rich-text editors can introduce:
- unexpected formatting;
- invalid characters;
- non-standard whitespace;
- hidden metadata.
Use a plain-text editor or a dedicated ads.txt editor.
Check for invalid characters
Invisible characters can be difficult to identify visually.
Potential problems include:
- non-breaking spaces;
- smart punctuation;
- invalid UTF-8 sequences;
- unexpected control characters.
Inspect the raw response
Download it:
curl -sS \
https://example.com/ads.txt \
-o ads.txt
Then inspect the file in a plain-text or code editor.
Check UTF-8 where necessary
The IAB specification states that:
text/plain; charset=utf-8
can be used to explicitly signal UTF-8 support.
Simple ASCII-compatible seller records generally avoid encoding complexity entirely.
Step 9: validate each seller line
A technically perfect HTTP endpoint can still contain invalid ads.txt records.
The primary record structure is:
FIELD 1
Advertising system domain
FIELD 2
Publisher account ID
FIELD 3
DIRECT or RESELLER
FIELD 4
Optional certification authority ID
Example
google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0
Do not copy that placeholder publisher ID into production.
Your actual advertising platform must provide the seller-account identifier you should publish.
Field 1: advertising system domain
The first field should identify the canonical domain of the advertising system.
For example:
google.com
Do not replace it with:
- your own website domain;
- an arbitrary corporate homepage;
- the ad network’s dashboard URL;
- a URL containing
https://.
Field 2: publisher account ID
The second field identifies the relevant seller or publisher account inside the advertising system.
This value must match what the platform expects.
For Google AdSense, Google tells publishers to compare the value against the publisher ID shown in their AdSense account.
A typo in the ID is not an HTTP problem
This file:
google.com, pub-WRONG-ID, DIRECT
can still return:
200 OK
Content-Type: text/plain
and remain semantically wrong.
This is why delivery verification and content verification are separate tasks.
Field 3: DIRECT vs RESELLER
The IAB specification defines:
DIRECT
when the publisher directly controls the account represented in field 2 on the advertising system.
It defines:
RESELLER
when another entity is authorized to control that seller account and resell the inventory.
Do not guess this field.
Use the line supplied or documented by the advertising partner.
Field 4 is optional
The fourth field can contain a certification authority identifier associated with the advertising system.
A three-field line can therefore be valid:
example.com, 12345, DIRECT
as can a correctly populated four-field record:
example.com, 12345, DIRECT, abcdef123456
Comments are supported
Lines beginning with:
#
are treated as comments.
For example:
# Google
google.com, pub-1234567890123456, DIRECT
Comments can make larger files easier for administrators to maintain.
Comments do not authorize sellers
This:
# google.com, pub-1234567890123456, DIRECT
is a comment.
It is not an active seller record.
ads.txt 1.1 also supports variable declarations
The current IAB standard supports declarations including:
OWNERDOMAIN=
MANAGERDOMAIN=
These are separate from ordinary authorized-seller records.
Use them only when they accurately describe your inventory ownership or management structure.
Step 10: check for duplicate or conflicting entries
Large ads.txt files can accumulate duplicate lines over time.
For example:
example.com, 123, DIRECT
example.com, 123, DIRECT
A duplicate may not necessarily make the complete file unreadable, but it adds unnecessary maintenance noise.
Conflicting relationship values deserve investigation
This is more concerning:
example.com, 123, DIRECT
example.com, 123, RESELLER
Determine which relationship is actually correct.
Do not automatically deduplicate by account ID alone
Different advertising systems can use similar or identical account-ID formats.
Treat the record as a combination of:
advertising system
+
account ID
+
relationship
rather than comparing field 2 in isolation.
Step 11: compare the live response with what you saved
This is particularly important on WordPress.
Suppose your administration screen contains:
google.com, pub-NEW-ID, DIRECT
but the public endpoint still shows:
google.com, pub-OLD-ID, DIRECT
The editor may be working perfectly while another delivery layer serves stale or conflicting content.
Possible causes include a physical ads.txt file
A web server usually serves a real:
/ads.txt
file before the request ever reaches WordPress rewrite logic.
This can create:
WordPress editor
→ new content
physical ads.txt
→ old content
public request
→ physical file wins
Check the WordPress document root
Look for a real file named:
ads.txt
in the public WordPress root.
Common locations include:
/public_html/ads.txt
/htdocs/ads.txt
/public/ads.txt
depending on hosting configuration.
TheOneWP checks for a physical file conflict
TheOneWP Ads.txt & App-ads.txt Editor serves its configured content virtually.
When a physical:
ads.txt
or:
app-ads.txt
exists in the WordPress root, the web server can serve that physical resource before WordPress handles the request.
The module therefore treats physical-file presence as a conflict that should be resolved before relying on its virtual endpoint.
Decide who owns ads.txt
A site should have a clear source of truth:
physical file
or
WordPress virtual endpoint
not:
physical file
+
plugin A
+
plugin B
+
CDN rule
+
hosting injection
all competing for the same URL.
Step 12: check WordPress rewrite rules
A virtual ads.txt implementation generally depends on WordPress receiving:
/ads.txt
and identifying the request through its rewrite system.
If the endpoint returns 404 after enabling a virtual implementation, investigate:
- permalink rules;
- server rewrite configuration;
- module activation;
- physical-file conflicts;
- WordPress root location.
Do not flush rewrite rules on every request
A plugin that adds a virtual endpoint may need to flush rewrite rules when the endpoint is first introduced.
It should not call:
flush_rewrite_rules()
on every page load.
That operation is comparatively expensive and unnecessary once rules are registered.
TheOneWP schedules its required rewrite refresh
The Ads.txt & App-ads.txt Editor uses dedicated rewrite rules for:
/ads.txt
/app-ads.txt
and handles the necessary rewrite refresh as an administrative lifecycle operation rather than continuously flushing rules on every request.
Step 13: check CDN caching
A CDN can continue serving an older ads.txt response after WordPress has already saved the new one.
The sequence can be:
WordPress updated
↓
origin response updated
↓
CDN still cached
↓
public ads.txt remains old
Inspect cache-related headers
Depending on the CDN, you may see headers such as:
Age:
X-Cache:
CF-Cache-Status:
Cache-Control:
ETag:
Last-Modified:
These headers can help identify whether the response is being served from cache.
Example
HTTP/2 200
content-type: text/plain
cf-cache-status: HIT
age: 2800
A:
HIT
or substantial:
Age
value can indicate that the edge is returning a cached copy.
Purge the specific ads.txt URL when possible
Instead of purging the entire website cache, invalidate:
https://example.com/ads.txt
when the CDN supports URL-specific purging.
Do not disable caching permanently without a reason
ads.txt is a small public resource that can generally be cached.
The problem is not caching itself.
The problem is:
serving stale content
after an intentional update
Check page-cache plugins too
A WordPress cache plugin may cache:
/ads.txt
even if no external CDN is involved.
After changing the file, test from:
- a logged-out browser;
- curl;
- an external network;
- a private browsing session.
Do not trust the logged-in administrator response alone
Many cache systems bypass cache for logged-in administrators.
You may see:
new ads.txt
as administrator
while anonymous crawlers receive:
old ads.txt
from cache
Test as an anonymous client
curl is useful because it does not carry your normal WordPress authentication cookies:
curl -sS \
https://example.com/ads.txt
Step 14: compare CDN and origin when necessary
Advanced troubleshooting may require determining whether the stale response comes from:
- WordPress;
- the origin web server;
- the CDN edge.
If you know the origin IP and direct origin access is supported, curl can temporarily resolve the production hostname to that IP:
curl \
--resolve example.com:443:203.0.113.10 \
https://example.com/ads.txt
This keeps the hostname:
example.com
while connecting to the selected IP.
Use origin testing carefully
This technique only works correctly when:
- the origin accepts direct traffic;
- the TLS certificate matches the hostname;
- the virtual host is configured correctly;
- the origin is not intentionally protected behind the CDN.
Do not weaken origin security simply to run this test.
Step 15: check security and maintenance layers
A security plugin, firewall or maintenance system can intercept:
/ads.txt
before the intended response is returned.
Possible outcomes include:
403 Forbidden
401 Unauthorized
503 Service Unavailable
CAPTCHA page
JavaScript challenge
maintenance HTML
ads.txt must remain publicly accessible
An advertising crawler cannot complete normal discovery if the endpoint requires:
- WordPress login;
- HTTP Basic Authentication;
- a CAPTCHA;
- a JavaScript challenge;
- an allowlisted browser cookie.
Be careful with staging password protection
A staging environment can reasonably require authentication.
A production ads.txt endpoint intended for advertising discovery cannot rely on a crawler successfully passing that authentication barrier.
Do not apply site-wide challenges blindly
A WAF rule may challenge unfamiliar automated user agents.
If that same policy affects legitimate advertising crawlers, the ads.txt endpoint becomes inaccessible.
Step 16: verify case and filename exactly
The expected path is:
/ads.txt
Use lowercase.
Do not rely on:
/Ads.txt
/ADS.TXT
/ads.TXT
because URL and filesystem case behavior can vary across servers.
Do not accidentally publish ads.txt.txt
Some desktop systems hide known file extensions.
A file visually named:
ads.txt
may physically be:
ads.txt.txt
Verify the actual filename when uploading manually.
Step 17: check for a trailing slash redirect
The standard endpoint is:
/ads.txt
not:
/ads.txt/
If WordPress or another canonicalization rule redirects:
/ads.txt
↓
/ads.txt/
inspect why.
A text-file endpoint should generally retain its file-style URL.
Generic WordPress redirects can accidentally affect ads.txt
Redirect managers and canonicalization systems sometimes contain broad patterns such as:
everything without slash
→ add slash
or:
all missing URLs
→ homepage
Those rules can interfere with special root-level resources.
TheOneWP Redirect Manager addresses URL redirects as a separate layer and should be reviewed when debugging unexpected redirect behavior.
Check the complete redirect chain
A browser ending at:
/ads.txt
does not tell you whether the request took:
1 hop
or
8 hops
Use curl or another HTTP diagnostic tool.
Step 18: check HTTP status codes individually
Common responses mean different things.
200 OK
Resource successfully served.
This is the normal desired final response.
301 Moved Permanently
Permanent redirect.
Often appropriate for:
HTTP → HTTPS
or:
apex → www
302 Found
A temporary redirect.
It may be followed by crawlers where permitted by the ads.txt redirect rules, but permanent canonical changes are usually clearer with the appropriate permanent status.
307 Temporary Redirect
Another temporary redirect type recognized by the ads.txt specification.
401 Unauthorized
The resource requires authorization.
This is unsuitable for a normally public ads.txt deployment.
403 Forbidden
The server understands the request but refuses access.
Check:
- WAF;
- filesystem permissions;
- security plugins;
- server rules.
404 Not Found
No ads.txt resource is being served at the requested URL.
500 Internal Server Error
The server or WordPress failed while processing the request.
Inspect:
- PHP errors;
- plugin conflicts;
- rewrite handlers;
- server logs.
503 Service Unavailable
The resource is temporarily unavailable.
This may come from:
- maintenance mode;
- origin failure;
- server overload;
- CDN protection.
For a broader explanation of responses, see HTTP Status Codes for WordPress Sites, Explained.
Step 19: verify redirects do not terminate on the homepage
A common WordPress mistake is:
unknown URL
↓
301
↓
homepage
If:
/ads.txt
does not actually exist and gets redirected to:
/
the endpoint is not properly serving ads.txt.
The fact that the final request returns:
200
does not fix the missing resource.
Check final Content-Type after redirects
You may have:
/ads.txt
↓
301
↓
homepage
↓
200 text/html
which is clearly not equivalent to:
/ads.txt
↓
200 text/plain
Step 20: check that the live content matches the ad platform
For Google AdSense, compare the exact seller line provided by the account with the live ads.txt output.
Check:
- advertising-system domain;
- publisher ID;
- DIRECT or RESELLER;
- certification ID when supplied.
Publisher ID mismatches are common
For example:
AdSense account:
pub-1234567890123456
Live ads.txt:
pub-1234567890123457
The file is technically served correctly.
The account declaration is wrong.
Do not manually modify seller IDs unless the provider instructs you to
Advertising platforms provide the exact records expected for their systems.
Use those records rather than attempting to infer values from:
- account names;
- customer IDs;
- analytics IDs;
- website IDs;
- ad-unit IDs.
Step 21: understand propagation delay
After fixing ads.txt, an advertising platform may not recognize the change immediately.
Google states that changes can take:
a few days
to appear in AdSense.
For low-traffic sites, Google notes that the process can sometimes take:
up to a month
because the file may be crawled less frequently.
Do not keep editing a correct file while waiting
If the live endpoint already returns:
correct URL
+
200 OK
+
text/plain
+
correct publisher record
repeatedly changing the file will not force immediate platform recognition and can complicate troubleshooting.
Separate serving status from crawler status
There are two different questions:
Question 1:
Is my server correctly
serving ads.txt?
Question 2:
Has the advertising platform
already recrawled it?
You can verify the first immediately.
You may need to wait for the second.
Use the Google ads.txt troubleshooter when relevant
Google provides an official ads.txt troubleshooting tool for publishers using AdSense.
It walks through checks including:
- whether
/ads.txtis reachable; - whether the publisher ID matches;
- whether robots.txt blocks crawling;
- whether domain redirects are correct;
- whether HTTP and HTTPS versions are reachable.
Step 22: distinguish ads.txt from app-ads.txt
The two files use related syntax but serve different inventory environments.
ads.txt
→ website advertising inventory
app-ads.txt
→ app advertising inventory
They should not be confused merely because their line format is similar.
See ads.txt vs app-ads.txt: What’s the Difference?.
Do not rename app-ads.txt to ads.txt
If an advertising platform specifically requires:
app-ads.txt
publishing the same content only at:
/ads.txt
does not create the expected app resource.
Test app-ads.txt independently
When the site requires both, verify:
https://example.com/ads.txt
https://example.com/app-ads.txt
independently.
TheOneWP keeps the two resources separate
The Ads.txt & App-ads.txt Editor stores and serves ads.txt and app-ads.txt as independent resources.
This avoids treating one file as an alias of the other.
What happens when TheOneWP ads.txt content is empty?
The virtual endpoint should represent an intentionally configured resource rather than a meaningless blank response.
The current TheOneWP implementation treats an empty saved ads.txt value as not configured, allowing normal WordPress 404 handling rather than serving a blank virtual file.
Do not confuse an empty HTTP 200 file with a configured seller list
The ads.txt specification has specific handling for publishers that intentionally declare no authorized advertising systems.
Historically, completely empty files created ambiguity.
The current IAB specification defines a properly formatted placeholder mechanism for that special case.
If your intention is simply:
ads.txt has not been configured yet
a normal missing resource and an explicit no-authorized-sellers declaration are not conceptually the same thing.
Checking ads.txt from outside your network
Testing from your own office connection is useful.
An external crawler may encounter different infrastructure because of:
- regional CDN edges;
- firewall rules;
- geographic restrictions;
- IPv6 routing;
- bot-management rules.
Use an external network when troubleshooting unexplained crawler failures
Possible tests include:
- mobile data;
- a remote server;
- another geographic network;
- a reputable HTTP diagnostic service.
The goal is to confirm the public endpoint behaves consistently outside your normal authenticated network.
Check IPv4 and IPv6 when the domain publishes both
If DNS contains both:
A
and
AAAA
records, different clients can reach different network paths.
A misconfigured IPv6 virtual host can create:
IPv4
→ 200 ads.txt
IPv6
→ 404
or another inconsistent result.
Force IPv4 with curl
curl -4 -i \
https://example.com/ads.txt
Force IPv6 with curl
curl -6 -i \
https://example.com/ads.txt
If IPv6 is advertised but the test fails, investigate the network or server configuration.
Check DNS after migrations
An ads.txt issue appearing immediately after a migration may have nothing to do with WordPress.
Possible causes include:
- old DNS records;
- mixed origin servers;
- stale CDN configuration;
- different www and apex destinations;
- incomplete IPv6 migration.
Different origins can serve different ads.txt files
During migration, you might accidentally have:
Server A
→ new ads.txt
Server B
→ old ads.txt
If DNS or a load balancer sends requests to both, crawlers can receive inconsistent declarations.
Test repeatedly when load balancing is involved
Run:
curl -sS \
https://example.com/ads.txt
several times and compare the output.
Inconsistent responses can reveal:
- unsynchronized nodes;
- multiple origins;
- cache inconsistency.
Check server access logs
If you need to know whether crawlers are requesting:
/ads.txt
server or CDN access logs can provide evidence.
Look for:
request path
status code
user agent
timestamp
response size
Do not use access logs as proof that the content was valid
A log line such as:
GET /ads.txt 200
proves that a request received status 200.
It does not prove that the response contained:
correct publisher ID
+
valid syntax
+
text/plain
Check both request and response quality
Access log
→ did crawler reach it?
HTTP inspection
→ how was it served?
Content validation
→ what did it contain?
Check redirects through logs too
If a crawler requests:
/ads.txt
and receives:
301
the redirect access log can help reveal the next step.
See Reading a Redirect Access Log when redirect behavior needs deeper analysis.
Do not block ads.txt with maintenance mode
Some maintenance tools intercept nearly every frontend request.
That can transform:
/ads.txt
into:
503 maintenance page
or:
200 HTML maintenance page
during maintenance windows.
If continuous ads.txt availability matters, configure maintenance rules accordingly.
Do not password-protect the production endpoint
This is particularly common after staging-to-production migrations.
A leftover:
HTTP Basic Auth
configuration can make the entire site or endpoint return:
401 Unauthorized
to crawlers.
Do not redirect ads.txt to a login page
This response:
/ads.txt
↓
302
↓
/wp-login.php
↓
200 text/html
is not a valid public ads.txt deployment.
Do not add noindex and assume it matters
ads.txt is not a normal HTML document intended for search-engine indexing.
The important controls are:
- public accessibility;
- HTTP behavior;
- crawler access;
- correct content.
HTML SEO meta directives are not the mechanism used to manage this resource.
Do not add a canonical tag
A plain-text ads.txt resource does not need:
<link rel="canonical">
That would require inserting HTML into a plain-text protocol resource.
Do not include ads.txt in the XML sitemap
An XML sitemap exists to describe crawlable site URLs for search engines.
ads.txt has its own standard discovery location.
Adding:
/ads.txt
to your SEO XML sitemap is unnecessary.
TheOneWP XML Sitemap handles a completely different machine-readable resource.
Root-level machine-readable resources should remain independent
A WordPress installation can expose:
/robots.txt
/ads.txt
/app-ads.txt
sitemap URLs
but each follows a different specification and purpose.
TheOneWP Robots.txt Editor manages crawler instructions, while the Ads.txt & App-ads.txt Editor manages authorized advertising sellers.
A practical curl verification sequence
Start with the canonical HTTPS URL:
curl -i \
https://example.com/ads.txt
Then check the root HTTP version:
curl -L -i \
http://example.com/ads.txt
Then test www when relevant:
curl -L -i \
https://www.example.com/ads.txt
Finally retrieve only the body:
curl -sS \
https://example.com/ads.txt
A healthy result might look like
HTTP/2 200
content-type: text/plain; charset=UTF-8
cache-control: public, max-age=3600
google.com, pub-1234567890123456, DIRECT, f08c47fec0942fa0
The exact caching headers can vary.
The important core signals are:
successful response
+
plain text
+
valid content
Example: wrong Content-Type
HTTP/2 200
content-type: text/html
google.com, pub-1234567890123456, DIRECT
The body visually resembles ads.txt, but the MIME type does not match the ads.txt specification.
Example: soft 404
HTTP/2 200
content-type: text/html
<h1>Sorry, page not found</h1>
This is not a valid ads.txt response.
Example: stale physical file
WordPress editor:
google.com, pub-NEW, DIRECT
Public /ads.txt:
google.com, pub-OLD, DIRECT
Check:
- physical file;
- CDN cache;
- page cache;
- multiple origins.
Example: apex-domain problem
https://www.example.com/ads.txt
→ 200
https://example.com/ads.txt
→ 404
Configure the root domain so the ads.txt discovery path reaches the intended resource.
Example: HTTP problem
https://example.com/ads.txt
→ 200
http://example.com/ads.txt
→ 404
Google recommends making both protocols reachable, normally by redirecting HTTP to the working HTTPS URL.
Example: robots.txt problem
User-agent: *
Disallow: /ads
Review the directive because it can prevent crawlers that respect robots.txt from retrieving the ads.txt path.
Example: security challenge
HTTP/2 403
Checking your browser...
The firewall or bot-management configuration is interfering with public crawler access.
Example: redirect to homepage
/ads.txt
↓
301
↓
/
↓
200 text/html
This does not constitute a working ads.txt resource.
Example: correct server, wrong seller data
HTTP/2 200
Content-Type: text/plain
google.com, pub-WRONG, DIRECT
HTTP delivery is healthy.
Advertising configuration is not.
WordPress troubleshooting order
When ads.txt is not working on WordPress, use this sequence:
1. Open /ads.txt
2. Check HTTP status
3. Check Content-Type
4. Check response body
5. Check apex and www
6. Check HTTP and HTTPS
7. Check robots.txt
8. Check redirects
9. Check physical ads.txt
10. Check WordPress virtual endpoint
11. Check page cache
12. Check CDN cache
13. Check firewall / bot rules
14. Compare seller ID
15. Wait for recrawl
Do not start by reinstalling WordPress
An ads.txt delivery problem is normally much narrower than a broken WordPress installation.
Identify the failing layer first.
Do not start by flushing every cache repeatedly
Check whether the public response is actually stale.
If the wrong content comes directly from the origin, repeatedly purging the CDN will not repair the source.
Do not keep changing seller records during troubleshooting
Separate:
transport debugging
from
content editing
First make sure one known test version is served consistently.
Then validate the actual seller declarations.
Do not create multiple competing ads.txt implementations
If one plugin does not appear to work, installing three more ads.txt plugins can create:
- rewrite conflicts;
- unclear ownership;
- stale options;
- different output depending on request order.
Use one source of truth.
Do not forget hosting-level ads.txt systems
Some advertising platforms, hosting systems or managed-site products can inject ads.txt outside WordPress.
If WordPress output does not match your settings, investigate the complete hosting stack.
Do not assume the file is correct because AdSense stopped showing an alert
An advertising platform’s status can lag behind the live endpoint.
Your own HTTP verification should remain independently reproducible.
Do not assume the file is wrong because AdSense still shows an alert immediately after a fix
Crawler recognition is not instantaneous.
Once the server response is demonstrably correct, allow time for recrawling.
How TheOneWP simplifies ads.txt delivery
TheOneWP Ads.txt & App-ads.txt Editor provides separate editors for:
ads.txt
app-ads.txt
and publishes configured content through the standard root-level URLs.
Virtual delivery avoids manual FTP editing
Instead of maintaining:
/public_html/ads.txt
manually, the configured text can be stored inside WordPress and served through the virtual endpoint.
Physical files still take precedence at the web-server layer
If a real:
ads.txt
exists in the public WordPress root, the server can return it before WordPress receives the request.
That is why checking for a physical file is part of the module workflow.
Saved output should always be verified publicly
The administration screen is only the configuration layer.
The authoritative verification target is:
https://your-domain.example/ads.txt
because that is what advertising crawlers see.
Use the same principle for app-ads.txt
If app inventory is relevant, verify:
https://your-domain.example/app-ads.txt
independently instead of assuming that a working ads.txt endpoint proves the app file works too.
Complete ads.txt verification checklist
- Open
/ads.txton the root domain. - Confirm the final resource returns a successful HTTP response.
- Prefer a final
200 OKresponse. - Verify
Content-Type: text/plain. - Confirm the response body contains plain text rather than HTML.
- Check that the root domain can discover the resource.
- Test the apex domain.
- Test the www hostname when used.
- Test HTTP.
- Test HTTPS.
- Follow and inspect the redirect chain.
- Avoid unnecessary redirect hops.
- Check that redirects stay within permitted ads.txt rules.
- Verify that the final destination still ends in valid ads.txt content.
- Check robots.txt for rules that block the path.
- Check crawler-specific robots.txt directives.
- Verify TLS certificate validity.
- Check for HTTP Basic Authentication.
- Check firewall and bot-management challenges.
- Check maintenance mode.
- Check for a physical
ads.txtfile. - Check for competing WordPress ads.txt plugins.
- Check WordPress rewrite behavior.
- Check for trailing-slash redirects.
- Check global canonical redirects.
- Check page-cache output.
- Check CDN cache status.
- Purge stale ads.txt cache after updates when required.
- Compare origin and CDN responses when necessary.
- Check IPv4 and IPv6 where both are published.
- Check multiple origin nodes after migrations.
- Verify the advertising-system domain in every seller record.
- Verify every publisher or seller account ID.
- Verify DIRECT vs RESELLER.
- Check optional certification IDs when supplied.
- Check supported variable declarations separately.
- Remove accidental rich-text formatting.
- Remove invalid characters.
- Review duplicate records.
- Investigate conflicting records.
- Compare the live file with the advertising platform’s required line.
- Verify ads.txt and app-ads.txt independently.
- Check access logs when crawler activity needs investigation.
- Allow time for advertising platforms to recrawl a corrected file.
Related guides
- How to Set Up ads.txt for WordPress
- ads.txt vs app-ads.txt: What’s the Difference?
- WordPress’s Virtual robots.txt vs. a Physical File
- What Is robots.txt and Why Does It Matter for SEO?
- HTTP Status Codes for WordPress Sites, Explained
- Reading a Redirect Access Log
Final recommendation
The fastest way to verify ads.txt is to stop treating the browser view as the complete test.
Check the endpoint as an HTTP resource:
URL
→ /ads.txt
status
→ 200 OK preferred
Content-Type
→ text/plain
body
→ valid ads.txt records
root-domain discovery
→ works
HTTP / HTTPS
→ works
robots.txt
→ does not block it
redirects
→ valid
seller data
→ matches ad platform
Start with:
curl -i \
https://example.com/ads.txt
Then test:
http://example.com/ads.txt
https://www.example.com/ads.txt
when those variants exist.
If the response is wrong, identify which layer owns the failure:
404
→ endpoint or rewrite problem
HTML response
→ wrong handler or soft 404
old content
→ physical file or cache
403 / challenge
→ security layer
wrong redirect
→ canonicalization problem
correct delivery but wrong ID
→ ads.txt content problem
On WordPress, also verify whether a physical file is overriding a virtual endpoint. A plugin can save the correct content perfectly while the web server continues serving an older physical ads.txt before WordPress is ever involved.
TheOneWP Ads.txt & App-ads.txt Editor provides a virtual WordPress-managed endpoint for both advertising files and explicitly separates their configuration. After every significant change, the final verification should still happen against the public URL rather than only inside wp-admin.
Once the live resource returns the correct plain-text content with a healthy HTTP response, correct root-domain behavior and valid seller IDs, the server-side implementation is working. If an advertising platform still reports an issue immediately afterward, distinguish a crawler-refresh delay from an actual delivery error before changing the file again.

