You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
whether rendererVersion >= 3 (so the custom renderer field — 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 inline adm resolve 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" with adRenderFailed
(PUC 1.18.0 emits it) so the slot fails fast / collapses instead of staying
blank after stopImmediatePropagation(). Applies to both the inline-adm
decline and the PBS Cache .catch/no-adm decline.
Aggregate inline-adm byte cap: the 1 MiB cap in sanitize_creative_html is per-creative. build_bid_map inlines 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 in build_bid_map (omit adm past the budget → fall back to
PBS Cache coordinates), or a narrower condition for inlining.
Context
PR #899 ships the winning creative inline in
window.tsjs.bids[...].adm, renderedby the Prebid Universal Creative (PUC) via the pbRender bridge
(
installTsRenderBridge→TS_DISPLAY_RENDERER,f.srcdoc = d.ad) inside GAM'siframe. 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
srcdocdocument's baseURL inherits, whether PUC honors a custom
renderer) determines whether theinline
adm's asset/click URLs resolve. PR #899 mitigated the immediate risk byemitting absolute first-party URLs (
crate::creative::rewrite_inline_creative_html→
https://<publisher.domain>/first-party/…), which resolve regardless of thedocument base URL and regardless of whether the custom renderer is honored.
Confirming the actual contract closes the remaining questions below.
Tasks
whether
rendererVersion >= 3(so the customrendererfield —TS_DISPLAY_RENDERER— is honored) or whether PUC's own fallback path rendersd.ad. Record the pinned version/template.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 inline
admresolve in the rendercontext.
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.
gpt/index.tsinstallTsRenderBridge): once the PUCversion is pinned, reply to a declined "Prebid Request" with
adRenderFailed(PUC 1.18.0 emits it) so the slot fails fast / collapses instead of staying
blank after
stopImmediatePropagation(). Applies to both the inline-admdecline and the PBS Cache
.catch/no-admdecline.admbyte cap: the 1 MiB cap insanitize_creative_htmlis per-creative.build_bid_mapinlines the creativefor every winning slot into the page's
<script>, so N slots can inline up toN 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 in
build_bid_map(omitadmpast the budget → fall back toPBS Cache coordinates), or a narrower condition for inlining.
References
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