Skip to content

New Module: ZeroGPU Real Time Data - #4906

Open
amaan-ai20 wants to merge 1 commit into
prebid:masterfrom
zerogpu:zerogpu-rtd-module
Open

New Module: ZeroGPU Real Time Data#4906
amaan-ai20 wants to merge 1 commit into
prebid:masterfrom
zerogpu:zerogpu-rtd-module

Conversation

@amaan-ai20

@amaan-ai20 amaan-ai20 commented Aug 12, 2026

Copy link
Copy Markdown

New Module: ZeroGPU Real Time Data

This PR adds zerogpu.rtd, a general module that enriches an incoming OpenRTB request with IAB content categories derived from the publisher's domain.

On each auction the module resolves the domain from the bid request, classifies it with ZeroGPU's zlm-v1-iab-domain-classifier model, and appends the resulting categories to {site,app,dooh}.content.data as Seller-Defined contextual segments under ext.segtax: 6 (IAB Content Taxonomy 2.2).

Because the segments are written to standard First Party Data fields, every bidder in the auction can read them — no bidder-specific integration is required, per the Module Rules requirement that RTD modules make data available cross-bidder.

Documentation PR: prebid/prebid.github.io#6700

The auction never waits on ZeroGPU

The hook reads an in-process cache and does no I/O. On a cache miss the auction proceeds unenriched and the classification is fetched in the background, so subsequent auctions on that domain are enriched from memory.

This matters because the classification call takes roughly 0.9s measured against the live API — far too long to sit in front of bidders. Measured hook cost is ~15µs whether the domain is cached or not.

Consequences of the design, all deliberate:

  • The first impressions on a newly-seen domain go unenriched. After that the domain is cached for 24h.
  • Concurrent auctions for the same uncached domain collapse onto a single outbound request, so a traffic burst on a new domain does not produce a burst of API calls.
  • Warm-ups use the module's own lifetime context rather than the hook context. The hook context is cancelled at the execution plan's group timeout, which would abort the warm-up and leave the domain permanently cold.
  • Shutdown() cancels in-flight warm-ups and waits for them, so no goroutine outlives the host.

Every failure mode is fail-open: a slow, unreachable, or erroring API leaves auctions unenriched. The module never rejects a request, never delays one, and never creates bids.

Stage choice

processed_auction_request — the last point at which the request is still shared by every bidder, after stored requests are merged, and where account-level config is available. Running at bidder_request would warm the same domain once per bidder.

Privacy

The default configuration sends only a domain to ZeroGPU and writes only contextual data. No user identifiers, device data, or geographic information leave Prebid Server, and nothing is written to user-scoped ORTB fields. Under the default configuration the module has no user privacy implications.

enrich_user_audience is opt-in and defaults to false. When enabled it writes IAB Audience Taxonomy 1.1 segments to user.data. It is off by default for two reasons, both documented in the module README and on the docs page:

  1. The segments are inferred from the domain, not observed from the user.
  2. add-a-module.md requires a module supplying user-level data to check the enrichUfpd Activity Control, and PBS-Go does not currently expose activity controls to modules, so the module cannot perform that check on the host's behalf.

The module does not create bids and does not add pixels to creatives.

Configuration

api_key is the only required parameter; everything else has a working default. A complete host configuration is in modules/zerogpu/rtd/sample/pbs_example.json, and all parameters are documented in modules/zerogpu/rtd/README.md.

hooks:
  enabled: true
  modules:
    zerogpu:
      rtd:
        enabled: true
        api_key: ${ZEROGPU_API_KEY}
  host_execution_plan: >
    {
      "endpoints": {
        "/openrtb2/auction": {
          "stages": {
            "processed_auction_request": {
              "groups": [{
                "timeout": 10,
                "hook_sequence": [{
                  "module_code": "zerogpu.rtd",
                  "hook_impl_code": "zerogpu-rtd-processed-auction-request"
                }]
              }]
            }
          }
        }
      }
    }

The group timeout only has to cover an in-memory cache read, so a small value is correct. It is unrelated to timeout_ms, which bounds the background warm-up and never applies to the auction path.

account_filter.allow_list restricts a host-enabled module to specific accounts.

Testing

./validate.sh --nofmt passes — full unit test suite plus go vet, no failures. Module coverage is 97.7% of statements (go test ./modules/zerogpu/rtd -cover), above the 90% requirement, and the package is clean under -race.

Coverage includes both wire-level and behavioural cases: every documented ZeroGPU status (400/401/403/420/500), malformed and empty responses, each domain-resolution fallback, domain normalization, cache hit/miss, negative-cache TTL selection, concurrent warm-up collapsing, shutdown behaviour, each enrichment flag, account allow-list, and the request both with and without ext.prebid.data.bidders (which determines whether core's FPD processing redistributes the injected segments per bidder).

Notes for reviewers

  • modules/builder.go is regenerated with make build-modules. Only the two zerogpu additions are included; the pre-existing scientiamobile import alias in that file differs from current generator output and has been left untouched to keep this diff scoped.
  • The sample config is named sample/pbs_example.json rather than sample/pbs.json because the repository's .gitignore contains pbs.*, which matches at any depth and would silently exclude the file. This follows the existing scientiamobile/wurfl_devicedetection precedent.
  • Maintainer contact is the group address prebid@zerogpu.ai, also registered in .github/workflows/scripts/codepath-notification.

@amaan-ai20
amaan-ai20 marked this pull request as draft August 12, 2026 11:15
@amaan-ai20
amaan-ai20 marked this pull request as ready for review August 12, 2026 18:51
@bsardo bsardo added the module label Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants