Skip to content

Injected script calls the EC route on consent and merges the IDs into Prebid #1599

Description

@aram356

Summary

The injected script calls the EC route with a same-origin POST when the CMP reports consent and on every later change, sends consent changes in order with one call in flight, letting a newer change replace a waiting one but never a waiting withdrawal, which later changes wait behind, discards a result overtaken by a newer consent change, removes the IDs it merged on a withdrawal, sends the TCF string and the GPP string (Sourcepoint's capture from #1535), copies a localStorage _pubcid_optout into the cookie, and merges the returned IDs into Prebid.

Part of #1558, server-side identity on every adapter. Plan ID T20, planned in wave 8 (MVP: Fastly and Axum); priority P1, size M. Design: spec; order and dependencies: plan.

Requirements

ID-9 EC route

A same-origin route, /_ts/api/v1/ec by default, lets the script Trusted Server injects into proxied pages report consent and receive identity, so a reader who consents after the page loads gets an EC on that page view instead of the next navigation. A POST whose Origin matches the page mints the EC when the reader has none and consent allows, creates the record, runs the providers as a navigation does, and sets ts-ec, the SharedID cookie and the mirror cookie on its own response. It carries the consent strings the script reads from the CMP, the TCF string from __tcfapi and the GPP string from __gpp (Sourcepoint's capture from #1535 where present), which replace the consent cookies for that request; a withdrawal expires ts-ec, the SharedID cookie and the mirror cookie and tombstones the record in that response. The POST answers with JSON holding exactly what WB-4 would put in the mirror cookie for that request, and the SharedID only under SID-2 and SID-6; the script merges it into Prebid, and nothing else in the record reaches the page. A plain GET answers Prebid's SharedID pixelUrl with an empty 204: it never mints, calls a provider or changes consent, and only re-sets an existing SharedID cookie from the record (WB-3). The script sends consent changes in order with at most one call in flight. While a call is in flight, a newer change replaces a waiting one, except a waiting withdrawal, which is never replaced: later changes wait behind it. So every withdrawal reaches the server, after any grant in progress and before any later grant. The script discards a result that arrives while a newer consent change is waiting, and a withdrawal removes the IDs it merged into Prebid. Every response carries Cache-Control: no-store; a rate limit on the route waits with ID-6 (DEC-15). The route is served from the page's own host, which WebKit's cap on cookies from non-document responses exempts when the IP matches the page's (read from WebKit's source; the Accept tests it).

WB-6 Identity-only page script

A tsjs mode captures Prebid's IDs without the auction shim, reads the mirror cookie and merges the IDs into Prebid.

SID-2 Opt-out

A _pubcid_optout cookie stops SharedID reads, storage, sending, creation and write-back. Prebid also reads the opt-out from localStorage, which the server cannot see, so the injected script copies a localStorage _pubcid_optout into the cookie (T20).

Current state

What the code does today, from the design's survey at the revisions it names:

  • ID-9: on main only a real-browser navigation through the publisher proxy mints an EC, and no such route exists. Extract existing Sourcepoint consent synchronization #1535 (RC line) posts Sourcepoint's GPP string to a separate, non-minting /_ts/consent route, wired into each adapter's router.
  • WB-6: the ts-eids capture runs only inside the shim, and nothing reads the mirror.

Acceptance criteria

  • ID-9: On Fastly and Axum, a consented same-origin POST with no ts-ec creates the record and sets ts-ec and the SharedID cookie in that response
  • ID-9: Its JSON omits a non-mirrored partner's ID, an ID whose vendor's TCF consent is denied and an expired ID
  • ID-9: A withdrawal issued while a grant call with no EC and delayed providers is in flight leaves no identity cookie, no live record and no ID in Prebid
  • ID-9: With grant A in flight, a withdrawal B and then a grant C reach the server as A, B, C, so B expires the identity cookies and tombstones A's record and C is handled as a first consent with no ts-ec
  • ID-9: A cross-site Origin, a GET and a client ID-7 refuses mint nothing and call no provider
  • ID-9: An unchanged returning reader gets no Set-Cookie
  • ID-9: In Safari, ts-ec and the SharedID cookie set by the route keep their one-year Max-Age on Fastly and on Axum behind CloudFront
  • WB-6: In that mode Prebid receives the mirrored IDs and no Trusted Server bidder is added to ad units
  • SID-2: With _pubcid_optout present nothing SharedID-related is read, stored, sent, created or written, and a localStorage-only opt-out stops creation from the next request on

Dependencies

Blocked by:

Related pull requests

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions