Skip to content

Nexx360 Analytics Adapter: add analytics adapter - #15388

Open
gchicoye wants to merge 3 commits into
prebid:masterfrom
nexx360:nexx360-analytics-agent
Open

Nexx360 Analytics Adapter: add analytics adapter#15388
gchicoye wants to merge 3 commits into
prebid:masterfrom
nexx360:nexx360-analytics-agent

Conversation

@gchicoye

@gchicoye gchicoye commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Type of change

  • Feature
  • Does this change affect user-facing APIs or examples documented on http://prebid.org? — new analytics adapter; docs PR to prebid.github.io linked below.

Description of change

Adds the Nexx360 Analytics Adapter (nexx360Analytics), an endpoint-type analytics adapter that reports Prebid auction activity to the Nexx360 monitoring collector.

  • Buffered per auction, flushed once on auctionEnd: auctionInit, bidRequested, bidResponse, bidTimeout.
  • Sent immediately: bidWon, adRenderSucceeded, adRenderFailed (failure carries reason).
  • serverAuction event: libraries/nexx360Utils attaches server-side auction data from the Nexx360 OpenRTB response ext to each bid response it produces (serverAuctionData); when a nexx360 bid response carrying that data is seen, a serverAuction event is synthesized (once per auction). Because the data travels with the bid that produced it, it cannot leak into an unrelated auction.
  • Beacons POST a JSON array to ${endpoint}/events (default https://monitoring.nexx360.io) using noCredsAjax with contentType: 'text/plain' and keepalive: true, so the cross-origin request is a CORS simple request (no preflight), carries no credentials, and survives page navigation.
  • Sampling is applied server-side; the adapter exposes no sampling option.

Config (enableAnalytics options): publisherId (required), endpoint (optional), abTestLabel (optional). Options are typed via the AnalyticsProviderConfig augmentation from #15467 (Nexx360AnalyticsOptions).

Rules compliance: uses the shared AnalyticsAdapter base (provides disableAnalytics); no storage (gvlid: null); TypeScript public types provided.

Also extends libraries/nexx360Utils (already used by the merged Nexx360 Bid Adapter) so interpretResponse attaches serverAuctionData to bid responses, plus a types module — a functional dependency of the serverAuction event.

Maintainer: tech@nexx360.io

Testing

  • eslint on changed files — clean.
  • Unit tests — 26 passing (adapter + nexx360Utils server-auction spec).
  • Coverage on added/modified code: adapter ~96.9% lines / 97.0% functions / 94.3% branches; nexx360Utils additions 100%.

Other information

  • Documentation PR: to be linked (prebid.github.io).

Docs PR: prebid/prebid.github.io#6680

@github-actions

Copy link
Copy Markdown

This PR includes an adapter whose code does not match its file name. Bid adapter modules should be named <bidderCode>BidAdapter, userId <userIdCode>IdSystem, RTD <rtdCode>RtdProvider, and analytics <analyticsCode>AnalyticsAdapter.

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown

This PR introduces changes that may not work on all browsers. According to Babel, the following polyfills may be needed, and they are not automatically included:

  • Changes to modules/nexx360AnalyticsAdapter.ts may need:
    • es.array.push
    • es.iterator.constructor
    • es.iterator.for-each
    • es.iterator.map
    • es.json.stringify
    • es.set.difference.v2
    • es.set.intersection.v2
    • es.set.is-disjoint-from.v2
    • es.set.is-subset-of.v2
    • es.set.is-superset-of.v2
    • es.set.symmetric-difference.v2
    • es.set.union.v2
    • esnext.iterator.constructor
    • esnext.iterator.for-each
    • esnext.iterator.map
    • esnext.set.difference.v2
    • esnext.set.intersection.v2
    • esnext.set.is-disjoint-from.v2
    • esnext.set.is-subset-of.v2
    • esnext.set.is-superset-of.v2
    • esnext.set.symmetric-difference.v2
    • esnext.set.union.v2
  • Changes to test/spec/libraries/nexx360Utils/serverAuction_spec.js may need:
    • es.iterator.constructor
    • es.iterator.for-each
    • esnext.iterator.constructor
    • esnext.iterator.for-each
  • Changes to test/spec/modules/nexx360AnalyticsAdapter_spec.js may need:
    • es.iterator.constructor
    • es.iterator.filter
    • es.iterator.find
    • es.iterator.for-each
    • es.iterator.map
    • es.iterator.some
    • esnext.iterator.constructor
    • esnext.iterator.filter
    • esnext.iterator.find
    • esnext.iterator.for-each
    • esnext.iterator.map
    • esnext.iterator.some
    • esnext.json.parse

The best way to address this is to provide good test coverage, as normal PR checks run unit tests on older browsers.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b12c995d02

ℹ️ 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".

Comment thread modules/nexx360AnalyticsAdapter.ts Outdated
Comment thread libraries/nexx360Utils/index.ts Outdated
@barecheck

barecheck Bot commented Jul 24, 2026

Copy link
Copy Markdown

Barecheck - Code coverage report

Total: 91.17%

Your code coverage diff: 0.03% ▴

Uncovered files and lines
FileLines
libraries/nexx360Utils/index.ts83-84, 112-113, 205
modules/nexx360AnalyticsAdapter.ts644, 674, 680, 689

Adds the nexx360 endpoint analytics adapter. It buffers per-auction
events (auctionInit, bidRequested, bidResponse, bidTimeout) and flushes
them on auctionEnd, and sends bidWon / adRenderSucceeded / adRenderFailed
immediately. When a nexx360 bid response arrives, a serverAuction event
is synthesized from server-side auction data on the OpenRTB response ext.
Beacons POST as text/plain (no CORS preflight) with no credentials.
Sampling is applied server-side.

Also extends libraries/nexx360Utils (used by the Nexx360 Bid Adapter)
with extractServerAuction / getLastServerAuctionData /
clearLastServerAuctionData plus a types module, which the serverAuction
event depends on.

Maintainer: tech@nexx360.io

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NGAcCirXcABf5miqJbouV2
@gchicoye
gchicoye force-pushed the nexx360-analytics-agent branch from b12c995 to 59f6343 Compare July 25, 2026 06:15
@gchicoye

gchicoye commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Hi @monis0395, @jsnellbaker , any news on that?

@monis0395

Copy link
Copy Markdown
Collaborator

@codex review also check for public interfaces rule in PR_Review.md

@monis0395

Copy link
Copy Markdown
Collaborator

Hi @monis0395, @jsnellbaker , any news on that?

@gchicoye overall the PR looks good! I just need to confirm one thing related to exporting of types for analytics. Will let you know once done!

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59f6343c8b

ℹ️ 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".

Comment thread libraries/nexx360Utils/index.ts Outdated
return [];
}

extractServerAuction(respBody);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear server auction data when bids are rejected

Fresh evidence in the current revision is that ext.serverAuction is still copied into a module-level slot before any returned bid is validated by core. When the Nexx360 response contains a seatbid entry but the bid is malformed or rejected by isValid (for example, missing price makes cpm undefined, or createResponse throws after this assignment), no BID_RESPONSE analytics path runs to consume or clear the slot, so the next unrelated accepted Nexx360 bid can emit this stale server auction under the wrong auction.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cb6bdb6 by removing the module-level slot entirely. interpretResponse now attaches the server-auction data to every bid response it returns (serverAuctionData field), and the analytics adapter reads it from the bidResponse event args. The data travels with the bid that produced it, so a bid rejected by core (or a createResponse throw) can no longer leave stale data behind for an unrelated auction — the whole stale-slot class of bugs is gone. getLastServerAuctionData/clearLastServerAuctionData are removed; tests updated accordingly.

Comment on lines +646 to +649
}, JSON.stringify(events), {
contentType: 'text/plain',
method: 'POST',
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Set keepalive on analytics POSTs

For analytics POSTs emitted at BID_WON/AD_RENDER_* or flushed at auction end, page navigation can occur before a normal fetch completes; this options object omits keepalive, so those low-priority telemetry events are more likely to be dropped during unload. Add keepalive: true to the ajax options.

AGENTS.md reference: AGENTS.md:L71-L71

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cb6bdb6keepalive: true added to the ajax options so the low-priority telemetry POSTs survive page navigation.

Comment thread modules/nexx360AnalyticsAdapter.ts Outdated

const originEnableAnalytics = nexx360AnalyticsAdapter.enableAnalytics;

nexx360AnalyticsAdapter.enableAnalytics = function(config: { options?: Partial<AnalyticsOptions> }) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Type the public analytics options

The only typing for Nexx360's publisher-facing config is this private wrapper parameter, so pbjs.enableAnalytics({ provider: 'nexx360', options: ... }) still falls back to the generic analytics config shape and TypeScript consumers do not get checks for required publisherId or the endpoint/abTestLabel option names. Add a provider-specific AnalyticsProviderConfig module declaration for the 'nexx360' options instead of keeping the interface local-only.

AGENTS.md reference: AGENTS.md:L24-L24

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cb6bdb6. The branch is now synced with master to pick up #15467, and the adapter exports Nexx360AnalyticsOptions and registers it via the AnalyticsProviderConfig module augmentation (same pattern as pgamdirectAnalyticsAdapter), so pbjs.enableAnalytics({provider: 'nexx360', options}) is fully typed with publisherId required.

@patmmccann patmmccann removed the core label Aug 5, 2026
@patmmccann
patmmccann removed the request for review from jsnellbaker August 5, 2026 16:31
@monis0395

Copy link
Copy Markdown
Collaborator

@gchicoye Please go through the Codex comments and address or resolve them. Also, once PR #15467 is merged, please expose the adapter options types as well.

Gabriel Chicoye and others added 2 commits August 7, 2026 16:15
- Attach server-auction data to each bid response instead of holding it
  in module state, so it travels with the bid that produced it and can
  no longer leak into an unrelated auction when a bid is rejected by
  core (removes getLastServerAuctionData/clearLastServerAuctionData).
- Add keepalive: true to analytics POSTs so low-priority telemetry
  survives page navigation.
- Expose publisher-facing options types via the AnalyticsProviderConfig
  augmentation introduced in prebid#15467.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018xpKEXiu3WKjAC9iBwAcVi
@gchicoye

gchicoye commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@monis0395 All Codex comments are addressed in cb6bdb6 (branch synced with master):

  • Stale server-auction slot: removed the module-level slot entirely — interpretResponse now attaches the server-auction data to each bid response it returns, and the analytics adapter reads it from the bidResponse event args. Data travels with the bid that produced it, so a rejected/malformed bid can no longer leak it into another auction.
  • keepalive: analytics POSTs now set keepalive: true.
  • Public options types: now that Core: fix analytics provider configuration types #15467 is merged, the adapter exports Nexx360AnalyticsOptions and registers it via the AnalyticsProviderConfig module augmentation (same pattern as pgamdirectAnalyticsAdapter), so enableAnalytics({provider: 'nexx360'}) is fully typed.

Lint clean, 26 unit tests passing, tsc clean on the changed files. PR description updated accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants