Skip to content

Distinguish empty PBS demand from stored-request intent #1086

Description

@ChristianPavilonis

Description

TSJS injects a synthetic trustedServer bidder into every ad unit so providers configured with routing = "all_eligible", such as APS, can participate even when the publisher did not configure inline server-side bidders for that slot.

When such a slot has no plan-owned bidder parameters, TSJS sends this envelope:

{
  "bidderParams": {}
}

The auction router currently treats missing, null, and empty bidderParams as intentional Prebid Server stored-request demand. It routes the slot to every configured prebid-server provider and builds:

{
  "ext": {
    "prebid": {
      "storedrequest": {
        "id": "<dynamic-slot-code>"
      }
    }
  }
}

For a dynamic slot with no matching stored impression, PBS returns HTTP 400. That rejects the provider's complete OpenRTB request, including otherwise valid impressions with inline bidder parameters. Multiple PBS provider instances repeat the same failing stored-request lookup. Other all_eligible providers can still succeed independently.

An empty bidder map is ambiguous. It can mean either "invoke all-eligible providers with no PBS demand" or "load a PBS stored impression." The router should not infer both cases from the same shape.

This was observed while validating #1016, but it is unrelated to per-provider OpenRTB test: 1 behavior.

Suggested fix

Add explicit stored-request intent to the trustedServer envelope, for example:

{
  "bidderParams": {},
  "storedRequest": false
}

TSJS-generated envelopes used only to invoke all-eligible providers should set storedRequest: false. Routing should then skip explicit PBS providers for that slot while still admitting all_eligible providers.

Intentional PBS stored demand should use storedRequest: true. Omitted values can preserve the legacy stored-request behavior during migration if compatibility requires it. Direct server-generated opportunities should continue to use trusted server-owned routing rather than allowing the browser to select a provider.

Regression coverage should include:

  • an APS all-eligible slot with no PBS bidder parameters, which reaches APS and skips every explicit PBS provider;
  • explicit stored-request intent, which retains the existing PBS path;
  • inline bidders split across multiple PBS provider instances;
  • one no-PBS slot alongside valid inline PBS impressions, proving it cannot cause a provider-wide HTTP 400.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions