Pin and browser-test the GAM-served PUC render contract for inline SSAT creatives #926
Description
Context
PR #899 ships the winning creative inline in window.tsjs.bids[...].adm, rendered
by the Prebid Universal Creative (PUC) via the pbRender bridge
(installTsRenderBridge → TS_DISPLAY_RENDERER, f.srcdoc = d.ad) inside GAM's
iframe. Several open questions about the GAM-served PUC render contract were
deferred from that PR; this task tracks pinning and testing it.
Why load-bearing: the render context (which origin the srcdoc document's base
URL inherits, whether PUC honors a custom renderer) determines whether the
inline adm's asset/click URLs resolve. PR #899 mitigated the immediate risk by
emitting absolute first-party URLs (crate::creative::rewrite_inline_creative_html
→ https://<publisher.domain>/first-party/…), which resolve regardless of the
document base URL and regardless of whether the custom renderer is honored.
Confirming the actual contract closes the remaining questions below.
Tasks
- Pin the PUC version/template used by the GAM-served bundle. Confirm
whetherrendererVersion >= 3(so the customrendererfield —
TS_DISPLAY_RENDERER— is honored) or whether PUC's own fallback path renders
d.ad. Record the pinned version/template. - Add a browser contract test against the GAM-served PUC bundle that
exercises the end-to-end inline render (mocktioneer bid winning so the bridge
actually fires). Per PR Render SSAT winning creative inline without PBS Cache round trip #899's test plan this path was never exercised —
GAM usually awards its own demand, so the bridge never fired. The test should
assert the absolute first-party URLs in the inlineadmresolve in the render
context. - Confirm cookie context: verify whether first-party proxy requests
issued from GAM's iframe are a third-party cookie context, so EC cookies may
not attach as they would first-party. Assess impact on measurement/attribution. - JS decline-fast (
gpt/index.tsinstallTsRenderBridge): once the PUC
version is pinned, reply to a declined "Prebid Request" withadRenderFailed
(PUC 1.18.0 emits it) so the slot fails fast / collapses instead of staying
blank afterstopImmediatePropagation(). Applies to both the inline-adm
decline and the PBS Cache.catch/no-admdecline. - Aggregate inline-
admbyte cap: the 1 MiB cap in
sanitize_creative_htmlis per-creative.build_bid_mapinlines the creative
for every winning slot into the page's<script>, so N slots can inline up to
N MiB with no aggregate bound — pure document-weight/TTFB cost in the common
case where GAM awards its own demand and the bridge never fires. Add an
aggregate budget inbuild_bid_map(omitadmpast the budget → fall back to
PBS Cache coordinates), or a narrower condition for inlining.
References
- PR Render SSAT winning creative inline without PBS Cache round trip #899 (feat/ssat-render-inline-creative)
crates/trusted-server-core/src/publisher.rs—build_bid_mapcrates/trusted-server-core/src/creative.rs—rewrite_inline_creative_htmlcrates/trusted-server-js/lib/src/integrations/gpt/index.ts—installTsRenderBridge,TS_DISPLAY_RENDERER,extractCachedAdm
Activity