Stack Teardowns · Issue 02 · Web track · Desktop
CNN.com
Fifteen wrappers fire in the page lifecycle on a US desktop capture. Across 2,721 captured bid requests and 3,063 bidder attempts, 98% timed out before they could compete. The premium ATF banner saw 5 responses across 1,112 attempts and produced zero Prebid wins. Captured via the Beamflow Chrome extension and cross-checked against CNN's public ads.txt and each declared SSP's sellers.json.
The numbers at a glance
Bid requests captured
2,721
US desktop session
Wrappers detected
15
13 SSP + 1 DSP + 2 server-side managed
Bid timeout rate
98%
3,002 of 3,063 bid attempts
Bidders with 0 responses
6 of 12
never returned in tmax
Schain coverage
16%
369 of 2,355 wire-level bids
Authorized via ads.txt
100%
2,342 of 2,342 programmatic
›Methodology
- Capture method:
- Live wire-level capture of every bid request fired in the browser
- Tool:
- Beamflow Chrome extension v0.3.0 (install)
- Geo:
- US residential network (matters for the wrapper stack — a US capture and an international capture run materially different wrapper sets on CNN; see Finding 6)
- Device:
- Desktop Chrome
- Session:
- 2,721 bid requests captured across the homepage, multiple category sections, and multiple article pages of www.cnn.com
- Schain detection:
- Direct read of the schain parameter on each OpenRTB bid request
- Timing instrumentation:
- tmax per wrapper, latency p50/p95 per bidder, bidTimeout events captured per placement
- Bid attempt counting:
- A bid attempt is a per-bidder request that either returned a measurable response within tmax (counted in latencyByBidder samples, 61 in this capture) or fired a bidTimeout event (counted in timeoutsByBidder, 3,002 in this capture). Total bidder-level attempts: 3,063. The 2,721 figure for total bid requests captured on the wire includes both bidder-level attempts and wrapper-level requests routed server-side (notably Amazon TAM and Magnite Prebid Server, which do not surface as Prebid bidder events).
- Wrapper attribution:
- Endpoint host pattern matching against a known-wrapper database
- Supply chain audit:
- ads.txt + sellers.json crawl via Beamflow.co (view the live scan)
1. The site at a glance
www.cnn.com is the flagship CNN news property, owned by Warner Bros. Discovery. The runtime capture covered the homepage, multiple category sections, and multiple article pages and recorded 2,721 bid requests across the session. The site monetizes through display advertising on a prebid.js stack with fifteen detected wrappers (twelve SSP-side wire-level, one DSP-direct integration, two server-side managed). No paywall or subscription gate was encountered during the captured session.
No video ads were observed in the captured surfaces. Video formats are likely served on dedicated video pages not covered in this session. A follow-up capture on a CNN Video URL would show whether video runs on a separate stack or shares the same wrappers seen here.
Where this stack sits in CNN's revenue
WBD's January 2026 spinoff proxy revealed CNN at roughly $1.8B in 2026 total revenue, down from $2.2B in 2021. CNN Digital ad revenue is not disclosed; estimates place it in the $150-250M range inside that total.
The cnn.com open-web display stack analyzed here is a small slice of CNN's overall revenue picture, and an even smaller slice once you factor in the rest of the demand stack outside the Prebid layer covered by this capture. Per-impression efficiency on whatever does flow through this layer matters disproportionately at smaller scale.
Sources: Hollywood Reporter on the WBD proxy filing, Variety on CNN profitability. The CNN Digital ad revenue figure is an estimate, not a disclosed number.
2. Wrappers and adapters detected
Eleven wrappers detected at the page lifecycle level. Each wrapper is a gateway into a wider demand pool, not a single bidder. A single Prebid adapter call to Criteo can route to dozens of advertisers via Criteo's own auction. A single Amazon TAM call routes to the full TAM bidder list. The 15 here counts integration surfaces fired in the browser, not buyers competing in the auction. Rows are ordered by bid volume.
How to read the "Type" column
- Prebid adapter
- The vendor ships an official Prebid.js adapter (e.g.
criteoBidAdapter,rubiconBidAdapter). Bids are requested inside the standard Prebid auction (pbjs.requestBids()) and Prebid handles bid timeouts, schain injection, and timing centrally. This is the most common integration path for SSPs in a header bidding stack. - Managed wrapper
- The vendor ships its own orchestration library that participates in the page auction (e.g. Amazon TAM's
apstag, PubMatic OpenWrap's managed Prebid build). It runs alongside or wraps Prebid; the publisher gets the vendor's curated demand pool and the vendor handles orchestration on its own infrastructure. Some signal handling (notably schain in Amazon TAM's case) happens server-side and is not visible in the browser-side OpenRTB payload. - Direct integration
- An endpoint called directly from the page that is not routed through Prebid's standard auction flow. Can be a non-Prebid header bidding wrapper, a publisher-side custom script, or in The Trade Desk's case a DSP-side direct call. These integrations still fire OpenRTB bid requests from the browser, so wire-level signals (schain, timing) are still measurable, but they are not governed by Prebid's tmax or schain config; each vendor handles its own.
All three categories can coexist in the same page and most often do. Not every wrapper connected to the prebid layer is technically a Prebid adapter, which is the source of most of the noise in supply-chain audits.
| Wrapper | Type | Routes to | Bids | Schain |
|---|---|---|---|---|
| The Trade Desk (direct.adsrvr.org) | Direct integration | The Trade Desk DSP (buyer-side direct integration) | 378 | 96/378 (25%) |
| Amazon TAM / UAM | Managed wrapper | Amazon Publisher Services full TAM bidder list (handled server-side) | 358 | 0/358 (0%) |
| Magnite Fastlane (Rubicon) | Prebid adapter | Magnite's exchange + Marketplace + Streaming demand pool | 312 | 0/312 (0%) |
| Index Exchange (Casale direct integration) | Direct integration | Index Exchange marketplace demand | 287 | 4/287 (1%) |
| Nativo | Direct integration | Nativo's native + display demand | 282 | 0/282 (0%) |
| TripleLift | Prebid adapter | TripleLift's native + display + video demand | 266 | 0/266 (0%) |
| Media.net | Direct integration | Media.net demand (Yahoo-aligned partnership) | 248 | 0/248 (0%) |
| Wunderkind | Direct integration | Wunderkind's demand pool | 215 | 215/215 (100%) |
| Kargo | Direct integration | Kargo's contextual + mobile-first demand | 167 | 0/167 (0%) |
| Criteo Commerce Grid | Prebid adapter | Criteo Commerce Grid demand (browser-side bid endpoint at grid-bidder.criteo.com). | 139 | 2/139 (1%) |
| PubMatic OpenWrap | Managed wrapper | PubMatic exchange + OpenBidding partners | 50 | 42/50 (84%) |
| Magnite Prebid Server | Managed wrapper | Magnite Demand Manager S2S endpoint at prebid-server.rubiconproject.com | 8 | 0/8 (0%) |
| OpenX | Prebid adapter | OpenX exchange demand | 4 | 4/4 (100%) |
| Sovrn (ap.lijit.com) | Direct integration | Sovrn marketplace demand (lijit.com is Sovrn's bidding domain) | 4 | 4/4 (100%) |
| Sharethrough | Prebid adapter | Sharethrough native + display demand | 2 | 2/2 (100%) |
3. Supply path coverage
The IAB SupplyChain object (schain) declares who sits between the publisher and the auction on every OpenRTB bid request. Buyers use it to verify the path back to an authorized seller; missing or unverifiable chains mean buyers discount the bid, skip it, or apply a lower cap. This section reads schain coverage per wrapper from the wire-level capture, with server-side wrappers broken out separately because their browser payload does not carry schain (the chain is added on their backend).
Wire-level schain coverage
369 / 2354
16% of bid requests from the 13 wire-level-evaluable wrappers carried the schain object on the browser-side OpenRTB payload. Every chain present resolved at depth 1 (one declared seller between publisher and auction).
Denominator excludes Amazon TAM's 366 bids because TAM passes schain server-side and the browser capture cannot evaluate it. Including TAM in the denominator would push the headline down to 14% but that number conflates two different signal paths. See the server-side group below for the TAM read.
Wire-level schain by wrapper
13 of 15 wrappers. Per-wrapper share of bids that included schain in the browser-side OpenRTB request. Green: 100% coverage. Amber: partial. Red: 0%.
Server-side schain (not browser-observable)
Two wrappers in this stack run upstream server-side auctions. Their browser-side traffic is a passthrough to their own backend, where the actual OpenRTB bid request to demand is fired (with schain added there). Wire-level 0% is expected for both, not a coverage gap. Amazon Publisher Services' documentation explicitly covers TAM's server-side schain handling; Magnite Demand Manager (Prebid Server) follows the same pattern as a hosted S2S product.
Confirm end-to-end schain status with each server-side wrapper's account team. Amazon Publisher Services documents TAM's server-side schain handling explicitly. Magnite Demand Manager (Prebid Server) follows the same hosted-S2S pattern; the schain config lives in the Magnite Publisher Console under Wrapper Config -> SupplyChain.
›How each wrapper was classified (wire-level vs server-side)
Criterion. A wrapper is classified server-side when its browser-side traffic is a passthrough/slot-info request to the wrapper's own backend, with the actual OpenRTB bid request to demand running on that backend. In that case, schain (if any) is added server-side and is not present in the browser-side capture, so wire-level inspection cannot meaningfully measure it. A wrapper is classified wire-level when the browser fires the OpenRTB bid request directly to the wrapper's bid endpoint; in that case, schain (or its absence) on that request is the real, downstream-buyer-facing signal.
Result for this capture. Two wrappers are classified server-side: Amazon TAM (documented apstag model — browser sends slot data to aax.amazon-adsystem.com, server runs the auction) and Magnite Demand Manager / Prebid Server (browser sends to prebid-server.rubiconproject.com, hosted S2S backend runs the auction). The remaining thirteen wrappers fire OpenRTB bid requests directly from the browser. Four of them — Wunderkind, OpenX, Sovrn, and Sharethrough — pass schain on 100% of those wire-level bids, corroborating the classification: server-side passthrough wrappers cannot show schain on the wire.
Per-wrapper basis.
- The Trade Desk (direct) — DSP-direct integration to
direct.adsrvr.org. Browser-side. Wire-level. - Amazon TAM / UAM — apstag library sends slot data to
aax.amazon-adsystem.com; Amazon's backend runs the auction and adds schain server-side. Server-side. - Magnite Fastlane (Rubicon) — Prebid adapter (
rubiconBidAdapter). Fires from browser tofastlane.rubiconproject.com. Wire-level. - Index Exchange — Direct integration; bid requests fire from the browser to
htlb.casalemedia.com. Wire-level. - Nativo — Browser-fired bid request via the Nativo Prebid adapter at
exchange.postrelease.com. Wire-level. - TripleLift — Prebid adapter firing to
tlx.3lift.comfrom the browser. Wire-level. - Media.net — Browser-fired bid request to
prebid.media.net. Wire-level. - Wunderkind — Direct integration firing OpenRTB requests from the browser to
ssp.wknd.ai. Wire-level, confirmed by 100% schain coverage on 215 of 215 bids. - Kargo — Browser-fired bid request to
krk2.kargo.com. Wire-level. - Criteo / Grid — Endpoint
grid-bidder.criteo.comis the Grid SSP, now a Criteo product post-2022. Browser-side Prebid adapter. Wire-level. The 1% schain reading (2 of 139 bids) is from the Spotim chain (see Finding 5). - PubMatic OpenWrap — Hybrid wrapper. The browser fires OpenRTB bid requests to PubMatic's bid endpoint (
hbopenbid.pubmatic.com) carrying schain on 84% of bids in this capture (42 of 50). OpenWrap may also do downstream OpenBidding server-side orchestration that we cannot see, but the publisher-to-PubMatic hop — which is the relevant scope for schain integrity — is wire-level evaluable. - Magnite Demand Manager / Prebid Server — The browser fires to
prebid-server.rubiconproject.com, which is Magnite's hosted Prebid Server S2S endpoint. The actual OpenRTB bid request to demand happens on Magnite's backend; schain is added there. Server-side. Separate path from Magnite Fastlane (which is the browser-side Prebid adapter for the same SSP). - OpenX — Prebid adapter firing to
rtb.openx.netfrom the browser. Wire-level. 100% schain on 4 of 4 (small sample). - Sovrn (lijit.com) — Direct integration to
ap.lijit.com. Browser-side. Wire-level. 100% schain on 4 of 4 (small sample). - Sharethrough — Prebid adapter firing to
btlr.sharethrough.comfrom the browser. Wire-level. 100% schain on 2 of 2 (small sample).
If a future capture shows a wrapper firing only a passthrough call without an OpenRTB bid payload, that wrapper should be reclassified server-side. The PubMatic OpenWrap line in particular is sensitive to the wrapper config in use; an S2S-only OpenWrap deployment would behave like Magnite Prebid Server here.
Four wrappers pass schain on 100% of wire-level bids (Wunderkind, OpenX, Sovrn, Sharethrough); PubMatic OpenWrap is at 84%; TTD direct at 25%. Five wrappers show 0% wire-level (Magnite Fastlane, Nativo, TripleLift, Media.net, Kargo) — could still be adding schain server-side; the capture only sees the browser-side request. The fix where the gap is real lives in per-wrapper config: pbjs.setConfig({schain}) for adapters, each managed wrapper's own admin UI for the rest.
All 369 schain-carrying bids split into just two chain shapes: wunderkind.co (sid 340) on 351 bids (Wunderkind, PubMatic, TTD), and spotim.market on 18 bids (OpenX, IX, Sovrn, Criteo, Sharethrough, PubMatic). Spotim is OpenWeb's parent — OpenWeb appears to be wrapping the auction and stamping its own seller identity. See Finding 5.
4. Auction timing analysis
Three configuration patterns show up clearly across the 3,063 captured bidder attempts. First, a wrapper-level tmax misconfiguration on PubMatic OpenWrap (300ms shelf against an 888ms p50). Second, a 5,000ms tmax shelf on Criteo — 4x the typical Prebid budget, which keeps the auction open longer than any reasonable page-load window. Third, a stack-wide pattern of bidder responses arriving after the auction has already closed. Combined, the result is a bid timeout rate of 98%. Effectively all Prebid-layer bidders miss the window almost all of the time.
Session-level timeout rate
98%
3,002 of 3,063 bidder attempts timed out before a response could land. Six bidders (TripleLift, Criteo, OpenWeb, Nativo, Teads, AppNexus) returned zero measurable responses across the entire capture. An attempt is counted as one (bidder, ad unit) pairing in the Prebid auction, summed across the session. Sources: latencyByBidder samples (61) + timeoutsByBidder count (3,002).
Wrappers (Section 3) and bidders (below) are both 11, but the membership is not identical. The bidders below are Prebid-side participants pulled from pbjs.bidTimeout and bidResponse events. OpenWeb and Teads appear as Prebid bidder names without a separately-detected wrapper endpoint; Amazon TAM and Wunderkind run outside Prebid's auction so they appear as wrappers above but not as Prebid bidders here.
Responses vs timeouts per bidder
Green = response landed inside tmax. Red = timed out. Sorted by timeout rate descending. tmax varies by wrapper from 300ms to 5,000ms; see the configured tmax shelves table below.
For the five bidders with p95 over 3,000ms, even the bids that responded fall outside the 1,250ms tmax on their slow tail. With p95 above tmax, roughly half of the bids you see logged arrive after the auction has been decided.
Two tmax outliers pulling in opposite directions
PubMatic OpenWrap sits on a 300ms shelf against its own 888ms p50 (96% timeout); Criteo sits on a 5,000ms shelf against the Prebid default of 1,000ms (still 100% timeout). One is biding into a closed door, the other is holding the auction open four seconds longer than it needs to. Both are correctable in wrapper config: move pubmatic.com up to 1,250ms, audit whether Criteo's 5s shelf is intentional before adjusting. See the Prebid bidder-timeout doc.
Configured tmax shelves
| Wrapper | tmax | Samples | Note |
|---|---|---|---|
| adsrvr.org (TTD) | 1250ms | 370 | |
| nativo.com | 1250ms | 282 | |
| wunderkind.co | 300ms | 215 | Wunderkind uses a non-Prebid integration path; the 300ms shelf does not cause its bids to time out. |
| criteo.com | 5000ms | 139 | Misconfig. 5,000ms is 4x the typical Prebid wrapper budget. Either Criteo is treated as a priority demand source the page is willing to wait on, or it's a left-over override that holds up the auction render when Criteo runs slow. |
| pubmatic.com | 300ms | 50 | Misconfig. PubMatic OpenWrap p50 is 888ms; the 300ms shelf produces a 96% timeout rate on this wrapper. |
| rubiconproject.com | 2000ms | 8 | |
| media.net | 2000ms | 8 | |
| openx.com | 2500ms | 4 | |
| lijit.com (Sovrn) | 2500ms | 4 | |
| sharethrough.com | 2500ms | 2 |
The premium ATF banner produced zero Prebid wins
The headline above-the-fold banner (ad_bnr_atf_01) was attempted by 12 bidders across 1,112 attempts. Five responses landed inside tmax (from Rubicon 3, TTD 1, PubMatic 1). Zero of those responses won. The breakdown of responses vs timeouts on this single slot is the cleanest illustration of the structural problem.
1112
Total attempts
5
Responses (all TTD)
100%
Timeout rate
With 5 responses across 1,112 attempts and zero Prebid wins, the ATF slot is effectively decided outside the Prebid layer. The wins on this slot during the captured session almost certainly came from GAM line items, direct deals, or other demand paths the browser-side capture does not see. The Prebid layer is participating in an auction it rarely lands in time for, and never wins when it does.
Why this happens
Two non-mutually-exclusive root causes match the data:
- 1.
Auction start timing.
Prebid's
requestBids()fires before the ad slots are fully defined in the DOM. Every bidder is racing a clock that started early. The documented Prebid pattern (see the basic example) is to call requestBids inside a googletag.cmd.push callback after slot definition, then call setTargetingForGPTAsync in the bidsBackHandler before googletag.pubads().refresh(). If the wrapper does this in a different order, every bidder sees a tmax that has been ticking since before they were given anything to bid on. This is the most likely cause of the six bidders at 100% timeout rate. - 2.
Per-bidder tmax misconfig.
The PubMatic case above is the clearest example: a bidder whose p50 latency is 888ms placed on a 300ms shelf. Per the Prebid timeout-defaults docs, the default bidder timeout is 1,000ms with failsafeTimeout at 1,100ms; managed wrappers and direct integrations often need 1,250-1,500ms. Per-bidder overrides are explicitly supported via
pbjs.bidderSettings.<bidder>.bidderTimeout = N.
Even the bidders that do respond run close to or above the operative tmax on their slow tail: Medianet p95 1,663ms, PubMatic p95 1,535ms, TTD p95 1,270ms, Rubicon p95 1,237ms. With wrapper tmax shelves ranging from 300ms (PubMatic, Wunderkind) to 5,000ms (Criteo) and an apparent stack-wide failsafeTimeout near 1,000ms (see the DevTools subsection below), most bidders are racing a clock that closes well before their slow tail can land. Setting failsafeTimeout above the bidder timeout, as Prebid recommends, would let in-flight bids land after tmax expires without blocking the auction render. That is a wrapper-level config the publisher controls directly.
Aggregate yield signal
The Prebid layer alone is a thin slice of CNN's overall monetization. The bulk runs through Google Ad Manager line items, direct-sold deals, and server-side paths the browser capture cannot see. The aggregate numbers below characterize what the Prebid layer contributed during the captured session — not CNN's overall ad yield.
Prebid winning bids
4
across the captured session
Avg winning CPM
$3.08
Prebid wins only (n=4)
Avg bid CPM (schain vs no-schain)
$1.63 with / $1.03 without
52 bids with CPM attached
Four Prebid wins across 2,721 captured bid requests is the structural read: at premium-publisher scale, the Prebid layer is either winning a thin slice or losing repeatedly to demand the capture doesn't see. The schain vs no-schain bid CPM gap ($1.63 vs $1.03) is descriptive of this sample only and not inferential; n=52 across one session is far too small to claim schain causes higher prices. Per-placement breakouts are out of scope for this issue.
Verify in your own Chrome DevTools
Everything counted above is observable in plain Chrome DevTools with no extension at all. Open DevTools, switch to the Network panel, filter by Fetch/XHR, and reload www.cnn.com. You will see the same ten bidder requests get aborted as the tmax timer expires.

canceled, 0 bytes returned). Kargo's own client-side telemetry endpoint logs the timeout back to its servers (the URL parameter is literally named timeout). GAM's ad request fires ~860ms after the canceled bidders, well past their kill point.Three observations from the network layer that the bidder-timing capture above does not surface directly:
- 1.
Ten bidders aborted in a 40ms window around 1,000ms.
TTD, Index Exchange, Media.net, Criteo, Magnite Fastlane, Magnite Prebid Server, TripleLift, PubMatic OpenWrap, Teads, and PubMatic all show status
canceledat 1.00-1.04s with 0kB returned. That cluster is the network-layer signature of Prebid'sbidTimeoutevent firing. It is also tighter than the 1,250ms tmax shown in tmaxByWrapper, which suggests a separatefailsafeTimeoutat ~1,000ms is overriding per-wrapper tmax stack-wide. Both ride in the same Prebid timeouts config (see the Prebid timeout-defaults doc). - 2.
Kargo's own telemetry confirms the timeout from the SSP side.
The 200 OK request to
krk2.kargo.com/api/v1/eventis Kargo's client-side ping back to its own servers, and the URL parameter is literally namedtimeout. Kargo is logging on its own side that this page killed its bid before it could respond. SSP account teams can pull these telemetry reports for any given publisher; the evidence the timeout is happening exists on both sides of the wire. - 3.
Prebid runs inside an anti-tracking iframe.
Every bidder request in the panel above shows
frame_ant.js:2as its initiator. Theantprefix is CNN's anti-tracking iframe wrapper, which means every bid request crosses an iframe boundary on its way out. This is a defensible privacy architecture but adds latency overhead to every bidder request, compounding the tmax pressure documented above.
The takeaway: the findings in this section do not rely on a proprietary capture tool. Anyone at CNN's ad ops team (or anyone evaluating this teardown) can reproduce the timeout pattern by opening Chrome DevTools on www.cnn.com. The Beamflow capture adds bidder-level attribution and the per-bidder response/timeout breakdown; the network-layer evidence stands on its own.
5. Supply chain audit
View the live scan →Two views. First, the per-wrapper authorization status as observed in the runtime session above. Second, the full ads.txt and sellers.json audit across every declared seller on the file (not just what fired in this session), run through Beamflow.co.
5a. Per-wrapper authorization (this session)
Authorization is the second half of the supply chain story. Even if a bid carries a chain, downstream buyers verify the path against the publisher's ads.txt and each declared SSP's sellers.json. A break anywhere in that path means the buyer either skips the bid or prices it lower.
2342
Verified (100% of programmatic)
0
Not authorized in publisher ads.txt
0
DIRECT/RESELLER mismatches
Per-wrapper status
| Wrapper | Status | Detail |
|---|---|---|
| The Trade Desk (direct.adsrvr.org) | N/A (DSP-direct) | DSP-direct integration. Endpoint owner is The Trade Desk. Verification scope is different from an SSP path; 25% of bids carry schain on the wire. |
| Amazon TAM / UAM | Verified | 16 ads.txt entries verified against aps.amazon.com sellers.json. TAM handles schain server-side so wire-level coverage is expected to read zero. |
| Magnite Fastlane (Rubicon) | Verified | 20 ads.txt entries verified against rubiconproject.com sellers.json. |
| Index Exchange (Casale direct integration) | Verified | 20 ads.txt entries verified against indexexchange.com sellers.json. 4 of 287 wire-level bids carry schain (the Spotim chain — see Finding 5). |
| Nativo | Verified | 4 ads.txt entries verified against nativo.com sellers.json. |
| TripleLift | Verified | 20 ads.txt entries verified against triplelift.com sellers.json. |
| Media.net | Verified | 20 ads.txt entries verified against media.net sellers.json. |
| Wunderkind | Verified | 2 ads.txt entries verified against wunderkind.co sellers.json. 100% schain coverage on every captured bid. |
| Kargo | Verified | 6 ads.txt entries verified against kargo.com sellers.json. |
| Criteo Commerce Grid | Verified | 6 ads.txt entries verified. 2 of 139 wire-level bids carry schain (the Spotim chain — see Finding 5). |
| PubMatic OpenWrap | Verified | 20 ads.txt entries verified against pubmatic.com sellers.json. 84% schain coverage (42 of 50 bids). See timing section for why this wrapper produces so few bids relative to its potential. |
| Magnite Prebid Server | Verified | 20 ads.txt entries verified against rubiconproject.com sellers.json. Separate path from Magnite Fastlane — this is Magnite's hosted Prebid Server S2S. The browser-side request is a passthrough to Magnite's backend; the actual auction and schain handling happen server-side, so wire-level coverage reads zero by design. |
| OpenX | Verified | 20 ads.txt entries verified against openx.com sellers.json. 100% schain coverage (4 of 4 bids; small sample). |
| Sovrn (ap.lijit.com) | Verified | 20 ads.txt entries verified against lijit.com sellers.json. 100% schain coverage (4 of 4 bids; small sample). |
| Sharethrough | Verified | 20 ads.txt entries verified against sharethrough.com sellers.json. 100% schain coverage (2 of 2 bids; small sample). |
5b. Full ads.txt audit via Beamflow.co
The runtime view above only covers what fired during the captured session. The full picture lives in the publisher's ads.txt file itself, which declares every seller authorized to monetize cnn.com inventory. Beamflow.co crawls that file and cross-references every entry against the corresponding SSP's sellers.json. Server response: HTTPS, 30ms response, 2 redirects, text/plain.
1,011 clean · 723 issues
1,734 total entries
sellers.json Verification50% weight
D 65%
Supply Chain Completeness5% weight
F 15%
Syntax Health10% weight
A 100%
Duplicate Detection10% weight
C 84%
File Health15% weight
A 100%
File-level warnings
- ·Missing recommended "contact" variable
- ·High duplicate rate: 278 duplicate records found
SSP verification · 1,734 ads.txt entries checked
1,138
Verified by SSP sellers.json (66%)
506
Unverified (350 not found, 156 DIRECT/RESELLER mismatches)
Buyers cannot verify 506 of 1,734 entries, so some of that supply is likely being bid lower or skipped entirely.
Operator read
The number to focus on is the 506 entries unverified by SSP sellers.json (29% of the file). Those are entries declared in the publisher's ads.txt that downstream buyers cannot cryptographically verify back to the listed SSP. The 661 duplicate records and 7 defunct-SSP entries are cosmetic by comparison, but worth deduping on the next ads.txt release. The Supply Chain Completeness and sellers.json Verification grades are the same gap viewed from two sides: each unverified entry is one path where buyers cannot confirm the seller exists.
Machine-fixable categories
Of the 723 issues, the majority are machine-fixable without judgment calls: duplicate records flagged for removal, DIRECT/RESELLER mismatches identified, unverified publisher IDs flagged for review, and defunct SSPs cleared. Categories overlap at the per-entry level so component counts do not sum to a single clean total. Run the live scan for the per-entry breakdown.
6. What this site gets right
Architectural and configuration choices in the CNN.com stack worth copying or benchmarking against.
- 1.
Four wrappers pass schain on 100% of wire-level bids
Wunderkind (215 of 215 bids), OpenX (4 of 4), Sovrn (4 of 4), and Sharethrough (2 of 2) all carry the SupplyChain object on every captured browser-side bid. PubMatic OpenWrap is close behind at 84% (42 of 50). That five-of-thirteen-wrappers result demonstrates the per-wrapper schain config can be set correctly when the publisher and the SSP both wire it through. The other wrappers may also be adding schain server-side (which we cannot see from a browser-side capture), but where the wire reads zero, the fix lives in per-wrapper config and is straightforward.
- 2.
ads.txt authorization is clean at the publisher level
All 2,342 programmatic bids in the captured session verify cleanly against the publisher's ads.txt, with zero "not authorized" entries and no DIRECT/RESELLER mismatches. A 100% verified rate on a stack this size means the publisher's ads.txt file is well-maintained and the chain of trust between the publisher and each declared SSP holds.
7. Findings and open questions
Observations and open questions about the stack, ordered by estimated yield and risk impact.
- 1.
98% bid timeout rate across 3,063 bidder attempts is the headline operational issue
Of 3,063 bidder-level attempts captured across the session, 3,002 timed out before a response could land. Only 61 responses came back inside tmax. Six bidders (TripleLift, Criteo, OpenWeb, Nativo, Teads, AppNexus) returned zero measurable responses across the entire capture. The headline ATF banner slot was attempted by 12 bidders across 1,112 attempts; 5 responses landed and 0 wins resulted. With a 99.6% timeout rate and zero wins from Prebid on the premium ATF slot, that auction is effectively decided outside the Prebid layer — almost certainly by GAM line items or direct deals the wire capture does not see. Root cause: a combination of auction-start timing (Prebid's requestBids fires before ad slots are fully defined in the DOM, so bidders race a clock that started early) and per-bidder tmax misconfig (Finding 2 + Finding 3). Independent verification in Chrome DevTools (see Section 5) confirms ten bidder requests abort in a tight 1.00-1.04s cluster, which suggests a failsafeTimeout near 1,000ms is overriding the per-wrapper tmax stack-wide.
- 2.
PubMatic OpenWrap is misconfigured on the wrong tmax shelf
PubMatic's measured p50 latency in this session is 888ms. Its configured tmax is 300ms. The result is a 96% bid timeout rate on the wrapper. The 300ms shelf is reasonable for very-fast in-page banner adapters but PubMatic OpenWrap is a managed wrapper that orchestrates a server-side auction with multiple downstream demand sources; its real-world latency budget is closer to 800-1,500ms. Notably, PubMatic still passes schain on 84% of its bids (42 of 50) — the schain config is largely correct, but the timing config makes most of those bids moot because they never land. Fix: move pubmatic.com to the 1,250ms shelf, or set a bidder-level override via pbjs.bidderSettings.pubmatic.bidderTimeout = 1250.
- 3.
Criteo is on a 5,000ms tmax shelf — 4x the typical Prebid budget
The captured tmaxByWrapper shows criteo.com configured at 5,000ms — versus the Prebid default of 1,000ms and the typical managed-wrapper range of 1,250-2,000ms. Either Criteo is being treated as a priority demand source the page is willing to wait several seconds for, or it is a left-over override that lets Criteo hold up the auction render when it runs slow. In this capture, Criteo timed out on 100% of its 270 Prebid auction attempts (0 responses inside tmax) — so the 5-second budget did not help; it just sat there. Worth reviewing whether the 5,000ms shelf is intentional. If it is, the audit question is what Criteo is delivering that justifies the wait. If it is not, dropping it to 1,250ms aligns with the rest of the stack and removes a potential 4-second tail on slow page loads.
- 4.
Schain coverage gap: 5 of 13 wire-level wrappers pass it on 0% of bids
Of the 2,355 bid requests fired by wrappers we can evaluate at the wire level (Amazon TAM's 358 and Magnite Prebid Server's 8 bids excluded because both pass schain server-side), 369 (16%) carry the IAB SupplyChain object. Four wrappers pass it on 100% of their bids: Wunderkind (215 of 215), OpenX (4 of 4), Sovrn (4 of 4), Sharethrough (2 of 2). One passes it on a meaningful fraction: PubMatic OpenWrap at 84% (42 of 50). The Trade Desk direct integration sits at 25% (96 of 378). Two wrappers carry a trace amount: IX (4 of 287) and Criteo (2 of 139). Five wrappers show 0% wire-level: Magnite Fastlane, Nativo, TripleLift, Media.net, Kargo. For those five, server-side behavior is not always public; some SSPs add schain on their backend before forwarding to demand. The publisher's correct move is to confirm with each SSP rep what happens server-side, then act on the per-wrapper config gap where it remains. The fix typically lives in Prebid.js setConfig({schain}) for adapter wrappers and in each vendor's admin UI for managed wrappers and direct integrations.
- 5.
Two schain chains are propagating through the stack — Wunderkind direct and a Spotim wrapper-stamp
All 369 wire-level schain-carrying bids fall into just two chain shapes. Chain 1 — wunderkind.co (sid 340), single hop — accounts for 351 bids and is observed on Wunderkind, PubMatic OpenWrap, and The Trade Desk direct. This is the publisher's primary schain config propagated through the demand paths that accept it. Chain 2 — spotim.market (sid pub_mM0DBXIIardI), single hop — accounts for 18 bids and is observed on OpenX, Index Exchange, Sovrn, Criteo/Grid, Sharethrough, and PubMatic. Spotim is the parent company of OpenWeb. The presence of the Spotim chain on bids fired through six different SSPs means OpenWeb is wrapping the Prebid auction at some level and stamping its own seller identity (Spotim) onto the chain before those SSP-bound bids fire. Operationally this is something to be aware of: when buyers downstream see those bids, the declared chain points to Spotim, not directly to CNN. Whether that is the intended config for OpenWeb's integration here is worth confirming with the OpenWeb account team.
- 6.
Wrapper stack appears geo-segmented between US and international CNN properties
A separate capture on edition.cnn.com (CNN's international property, run during tool development before this issue went to draft) showed a materially different wrapper stack than the one captured here on www.cnn.com. The international property had The Ozone Project (a UK-focused header bidding consortium) and Sharethrough actively participating, neither of which appears with comparable volume on the US property captured for this issue. The US property here shows Wunderkind, Media.net, Kargo, TripleLift, Nativo, OpenWeb, Teads, OpenX, Sovrn, and AppNexus. Geo-segmented wrapper configs are common at this publisher size and align with how Ozone in particular is documented. Worth a dedicated follow-up issue covering both properties side by side to characterize the demand-stack split.
Related from MonetizationGuy
Running a prebid stack on a real publisher?
If your site has a comparable wrapper setup and you want a full audit, not just a wire capture but a real walk-through of your prebid.js config, schain coverage, bid timeout rate, and supply chain health, the free 30-minute call is the starting point.
Or run the Beamflow Chrome extension on your own site as a starting point. The capture takes two minutes and the schain coverage and timeout views are the same data this teardown was built on.
Book a Free 30-Min Call