The industry's first cross-origin isolated auction architecture.
Zero competitors. 140+ automated tests. Production-ready.
One script tag. Automatic role detection. Zero configuration. The auction runs in a secure cross-origin frame while the publisher page stays lean and fast.
| Metric | Traditional HB (per placement) | Cross-Frame HB (per placement) |
|---|---|---|
| Wrapper + Prebid JS (gzipped) | 100–200 KB | 15–20 KB (worker proxy only) |
| Config payload | 100KB–1MB (RON networks) | 0 KB (config lives in CORE) |
| Parse time (mobile) | 400–800 ms | 60–80 ms |
| Main thread blocked | Yes | No (separate process) |
Chrome's Site Isolation and Firefox's Fission give cross-origin iframes their own renderer process — a separate thread, separate V8 heap, separate garbage collector. The auction engine literally cannot block the publisher's page.
| Competitor | Auction Isolated? | Cross-Origin Comms? | Reduced Bundle? |
|---|---|---|---|
| Prebid.js | No | No (except AMP) | No (100–200KB gzipped) |
| Amazon TAM | S2S (not iframe) | N/A | Thin client |
| Index Exchange | No | No | Partial |
| PubMatic OpenWrap | No | No | No |
| Magnite | No | No | Partial |
| Criteo Direct Bidder | No | No | Somewhat (~50KB) |
| Google Open Bidding | S2S only | N/A | Yes (locked to Google) |
| Freestar | No | No | Partial |
| Mediavine | S2S | No | Partial |
| Playwire RAMP | No | No | No |
| HBMP Cross-Frame | YES | YES | YES (15–20KB) |
__tcfapiLocator frame-walking protocol must work across frame boundaries for consent to reach all auction participants.
__tcfapiLocator proxy installed in worker frames — CMP discovery works transparently across frame boundariesIntersectionObserver directly in the WORKER frame for reliable, IAB-compliant viewability detection that works with both withDFP=1 and withDFP=0.
IntersectionObserver in WORKER detects 50% visibility for 1 second (IAB standard), relays IMPRESSION_VIEWABLE to CORE via woof — works with both withDFP=1 and withDFP=0visible1Sec state from relayed IO events across frame boundaries, including withDFP=0 refreshesonBidViewable callbacks fire for all placements (CORE + WORKER) via $pbjs$.markBidViewable bridge — resolves winning bid by adId at fire timeIntersectionObserver in WORKER monitors ad slot containers (50% threshold + 1s IAB timer)IMPRESSION_VIEWABLE to CORE via woof, then unobserves until next refresh re-armsvisibility:*:visible1sec — statistics fires multitracking events 18/20, placement state updateswinnerTargetingHook registers a permanent viewability handler per element that calls $pbjs$.markBidViewable({ adId })adId, calls adapterManager.callBidViewableBidder() — adapters receive onBidViewable(bid)/demo/viewable fetch on initial and refresh) and negative path (ad below viewport — no IO, no events, no adapter callback) both covered by automated tests.
Transparent googletag API hooking — defineSlot, display, refresh are all intercepted. The publisher's existing GPT code works completely unchanged.
| Approach | Time to First Auction | Publisher Code Changes |
|---|---|---|
| DIY Prebid.js | 2–4 weeks | Major |
| Managed wrappers | Days to weeks | Moderate |
| Tag-based wrappers | Hours | Minor |
| HBMP Cross-Frame | Zero (publisher-side) | None |
page_url problem: When ads render inside a cross-origin iframe, Google loses the publisher’s page context. Without page_url, AdSense contextual targeting breaks — Google may filter AdSense demand from the auction entirely, costing significant revenue on AdSense-heavy setups.
ref= Parameter?ref= query parameter on the iframe srcref and sets both page_url and adsense_url on GPT via googletag.setConfig({ adsenseAttributes })?ref= param → window.top.location.href (friendly frame) → document.referrer (cross-origin). Always resolves a value.page_url via GPT config, the wrapper does not override it?lang= parameter is also supported for document_language targeting (falls back to document.documentElement.lang)CORE_ELECTED to all child frames.navigator.locks with ifAvailable: true — exactly one frame acquires the lock, all others instantly resolve as WORKER. No timeouts, no races./etc/hosts entries for a.test, b.test, c.test pointing to 127.0.0.1. Dev server must be running.