sellers.json and the SupplyChain object let a buyer trace a bid request back to the entity that gets paid for it. sellers.json is a public file where each ad system lists the sellers it represents. The SupplyChain object rides in the bid request as a list of nodes, one per entity in the payment flow. Matching nodes to files shows who sold the impression.
What does each piece say?
- ads.txt: the publisher names which ad systems may sell its inventory, each marked DIRECT or RESELLER, as described in the ads.txt 1.1 spec.
- sellers.json: each ad system posts /sellers.json. Every seller has a
seller_idand aseller_typeof PUBLISHER, INTERMEDIARY or BOTH, plus a name and domain unless it is marked confidential, according to the sellers.json spec. - SupplyChain: the object sits in
source.schainfor OpenRTB 2.6 or later, and insource.ext.schainfor 2.5. It holdscomplete,nodesandver. Each node must carry an ad system domain (asi) and a seller ID (sid), per the SupplyChain spec.
The sellers.json spec says every ad system listed in ads.txt, and every system named in a schain node, should publish the file. That gives each hop a place to be looked up. It also keeps bid requests small, because seller details can be cached offline instead of sent every time.
A node may carry a request ID (rid), a name and a domain, but the SupplyChain spec says name and domain should be left out when sellers.json already holds them. Domains in both files are root domains, not full URLs.
How do the nodes cross-check each other?
The SupplyChain spec sets the rules for building a chain. A reseller must add its own node, or drop the object. A seller that resells inventory with no chain creates one and sets complete to 0. An originating request sets complete to 1 with a single node. In a complete chain, the first node is the owner of the site or app, and the last node is the entity sending the request.
Three matches follow from the specs:
- Each node’s
asiandsidshould equal the values in ads.txt, per the SupplyChain spec. - Each
sidshould be aseller_idin that ad system’s sellers.json, per the sellers.json spec. - For an INTERMEDIARY entry, the sellers.json
domainshould be the root domain of that seller’s own sellers.json, so the next hop can be found, per the same sellers.json spec.
What does a worked example look like?
The domains publisher.example, ssp.example and reseller.example are placeholders, and so are the IDs. A DSP receives a request for a page on publisher.example. The chain in source.schain has two nodes:
"schain": {"ver": "1.0", "complete": 1, "nodes": [{"asi": "ssp.example", "sid": "pub-123", "hp": 1}, {"asi": "reseller.example", "sid": "acct-9", "hp": 1}]}
The records the DSP finds:
publisher.example/ads.txt: ssp.example, pub-123, DIRECT
publisher.example/ads.txt: reseller.example, acct-9, RESELLER
publisher.example/ads.txt: OWNERDOMAIN=publisher.example
ssp.example/sellers.json: {"seller_id": "pub-123", "name": "Example Publisher", "domain": "publisher.example", "seller_type": "PUBLISHER"}
reseller.example/sellers.json: {"seller_id": "acct-9", "name": "Example SSP Operator", "domain": "ssp.example", "seller_type": "INTERMEDIARY"}
Now walk the chain. The last node, reseller.example with acct-9, appears in ads.txt as a RESELLER. Its sellers.json entry is an INTERMEDIARY whose domain is ssp.example, which is the first node’s ad system. The first node, ssp.example with pub-123, is DIRECT in ads.txt, and its sellers.json entry is a PUBLISHER whose domain matches OWNERDOMAIN.
Chains can also be incomplete. If an upstream seller does not support the object, the next seller starts a chain with itself as the first node and sets complete to 0, per the SupplyChain spec. The DSP then knows where its evidence starts.
If acct-9 were missing from either file, the DSP could not confirm the second hop. The Tech Lab’s 2019 adoption post adds that a platform authorized only as a reseller is unlikely to pass as authorized if it claims to be direct.
What can the pair not do?
The same 2019 post lists three problems the pair cannot solve: removing fraud entirely, cryptographic verification of a declared path, and campaign discrepancies. A schain is therefore a claim by each seller, and the files are the evidence a buyer checks it against. This article describes version 1.0 of the object. A newer version is under proposal, and a separate Vectravia insight covers it.
How does Vectravia handle this?
Path Check runs this three-way comparison on each bid request, matching the SupplyChain object against ads.txt, app-ads.txt and sellers.json. Chains that are incomplete get flagged, along with sellers the files do not authorize. The checks read the public record before a bid is placed.