If a buyer cannot prove that the impression they are bidding on actually belongs to you, they have two choices: bid less to price in the risk, or not bid at all. That single sentence explains why supply chain transparency stopped being a compliance chore and became a revenue lever. Three IAB Tech Lab standards — ads.txt, sellers.json, and the SupplyChain object (schain) — exist to remove that uncertainty. They are not competing tools you pick between; they are three parts of one authentication system. This guide explains exactly what each one does, how they interlock, and how to keep yours clean so you stop leaking bids to buyer-side filters.
The problem all three standards solve
Before 2017, a buyer receiving a bid request for example.com had no reliable way to confirm the seller offering it was authorized to sell example.com's inventory. Fraudsters exploited this with domain spoofing — misrepresenting low-value or fabricated inventory as premium sites — and with unauthorized reselling, where an intermediary quietly resold inventory it had no right to touch and skimmed margin along the way.
The response was a chain of public, machine-readable declarations. Publishers declare who is allowed to sell their inventory. Advertising systems declare who they are paying. And every bid request carries a signed record of the hops it passed through. When a buyer can cross-check all three and they agree, the impression is trustworthy. When they disagree, the buyer knows to discount or reject it. That is the entire model.
ads.txt: the publisher's authorization list
ads.txt (Authorized Digital Sellers) is a plain text file you host at the root of your domain — example.com/ads.txt. It is a public whitelist declaring every advertising system authorized to sell your inventory, and the account ID that identifies you inside each of those systems. Buyers and their fraud vendors crawl it constantly.
Each authorization is one line with up to four comma-separated fields, three required and one optional:
- Field 1 — Advertising system domain. The canonical domain of the SSP or exchange, e.g.
google.com. This must match the domain where that system publishes its sellers.json. - Field 2 — Publisher account ID. The seller account ID that identifies you within that system. This is the value a buyer will later match against the system's sellers.json.
- Field 3 — Relationship type. Either
DIRECTorRESELLER(see below). - Field 4 — Certification Authority ID (optional). The advertising system's TAG (Trustworthy Accountability Group) ID, which disambiguates the system when the domain alone is not unique. Google's, for example, is
f08c47fec0942fa0.
A typical line looks like:
google.com, pub-0000000000000000, DIRECT, f08c47fec0942fa0
ads.txt also supports variable records that add context beyond individual authorizations. The most important are OWNERDOMAIN= (declares the entity that owns the domain), MANAGERDOMAIN= (declares an exclusive monetization partner that manages your inventory, and can be scoped by country), SUBDOMAIN= (points crawlers to a subdomain's own ads.txt), and CONTACT=. The OWNERDOMAIN and MANAGERDOMAIN variables were formalized in the ads.txt 1.1 revision and matter for publishers who work through a managed partner rather than selling everything themselves.
DIRECT vs RESELLER — the distinction buyers scrutinize
This flag is where most of the analytical value lives.
- DIRECT means you have a direct contractual relationship with that advertising system and are paid by them for that account. The account ID belongs to you.
- RESELLER means you have authorized another entity — an intermediary or partner — to sell or resell your inventory through their account in that system. You do not hold that relationship directly; you are vouching for a partner who does.
Both are legitimate. But buyers running supply path optimization generally prefer DIRECT paths because they are shorter, cheaper, and carry less counterparty risk. A long tail of RESELLER entries you cannot account for is a red flag — it suggests your inventory is being passed around in ways you may not be monitoring. Every RESELLER line is a statement of trust you are making publicly, so treat each one as a decision, not a default.
app-ads.txt: the same idea for apps and CTV
app-ads.txt extends the standard to mobile apps, OTT, and connected TV, where there is no website root to crawl. Instead, buyers read the developer website URL listed in the app store, then fetch /app-ads.txt from that developer domain. The file format is identical to ads.txt. The critical setup detail: the developer URL in your app store listing must point to the domain that actually hosts the app-ads.txt file, or the whole chain breaks before it starts.
sellers.json: the exchange's side of the mirror
ads.txt only tells half the story. It says "account ID X at google.com is authorized to sell my inventory," but it does not tell a buyer who account ID X actually is. That is what sellers.json provides.
sellers.json is published by the advertising system, not the publisher, at the root of its domain — e.g. google.com/sellers.json. It is a JSON file listing every seller and reseller operating in that system, keyed by seller ID. For each entry it declares:
- seller_id — the account ID that appears in publishers' ads.txt files (field 2 above).
- name — the business name of the seller, unless the entry is marked confidential.
- domain — the seller's own domain.
- seller_type —
PUBLISHER(the seller owns the inventory),INTERMEDIARY(the seller resells others' inventory), orBOTH. - is_confidential — a flag (0 or 1) indicating the system has withheld the seller's name and domain from the public file.
- is_passthrough — a flag indicating the system is not the seller of record but passes the transaction through on another party's behalf.
Now the two files snap together. A buyer takes the seller_id from your ads.txt line, looks it up in that system's sellers.json, and confirms the identity, type, and domain all line up. ads.txt is the publisher's declaration of "who may sell me"; sellers.json is the exchange's declaration of "who I am paying." Read together, they let a buyer verify both ends of a single relationship.
The SupplyChain object: proof at bid time
ads.txt and sellers.json are static files a buyer can crawl on their own schedule. The SupplyChain object — usually called schain — brings that verification into the live bid request itself. Defined by IAB Tech Lab and carried inside OpenRTB, it is an ordered, tamper-evident record of every entity that touched the request on its way from publisher to DSP.
The object has a small, precise shape:
- complete — 1 if every hop from the publisher onward is represented in the object; 0 if the chain is known to be incomplete.
- ver — the schain spec version (e.g. "1.0").
- nodes[] — an ordered array, one node per hop. The first node is closest to the publisher; each subsequent intermediary appends its own.
Each node carries:
- asi — the advertising system identifier: the canonical domain of that hop, matching its sellers.json domain.
- sid — the seller ID for the publisher or upstream party within that system, matching the seller_id in that system's sellers.json and the account ID in the publisher's ads.txt.
- hp — whether this node is part of the payment flow (1 = yes).
- rid, name, domain — optional request ID and identity fields.
The power of schain is that the buyer can validate every node against the static files in real time. For each node: does the asi domain publish a sellers.json? Does that sellers.json contain the sid? And at the publisher end, does the publisher's ads.txt authorize that seller ID at that system with the correct DIRECT/RESELLER type? When complete is 1 and every node validates, the buyer has an unbroken, cryptographically-adjacent proof of the path. When the chain is incomplete or a node fails lookup, the impression looks riskier and is priced or filtered accordingly. In Prebid, the schain module lets you set your own DIRECT node globally while each bidder appends its node, and Prebid Server handles the same construction server-side.
Why buyers pay more for transparent supply
None of this is altruism on the buy side. It is economics. A DSP practicing supply path optimization (SPO) is actively choosing which route to buy the same impression through, and it favors paths that are authorized, short, and cheap. Transparent supply wins on all three counts:
- Lower fraud risk. A validated chain makes spoofing and unauthorized reselling detectable, so the buyer does not have to discount for uncertainty.
- Fewer hidden fees. Every declared hop is a party that may take margin. A short, transparent chain means more of the buyer's spend reaches you — and buyers reward paths where their money is not evaporating into undeclared intermediaries.
- Filter survival. Many DSPs simply will not bid on inventory that is not authorized in ads.txt, or on requests with unresolvable schain nodes. An entry missing from your file is not a smaller bid — often it is no bid at all.
Transparency does not guarantee a higher CPM by itself. But its absence reliably suppresses demand, and a clean, minimal, fully-resolvable chain is one of the few supply-side signals a publisher fully controls.
Common mistakes that quietly cost demand
- Stale RESELLER entries. Partners you no longer work with linger in the file for years, expanding your attack surface and confusing buyer audits.
- Mismatched account IDs. A typo in field 2 means the sellers.json lookup fails and the whole authorization is worthless.
- Wrong advertising system domain. Field 1 must be the canonical sellers.json domain, not a marketing URL or a subdomain.
- app-ads.txt pointing nowhere. The app store developer URL and the hosting domain must match, or CTV and app buyers cannot verify you at all.
- Blocking crawlers. If a firewall, redirect chain, or aggressive bot rule stops verification crawlers from fetching the file, buyers treat you as unauthorized. The file must return a clean 200 over HTTP(S) at the exact root path.
- Redirects and wrong content type. ads.txt should be served as plain text at the root; multi-hop redirects and HTML error pages break parsers.
Practical takeaways
- Treat the three standards as one system. ads.txt authorizes, sellers.json identifies, and schain proves the path at auction time. A gap in any one weakens the other two.
- Audit ads.txt on a schedule, not once. Confirm every line maps to a live relationship, verify each seller ID resolves in the corresponding sellers.json, and delete partners you have dropped.
- Know why every RESELLER line exists. Each one is a public statement of trust — keep only the ones you can defend.
- Prefer DIRECT and short chains. They win supply path optimization and keep more spend flowing to you.
- Verify serving, not just content. Check that
/ads.txt(and/app-ads.txtwhere relevant) returns a clean 200 in plain text, with no redirects and no crawler blocking. - Use
OWNERDOMAINandMANAGERDOMAINwhen a partner manages your inventory so the ownership and management relationship is unambiguous to buyers. - Confirm your schain is complete. A
complete: 1object with every node resolvable is a demand signal you fully control.
Publishers who work with a managed monetization partner should make sure that partner keeps these files correct and current on their behalf — at WeForAds, maintaining accurate ads.txt entries and a complete supply chain is part of how we keep publisher inventory buyable. However you monetize, supply chain hygiene is one of the highest-leverage, lowest-cost things you can do to protect your revenue.