RTB Architecture
Demand path optimization for publishers: measure every path, then test the cut
Published · Last updated
Next scheduled review:
Demand path optimization is the publisher's answer to buyers' supply path optimization. You measure every route by which demand reaches your inventory. Then you remove or demote the routes that add fees and duplicate requests without adding unique bids. This guide covers why buyers trim paths, which metrics to track per path and how to test a cut safely.
Contents
Key facts
- ads.txt already labels your paths. In ads.txt 1.1, DIRECT means the publisher "directly controls the account", while RESELLER means it has "authorized another entity to control the account and resell" its ad space (IAB Tech Lab, ads.txt 1.1).
- Buyers see the same impression many times. The Trade Desk's Will Doherty said some supply-side platforms (SSPs) send 30% of a publisher's traffic "and they send it three times" (AdExchanger, 17 January 2024).
- Most chains fail a full check. A HUMAN Security diagnostic found 79% of bid requests carried a SupplyChain object, but only 42% of those objects passed full validation (PPC Land, 6 September 2026).
- Buyers cap what they listen to. Index Exchange estimates about 10 million queries per second (QPS) across the internet, with each demand-side platform (DSP) capping its intake at around 1 to 3 million (Index Exchange, accessed 9 November 2026).
- Direct buyer paths now have a price tag. The Trade Desk charges publishers a flat 4.5% fee for OpenPath, its direct publisher connection (PPC Land, 2 July 2026).
- Concentrated buyers do better. In the ANA's Q2 2026 benchmark, higher-performing advertisers bought across about 19,000 fewer domains and apps than lower performers (Fiducia on ANA, 6 August 2026).
Definition
Demand path optimization (DPO): the sell-side practice of listing every route from a publisher's inventory to buyers and measuring each route's unique bids, cost and data quality. The publisher then removes, merges or demotes the routes that duplicate others or erode trust.
It mirrors supply path optimization (SPO), which buyers run on their side. Both look at the same chain: publisher, SSP or exchange, any resellers, then the DSP. The difference is who holds the knife. If you do not prune your own paths, buyers will prune them for you, usually by dropping the paths they like least. This page sits in the publisher independence hub.
Why buyers run SPO, and what it does to your paths
Buyers trim paths for three reasons. Duplicate requests waste their QPS budget. Every extra hop takes a fee from the media dollar. And long, unverifiable chains look like fraud risk.
Duplication comes straight from header bidding. You ask every SSP to auction the same impression, and each one may send it to every DSP. AdExchanger described buyers sifting "dozens of duplicate bid requests" that look identical (AdExchanger, 17 January 2024). A DSP that caps intake at 1 to 3 million QPS cannot listen to all of them, so it keeps the paths it trusts (Index Exchange). The commercial side of those caps is covered in QPS, latency and bid performance.
Buyers also reward short paths with money. The ANA's Q2 2026 benchmark shows the best-performing advertisers buying on far fewer domains and apps (Fiducia on ANA, 6 August 2026). The Trade Desk built OpenPath to buy from publishers without an SSP in between. Its chief executive has cited Hearst Newspapers' fourfold fill-rate gain and 23% revenue increase, and a 97% rise in programmatic display revenue at the New York Post (company claims, PPC Land, 2 July 2026).
The lesson for a publisher is not "fewer partners is always better". It is that each path must earn its place with bids nobody else brings.
The demand paths a typical publisher runs
Start with an inventory. Most publishers have more paths than they think, because one SSP can appear several times: once as a direct seller, again behind a reseller and again inside a curated deal.
5 of 5 rows
SSP, direct account | ads.txt DIRECT; sellers.json | 0 | Low | Unique bids per auction |
SSP through a reseller | ads.txt RESELLER; sellers.json INTERMEDIARY; two or more nodes | 1 or more | Fee stacking, buyer blocklists | Whether the reseller adds buyers you lack |
Same SSP twice (client and server) | Two requests with the same | 0, but duplicated | Self-competition, wasted QPS | Deduplication and win overlap |
Curated or private marketplace deal | DIRECT or RESELLER, plus a deal ID | 0 to 1 | Curator fee on top of SSP fee | Net price after all fees |
Direct DSP connection | Publisher-declared path into one DSP | 0 | Dependence on one buyer | Fee versus the SSP path it replaces |
SSP, direct account
- How buyers see it
ads.txt DIRECT; sellers.json
seller_typePUBLISHER; one schain node- Extra hops
0
- Main risk
Low
- What to check
Unique bids per auction
SSP through a reseller
- How buyers see it
ads.txt RESELLER; sellers.json INTERMEDIARY; two or more nodes
- Extra hops
1 or more
- Main risk
Fee stacking, buyer blocklists
- What to check
Whether the reseller adds buyers you lack
Same SSP twice (client and server)
- How buyers see it
Two requests with the same
source.tidor none- Extra hops
0, but duplicated
- Main risk
Self-competition, wasted QPS
- What to check
Deduplication and win overlap
Curated or private marketplace deal
- How buyers see it
DIRECT or RESELLER, plus a deal ID
- Extra hops
0 to 1
- Main risk
Curator fee on top of SSP fee
- What to check
Net price after all fees
Direct DSP connection
- How buyers see it
Publisher-declared path into one DSP
- Extra hops
0
- Main risk
Dependence on one buyer
- What to check
Fee versus the SSP path it replaces
Table by AdSovereign, CC BY 4.0.
Definitions in the first two columns come from the ads.txt 1.1 and sellers.json specifications. The other columns are our design rules. The join keys between the three files are explained in SupplyChain object, ads.txt and sellers.json together.
Metrics per path: bid density, win rate and take rate
Measure paths, not partners. An SSP that is excellent as a direct path can be poor behind a reseller. Each metric below needs one row per path per day, built from your wrapper and ad server logs.
7 of 7 rows
Bid density | Bids received ÷ auctions the path joined | Wrapper bid events | How much demand the path brings |
Unique bid share | Auctions where only this path bid ÷ auctions it joined | Wrapper bid events, joined by auction | Demand you lose if you cut it |
Impressions won ÷ bids received | Ad server and wrapper win events | Whether its bids are competitive | |
Net eCPM | Publisher revenue ÷ impressions won × 1,000 | SSP payments, ad server | Price after the path's fees |
(Buyer spend − publisher revenue) ÷ buyer spend | Log-level data from the buyer, or SSP fee terms | Share of each dollar kept by the path | |
Duplicate rate | Requests sharing an auction ID with another path ÷ requests | Bid request logs | Self-competition and wasted QPS |
Timeout rate | Bids arriving after the wrapper timeout ÷ bids | Wrapper events | Latency cost of keeping the path |
Bid density
- Formula
Bids received ÷ auctions the path joined
- Data source
Wrapper bid events
- What it tells you
How much demand the path brings
Unique bid share
- Formula
Auctions where only this path bid ÷ auctions it joined
- Data source
Wrapper bid events, joined by auction
- What it tells you
Demand you lose if you cut it
- Formula
Impressions won ÷ bids received
- Data source
Ad server and wrapper win events
- What it tells you
Whether its bids are competitive
Net eCPM
- Formula
Publisher revenue ÷ impressions won × 1,000
- Data source
SSP payments, ad server
- What it tells you
Price after the path's fees
- Formula
(Buyer spend − publisher revenue) ÷ buyer spend
- Data source
Log-level data from the buyer, or SSP fee terms
- What it tells you
Share of each dollar kept by the path
Duplicate rate
- Formula
Requests sharing an auction ID with another path ÷ requests
- Data source
Bid request logs
- What it tells you
Self-competition and wasted QPS
Timeout rate
- Formula
Bids arriving after the wrapper timeout ÷ bids
- Data source
Wrapper events
- What it tells you
Latency cost of keeping the path
Table by AdSovereign, CC BY 4.0.
Unique bid share is the metric most publishers skip, and it decides most cuts. A path with low bid density but high unique share is worth keeping. A path with high density and near-zero unique share is a duplicate that buyers will eventually drop.
Take rate is the hardest number to get. You see your own revenue, not the buyer's spend. Buyers with log-level data can compute it, and some SSPs share it under contract. The ANA counts SSP and DSP fees together as transaction costs, which reached 27.2% of tracked spend in Q2 2026 (Fiducia on ANA, 6 August 2026).
A path record you can compute daily
The record below is our schema, not a standard. Field names are ours and the values are illustrative.
{
"date": "2026-11-08",
"path_id": "ssp-b.example/reseller-c.example",
"ads_txt_relationship": "RESELLER",
"sellers_json_seller_type": "INTERMEDIARY",
"schain_nodes": 2,
"schain_complete": true,
"auctions_joined": 4200000,
"bids_received": 630000,
"auctions_only_this_path_bid": 21000,
"impressions_won": 52000,
"publisher_revenue_usd": 78.0,
"buyer_spend_usd": 104.0,
"duplicate_requests": 1900000,
"late_bids": 41000,
"metrics": {
"bid_density": 0.15,
"unique_bid_share": 0.005,
"win_rate": 0.0825,
"net_ecpm_usd": 1.5,
"take_rate": 0.25,
"duplicate_rate": 0.4524,
"timeout_rate": 0.0651
}
}5 of 5 rows
| Copied from your ads.txt line and the SSP's sellers.json entry for this seller ID |
| Read from |
| The numerator of unique bid share; needs an auction-level join across paths |
| Often unknown; leave it null rather than guess, and take rate becomes null too |
| 21,000 ÷ 4,200,000 = 0.5% in this example: a strong cut candidate |
ads_txt_relationship, sellers_json_seller_type
- Meaning
Copied from your ads.txt line and the SSP's sellers.json entry for this seller ID
schain_nodes, schain_complete
- Meaning
Read from
source.schainin the bid request, as defined in OpenRTB 2.6
auctions_only_this_path_bid
- Meaning
The numerator of unique bid share; needs an auction-level join across paths
buyer_spend_usd
- Meaning
Often unknown; leave it null rather than guess, and take rate becomes null too
metrics.unique_bid_share
- Meaning
21,000 ÷ 4,200,000 = 0.5% in this example: a strong cut candidate
Table by AdSovereign, CC BY 4.0.
ads.txt, sellers.json and schain hygiene
Buyers read your files before they read your bids. A path with a broken or missing declaration may be filtered out before any DSP prices it. Clean files are the cheapest DPO work you can do.
- Remove lines for partners you no longer use. Every stale RESELLER line is an authorised path someone can still sell through.
- Mark relationships honestly. Label a line DIRECT only when you hold the account and the contract, per the ads.txt 1.1 definition (IAB Tech Lab).
- Match sellers.json. Your seller ID should appear in each SSP's sellers.json with the right
seller_type. A PUBLISHER entry on a path you call RESELLER is a mismatch buyers notice (IAB Tech Lab, sellers.json). - Check that chains are complete. Ask each SSP for sample bid requests and confirm
schain.completeis 1 and every node resolves. HUMAN's diagnostic found 98% of objects declared themselves complete, yet only 42% passed full validation (PPC Land, 6 September 2026). - Review the file every month. Use the ads.txt generator to rebuild the file from a clean partner list instead of editing by hand.
Removing a RESELLER line is itself a path cut. Treat it like one and test it, as described below.
How to test a path cut without losing revenue
Never cut a path everywhere at once. Revenue moves for many reasons, and a one-week drop after a cut proves nothing. Run a controlled test instead: keep the path for a control group of traffic and remove it for a test group.
- Pick the unit of randomisation. Page views are easiest. Use pages or geographic regions if buyers might shift spend between groups during the test.
- Split traffic with your wrapper. Prebid.js has a server-to-server testing module whose
bidSourcesetting sends a bidder through the client or server path for a set share of requests. It adds anhb_sourcekey-value so your ad server can report each group (Prebid.org, s2sTesting module). - Fix the primary metric before you start. Use revenue per thousand page views (RPM) for the whole page, not the eCPM of one partner. A cut can lower one partner's eCPM while raising page revenue.
- Set guardrails. Stop the test if test-group RPM falls more than an agreed share for two days running, or if fill drops on a key placement.
- Run long enough to cover a buying cycle. Two full weeks covers weekday and weekend patterns; budget flight changes at month end need longer.
- Read the result per segment. Check desktop, mobile web, app and CTV separately, and top buyers separately. A cut can be neutral overall and harmful for one buyer.
Prebid's own documentation warns that its testServerOnly flag turns off client bids for part of the traffic "and should be used with caution" (Prebid.org). The same caution applies to any cut: test on a small share first. Wrapper analytics for these tests are covered in Prebid Server analytics and debugging.
A test plan in JSON
This plan is our format, not a Prebid configuration. It records what you will cut, how traffic splits and when you stop. Values are illustrative.
{
"test_id": "dpo-2026-11-reseller-c",
"hypothesis": "Removing reseller C does not lower page RPM because its bids are 99.5% duplicated by direct paths",
"paths_removed_in_test_group": ["ssp-b.example/reseller-c.example"],
"randomisation_unit": "page_view",
"traffic_split": { "control": 0.8, "test": 0.2 },
"primary_metric": "page_rpm_usd",
"secondary_metrics": ["fill_rate", "bid_density_all_paths", "timeout_rate", "top_10_buyer_spend"],
"guardrails": { "max_rpm_drop_pct": 3.0, "consecutive_days": 2, "action": "end_test_restore_path" },
"duration_days": { "minimum": 14, "maximum": 28 },
"segments": ["desktop_web", "mobile_web", "app", "ctv"],
"decision_rule": "Cut if RPM change is within -1% and the 95% interval excludes -3%"
}Worked example: two resold paths, one decision
The numbers in this example are illustrative, not benchmarks. Suppose a news site runs SSP B directly and also through reseller C. Over 14 days the test group, without reseller C, earns $11.92 RPM and the control earns $11.95 RPM. That is a 0.25% drop, inside the 1% band in the plan. The split itself can run on Prebid's bidSource setting.
The site also looks at what reseller C cost. If buyers paid $104 for impressions on which the site received $78, the path's take rate was 25%. If the same bids reach the same buyers through SSP B directly at a lower take rate, every dollar that moves to the direct path pays the publisher more. Buyers win too: they stop seeing a duplicate of the same impression.
The decision is to remove the RESELLER line and the reseller's adapter. Run the same comparison for every path in the inventory, and model the fee side with the ad tech fee calculator.
Where floors fit
Path cuts and price floors interact. Removing a duplicate path can lower bid density, which changes how much a floor costs you in lost fill. Set floors per path after the cuts, not before. The method for first-price auctions is in floor price strategy, and the auction mechanics behind wrappers are in header bidding explained.
Common mistakes
- Judging partners instead of paths. One SSP can be your best direct path and your worst resold one.
- Cutting on eCPM alone. A path with a high eCPM and no unique bids adds nothing; a path with a low eCPM and unique buyers may carry a key advertiser.
- Ignoring auction duplication. Two routes to the same SSP compete with each other and burn buyer QPS. Pick one route per SSP unless a test proves both pay.
- Leaving stale ads.txt lines. An unused RESELLER line is still an authorised path.
- Testing without a control group. Before-and-after comparisons confuse a cut with seasonality, news cycles and budget flights.
- Forgetting the direct DSP fee. A direct connection still has a price; compare it with the SSP path it replaces, not with zero.
- Cutting everything at once. Change one path per test so you know which cut moved revenue.
FAQ
What is demand path optimization?
What is the difference between DPO and SPO?
How many SSPs should a publisher use?
Should I remove resellers from my ads.txt file?
How long should a demand path test run?
How this works on owned infrastructure
Demand path optimization depends on one join: which path carried each bid, at what price, and what the publisher was paid. When the wrapper, SSP and ad server belong to different vendors, that join is assembled from exports days later, and unique bid share is often impossible to compute. AdSovereign provides SSP and exchange components designed to run in the publisher's own cloud account or data centre. Every path then writes its bid, win and fee events into one log the publisher controls, so path tests can be read the next morning. The architecture page shows where the event log sits, and the integrations page lists the supported connections.
Sources
- IAB Tech Lab, "ads.txt Specification Version 1.1" (Supply-Chain-Validation repository, accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/Supply-Chain-Validation/blob/main/ads.txt%20v1.1.md
- IAB Tech Lab, "sellers.json" specification, version 1.0 (Supply-Chain-Validation repository, accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/Supply-Chain-Validation/blob/main/sellers-json.md
- IAB Tech Lab, "OpenRTB API Specification Version 2.6", Source and SupplyChain objects (accessed 9 November 2026). https://github.com/InteractiveAdvertisingBureau/openrtb2.x/blob/main/2.6.md
- AdExchanger, "Attack Of The Clones: Programmatic's Hidden Scourge Of Bid Duplication" (17 January 2024). https://www.adexchanger.com/platforms/attack-of-the-clones-programmatics-hidden-scourge-of-bid-duplication/
- PPC Land, "SupplyChain object" (6 September 2026; reports HUMAN Security's diagnostic of 1 November 2023). https://ppc.land/supplychain-object/
- Index Exchange, "The Importance of QPS Optimization in Programmatic" (accessed 9 November 2026). https://www.indexexchange.com/index-explains/qps-optimization-programmatic/
- PPC Land, "The Trade Desk gains first Dutch publisher for OpenPath at 4.5% fee" (2 July 2026). https://ppc.land/the-trade-desk-gains-first-dutch-publisher-for-openpath-at-4-5-fee/
- Fiducia, "ANA Programmatic Transparency Benchmark: Q2 2026 Working-Media Efficiency Reaches a Record 45%" (6 August 2026). https://www.fiducia.eco/post/ana-programmatic-transparency-benchmark-q2-2026-working-media-efficiency-reaches-a-record-45
- Prebid.org, "Module: Server-to-Server Testing for Header Bidding" (s2sTesting, accessed 9 November 2026). https://docs.prebid.org/dev-docs/modules/s2sTesting.html