Every so often a demand partner asks you to add a line to your ads.txt, and nobody explains what that file is or why it exists. Here is the problem it came to solve, how to read what is inside it, how it differs from sellers.json and what breaks when it is wrong.
The fraud ads.txt came to stop
When an advertiser buys an impression in a programmatic auction, they do not see your site. They see a bid request: a package of data that, among other things, states which domain that ad slot comes from. For years nobody checked whether that was true: an intermediary only had to declare someone else's domain to sell inventory that was not theirs and get paid for it. The industry calls it domain spoofing.
The damage went both ways: the advertiser paid quality-publication prices for impressions served somewhere else entirely, and the impersonated publication never saw a cent. Once it was clear there was more inventory for sale than there were real page views, the industry needed a way for every publisher to state publicly who may sell on their behalf. That way is ads.txt.
ads.txt does not stop anyone from lying about your inventory. What it does is turn that lie into something you can check in a second.
What ads.txt actually is
The name comes from Authorized Digital Sellers. It is a plain text file placed at the root of your domain and served at that exact address: example-news.com/ads.txt. Not in a subfolder, not in an admin panel, and not dependent on your CMS. It is a file that gets downloaded and read.
Inside there is one line for each platform authorised to sell your inventory. It is public on purpose: anyone can open it in a browser. Buyers crawl it with bots and build their own list of who can sell what. When a bid reaches them claiming to come from your domain through an intermediary that is not in your file, they discard it.
It helps to understand what it is not. The file grants no technical permissions and revokes none: nothing stops working because you edited it. It is a declaration, and what signs it is being published on your own domain, which is what a third party cannot fake.
How to read a line of ads.txt
A typical line looks like this: ssp-example.com, 12345, DIRECT, f1a2b3c4d5e6f7a8. Four fields separated by commas, each answering a different question.
- The advertising system domain. Not the SSP's brand name, but the domain where the buying takes place; the platform always tells you which one, because it does not always match their corporate website.
- The publisher ID. Your account identifier inside that platform: it is what separates your inventory from that of any other publication using the same SSP.
- The relationship: DIRECT or RESELLER. It is mandatory and states whether that platform works with an account of yours or resells your inventory through one of its own.
- The certification ID, optional. It identifies that company in the TAG (Trustworthy Accountability Group) registry and confirms that the declared domain belongs to who it claims to be.
The order of the lines means nothing: it is a list, not a waterfall. Lines starting with a hash are comments and get ignored. There are also variable lines, such as CONTACT= to leave a reference email or OWNERDOMAIN= to declare the real owner of the site.
DIRECT and RESELLER: what sets them apart
DIRECT means you have a direct contractual relationship with that platform and that the account named in the second field is yours. RESELLER means you have authorised that platform to resell your inventory even though the account is not in your name. That is the normal case when you work with a monetisation partner that connects you to demand through its own accounts across several SSPs.
The distinction matters to the buyer, because a chain with several resellers stacked in it has more hands along the way and more commission before the money reaches you. And there is nothing to gain from dressing it up: marking as DIRECT something that is RESELLER improves nothing, because that ID is cross-checked against the platform's sellers.json and the contradiction shows up on its own.
sellers.json: the other half of the chain
ads.txt looks outward from the publication: it says who I authorise to sell. sellers.json looks the other way, from the platform: it says who I represent. Every SSP or exchange publishes it at the root of its own domain, at ssp-example.com/sellers.json, and the platform maintains it. You do not edit it, but you can read it, and it is worth doing.
The format is JSON, not plain text. Each entry ties a seller identifier to who that seller really is: name, domain and type. The type can be PUBLISHER, if the account belongs to the owner of the inventory; INTERMEDIARY, if it resells someone else's; or BOTH. There are also entries marked confidential, with no visible name or domain: it is allowed, and it is the point where the chain stops being auditable.
The two files are read together, and that is the whole point. Your ads.txt says ssp-example.com may sell for you under ID 12345; the sellers.json at ssp-example.com must say that ID corresponds to your domain. If they match, the buyer reconstructs the entire chain from advertiser to you. If they do not, the bid loses value or is dropped.
What happens when it is missing or wrong
- There is no file. Buyers that only accept authorised inventory stop bidding on you: the inventory does not disappear, but it is left competing for the cheapest budgets.
- A new partner's line is missing. The demand it connects gets discarded for having no backing in your file, and it shows up as a low fill rate with no obvious cause.
- There is a syntax error. One comma too many invalidates that whole line; the rest of the file is still read. It is the quietest failure of them all.
- The file never arrives. It returns a 404, redirects to another domain or gets blocked by a firewall when the crawler shows up. To the buyer it is the same as not existing.
- Old lines are left in. A partner you stopped working with a year ago is still authorised to sell on your behalf for as long as its line sits there.
None of these cases produces a visible error. The site loads the same, the ads look the same, and no alert goes off. The only place the problem surfaces is in the revenue, several weeks later.
app-ads.txt: the same thing for apps
A mobile or connected TV app has no domain root to put a file in, so the mechanism takes a detour: the crawler goes to the app's store listing, reads the website the developer declared there and looks for the file at the root of that domain: example-apps.com/app-ads.txt. The line format is identical.
That is why the most frequent failure is not in the content of the file but in the route to it: the store listing points to a domain that does not serve it, or declares none at all. And if you have both a site and an app, these are two separate files with two separate lists; ads.txt does not cover the app and app-ads.txt does not cover the site.
Why they have to be kept current
This is not written once and forgotten. Every partner you add is a new line and every one you drop is a line too many. There is also a lag: buyers do not re-read your file every day, so several days can pass between publishing a line and it taking effect. The line goes in before the partner starts selling, not after.
When monetisation runs through a partner, that list is theirs to maintain. At ADEQ Media we manage the ads.txt and sellers.json of the publications we work with, so that connecting premium demand through Header Bidding with SmartTag, or switching on direct campaigns, does not depend on somebody remembering to edit a file. With a single Header Script and a 48-hour implementation, that part is settled from day one.
Even when it is delegated, there is a half-minute check worth doing now and then: open yourdomain.com/ads.txt in a browser and look at what comes back. If that list does not resemble the set of partners selling your inventory today, there is your pending work.
What could your inventory earn?
We analyse your site and tell you what can be improved. No commitment.
Evaluate your site