Summary
APS OpenRTB bids never render. Every APS bid fails with Prebid's Missing ad markup or URL (reason noAd), so the slot is served an empty creative.
Root cause
APS is bid-by-reference: interpretResponse sets the renderer descriptor on the Prebid bid as the custom trustedServerRenderer field, and a bidResponse listener (installApsBidResponseRegistry) registers it into window.tsjs.apsPrebidRenderers keyed by Prebid's generated adId. The GAM Universal Creative later requests that adId and the bridge serves the APS creative.
Prebid normalizes each bid into its own internal object during addBidResponse and drops unknown top-level fields, so the custom trustedServerRenderer field is gone before the bidResponse listener runs. The listener sees renderer === undefined, returns without registering, and the registry stays empty. When the Universal Creative requests the descriptor, the bridge finds nothing and Prebid's default renderer throws Missing ad markup or URL.
Evidence
Observed on a live deployment with a runtime-instrumented registry:
- The custom field is absent as early as the
bidAccepted event (the earliest bid event), for every APS bid.
- The renderer registry receives zero writes across a full session (
registrationsCount: 0, validated by proxying the registry object).
- The descriptor itself is valid and registers correctly when exercised in isolation — so it is delivered by
/auction and set by interpretResponse, then lost in Prebid's pipeline.
- Result: all APS render failures are
bidder=aps, reason=noAd.
Impact
APS renderer bids do not render at all. This affects any deployment serving first-class APS OpenRTB bids.
Fix direction
Make registration independent of the custom field surviving Prebid's normalization: also stash the descriptor keyed by requestId (a first-class field Prebid preserves) at interpretResponse time, and fall back to it in the bidResponse listener when the custom field is absent.
Summary
APS OpenRTB bids never render. Every APS bid fails with Prebid's
Missing ad markup or URL(reasonnoAd), so the slot is served an empty creative.Root cause
APS is bid-by-reference:
interpretResponsesets the renderer descriptor on the Prebid bid as the customtrustedServerRendererfield, and abidResponselistener (installApsBidResponseRegistry) registers it intowindow.tsjs.apsPrebidRendererskeyed by Prebid's generatedadId. The GAM Universal Creative later requests thatadIdand the bridge serves the APS creative.Prebid normalizes each bid into its own internal object during
addBidResponseand drops unknown top-level fields, so the customtrustedServerRendererfield is gone before thebidResponselistener runs. The listener seesrenderer === undefined, returns without registering, and the registry stays empty. When the Universal Creative requests the descriptor, the bridge finds nothing and Prebid's default renderer throwsMissing ad markup or URL.Evidence
Observed on a live deployment with a runtime-instrumented registry:
bidAcceptedevent (the earliest bid event), for every APS bid.registrationsCount: 0, validated by proxying the registry object)./auctionand set byinterpretResponse, then lost in Prebid's pipeline.bidder=aps,reason=noAd.Impact
APS renderer bids do not render at all. This affects any deployment serving first-class APS OpenRTB bids.
Fix direction
Make registration independent of the custom field surviving Prebid's normalization: also stash the descriptor keyed by
requestId(a first-class field Prebid preserves) atinterpretResponsetime, and fall back to it in thebidResponselistener when the custom field is absent.