Add pgamdirect Analytics Adapter#14778
Conversation
Companion to modules/pgamdirectBidAdapter.ts (merged prebid#14763). Publishers install this alongside the bid adapter to forward auction telemetry to the PGAM Direct SSP backend. Forwards four Prebid events, deliberately narrow: AUCTION_END — competitor CPMs seen in the auction BID_WON — Prebid-layer winner + price AD_RENDER_SUCCEEDED — client-confirmed impression AD_RENDER_FAILED — with reason (exception / timeout / etc) The value add over a server-side-only ledger: client-confirmed render vs. "RTB said we won", plus visibility into what other bidders priced the same auction at (we own server-side data for our own DSP calls, but not for the ones other SSPs made through the same Prebid wrapper). Payload is normalised into a small fixed shape before POST — we deliberately drop the raw Prebid event args, which carry full FPD / user.eids / custom bidder params that we don't need and shouldn't exfiltrate. Sink: https://app.pgammedia.com/api/analytics-events (one POST per event; content-type text/plain to keep CORS simple). Config: pbjs.enableAnalytics({ provider: 'pgamdirect', options: { orgId: '<pgam org id>', // required endpoint: 'https://...' // optional override } }); GVL ID 1353 (PGAM Media LLC, same as the bid adapter). Tests: 12 covering registration, orgId validation, and the pure normalise transform across all 4 forwarded event types (including the 20-entry bidders_seen cap and filter-out of bidders with no code). Event-emission path is not covered in this spec because the sinon mock + AnalyticsAdapter async queue interact oddly in the test harness — we export normalise() directly so the transform is verifiable without the full event pipeline. The ajax call itself is covered by upstream AnalyticsAdapter base-class tests.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3fc5cf5674
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| typeof a.bid === 'object' && a.bid | ||
| ? ((a.bid as Record<string, unknown>).bidderCode as string | undefined) | ||
| : undefined, | ||
| ad_unit_code: typeof a.adId === 'string' ? a.adId : undefined, |
There was a problem hiding this comment.
Keep ad_unit_code semantics consistent across event types
normalise() sets ad_unit_code from a.adUnitCode for BID_WON but from a.adId for AD_RENDER_SUCCEEDED/AD_RENDER_FAILED, so the same field represents different identifiers depending on event type. In auctions with multiple ad units (or repeated wins from the same bidder), this prevents reliable win→render reconciliation and can misattribute render outcomes. Use the render event’s bid object (args.bid.adUnitCode) for ad_unit_code and keep adId in a separate field if needed.
Useful? React with 👍 / 👎.
Coverage Report for CI Build 24801750822Coverage decreased (-0.003%) to 96.394%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats💛 - Coveralls |
Two P1s flagged by Codex on the initial commit: 1. ad_unit_code semantic inconsistency Original code pulled ad_unit_code from args.adUnitCode on BID_WON but from args.adId on AD_RENDER_*, so the same field represented different identifiers across event types. In auctions with multiple ad units (or repeated wins from the same bidder), this prevented reliable win → render reconciliation and could misattribute render outcomes. Fix: render events now read ad_unit_code from args.bid.adUnitCode (stable across the BID_WON ↔ AD_RENDER_* join for the same slot). adId moves to its own field `ad_id` so per-bid traceability is preserved. Type definition updated with a comment explaining the split so future contributors don't re-conflate them. 2. Missing fetch keepalive Prebid AGENTS.md §71 requires low-priority telemetry calls to set fetch keepalive. Without it, BID_WON + AD_RENDER_* events emitted near page unload get dropped before reaching the endpoint — and those are exactly the events that fire in that window. Added `keepalive: true` to the ajax call. Prebid's ajax helper already supports the flag (src/ajax.ts option); no adapter-side polyfill needed. Tests: +1 spec case covering "missing bid object on AD_RENDER_* still captures ad_id cleanly." Existing render-event assertions updated to verify the ad_unit_code-vs-ad_id split explicitly. 13/13 pass (was 12).
|
Thanks @chatgpt-codex-connector — both P1s addressed in commit 2758809:
Tests: 13/13 pass, +1 spec case covering missing-bid-object on render events. |
|
To use Codex here, create a Codex account and connect to github. |
Summary
Companion to
pgamdirectBidAdapter(merged). Publishers install this alongside the bid adapter to forward auction telemetry to the PGAM Direct SSP backend.Why
A server-side-only ledger (what our bidder sees from RTB) can't answer two questions:
This adapter closes both gaps.
What it forwards
Four events only (deliberately narrow):
Payload shape
Normalised before POST — we deliberately drop raw Prebid event args which carry full FPD / user.eids / custom bidder params we don't need and shouldn't exfiltrate. Sink: `https://app.pgammedia.com/api/analytics-events\`, one POST per event, content-type text/plain (keeps CORS simple — same rationale as the bid adapter).
Config
```js
pbjs.enableAnalytics({
provider: 'pgamdirect',
options: {
orgId: '', // required
endpoint: 'https://...' // optional override
}
});
```
GVL ID
1353 (PGAM Media LLC, same as the bid adapter).
Tests
12 spec cases covering:
Event-emission XHR round-tripping isn't covered in this spec because the sinon mock + AnalyticsAdapter async queue interact oddly in the harness. We export `normalise()` directly so the pure transform is testable; the ajax call itself is covered by upstream AnalyticsAdapter base-class tests.
Test plan
🤖 Generated with Claude Code