Skip to content

Comments

pubstackBidAdapter: initial release#14490

Open
gpolaert wants to merge 5 commits intoprebid:masterfrom
pbstck:master
Open

pubstackBidAdapter: initial release#14490
gpolaert wants to merge 5 commits intoprebid:masterfrom
pbstck:master

Conversation

@gpolaert
Copy link
Contributor

Type of change

  • Bugfix

  • Feature

  • New bidder adapter

  • Updated bidder adapter

  • Code style update (formatting, local variables)

  • Refactoring (no functional changes, no api changes)

  • Build related changes

  • CI related changes

  • Does this change affect user-facing APIs or examples documented on http://prebid.org?

  • Other

Description of change

Other information

* feat: add SparkBidAdapter

* fix: reviews

* fix: use iframe for user_sync

* fix: change adapter name

* fix: add test file

* feat: add viewport value in imp[].ext.prebid.bidder.pubstack.vpl

* fix: remove unused context

* Pubstack Adapter: update utils and align adapter tests

* Pubstack Bid Adapter: apply lint-driven TypeScript cleanups

---------

Co-authored-by: gpolaert <gpolaert@pubstack.io>
Copilot AI review requested due to automatic review settings February 18, 2026 21:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new Pubstack bidder adapter for Prebid.js, enabling publishers to integrate with the Pubstack exchange for header bidding.

Changes:

  • Added a new TypeScript bid adapter module (pubstackBidAdapter.ts) that supports banner, video, and native ad formats
  • Created a utility library (pubstackUtils) for viewport distance calculation and page visibility detection
  • Added comprehensive test coverage for both the adapter and utility functions
  • Updated metadata to register the new bidder with GVLID 1408

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
modules/pubstackBidAdapter.ts Main bid adapter implementing ORTB conversion, bid validation, request building, and user sync
modules/pubstackBidAdapter.md Documentation and test parameters for the Pubstack adapter
libraries/pubstackUtils/index.ts Utility functions for element location, viewport distance calculation, and page visibility
test/spec/modules/pubstackBidAdapter_spec.js Unit tests for the Pubstack bid adapter
test/spec/libraries/pubstackUtils_spec.js Unit tests for the Pubstack utility library
metadata/modules.json Registration of Pubstack bidder in module metadata

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible())
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000))
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

Missing semicolon at the end of the statement. The code style should be consistent with the surrounding code which uses semicolons to terminate statements.

Copilot uses AI. Check for mistakes.
Comment on lines 55 to 64
const request = buildRequest(imps, bidderRequest, context)
const siteId = bidderRequest.bids[0].params.siteId
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId)
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0)
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible())
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000))
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

Missing semicolon at the end of the statement. The code style should be consistent with the surrounding code which uses semicolons to terminate statements.

Suggested change
const request = buildRequest(imps, bidderRequest, context)
const siteId = bidderRequest.bids[0].params.siteId
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId)
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0)
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible())
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000))
const request = buildRequest(imps, bidderRequest, context);
const siteId = bidderRequest.bids[0].params.siteId;
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId);
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0);
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible());
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000));

Copilot uses AI. Check for mistakes.
Comment on lines 55 to 64
const request = buildRequest(imps, bidderRequest, context)
const siteId = bidderRequest.bids[0].params.siteId
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId)
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0)
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible())
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000))
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

Missing semicolon at the end of the statement. The code style should be consistent with the surrounding code which uses semicolons to terminate statements.

Suggested change
const request = buildRequest(imps, bidderRequest, context)
const siteId = bidderRequest.bids[0].params.siteId
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId)
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0)
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible())
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000))
const request = buildRequest(imps, bidderRequest, context);
const siteId = bidderRequest.bids[0].params.siteId;
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId);
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0);
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible());
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000));

Copilot uses AI. Check for mistakes.
Comment on lines 55 to 64
const request = buildRequest(imps, bidderRequest, context)
const siteId = bidderRequest.bids[0].params.siteId
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId)
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0)
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible())
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000))
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

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

Missing semicolon at the end of the statement. The code style should be consistent with the surrounding code which uses semicolons to terminate statements.

Suggested change
const request = buildRequest(imps, bidderRequest, context)
const siteId = bidderRequest.bids[0].params.siteId
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId)
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0)
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible())
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000))
const request = buildRequest(imps, bidderRequest, context);
const siteId = bidderRequest.bids[0].params.siteId;
siteIds.add(siteId);
deepSetValue(request, 'site.publisher.id', siteId);
deepSetValue(request, 'test', config.getConfig('debug') ? 1 : 0);
deepSetValue(request, 'ext.prebid.version', getGlobal()?.version ?? 'unknown');
deepSetValue(request, `ext.prebid.cntRequest`, cntRequest);
deepSetValue(request, `ext.prebid.cntImp`, cntImp);
deepSetValue(request, `ext.prebid.pVisible`, isPageVisible());
deepSetValue(request, `ext.prebid.uStart`, Math.trunc((performance.now() - uStart) / 1000));

Copilot uses AI. Check for mistakes.
Copy link

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

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: 2f879844b3

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

request(buildRequest, imps, bidderRequest, context) {
cntRequest++;
const request = buildRequest(imps, bidderRequest, context)
const siteId = bidderRequest.bids[0].params.siteId

Choose a reason for hiding this comment

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

P2 Badge Preserve each bid's siteId when building batched requests

buildRequests receives all valid bids for the auction, but the request customizer always reads bidderRequest.bids[0].params.siteId and applies that single value to the whole ORTB request. When an auction contains multiple pubstack bids with different siteId values, every imp after the first is sent under the wrong publisher context (site.publisher.id and ?siteId=), which can misroute or reject those bids.

Useful? React with 👍 / 👎.


return Array.from(siteIds).map(siteId => ({
type: isIframeEnabled ? 'iframe' : 'image',
url: `${syncUrl}?consent=${payload}&siteId=${siteId}`,

Choose a reason for hiding this comment

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

P2 Badge Encode consent payload before appending to sync URL

The sync URL concatenates raw Base64 into consent= without URL-encoding it. Base64 output can contain +, and common query parsers decode + as a space, so the consent blob arrives corrupted and may fail to decode on the usersync endpoint, causing sync failures for affected consent strings.

Useful? React with 👍 / 👎.

gpolaert and others added 4 commits February 18, 2026 22:30
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@gpolaert
Copy link
Contributor Author

I ran the ESLint, but I still have semicolon and formatting issues. How can I configure it and add it as a hook before committing the files to avoid being spammed by Codex/Copilot?

@coveralls
Copy link
Collaborator

Pull Request Test Coverage Report for Build 22158457780

Details

  • 313 of 313 (100.0%) changed or added relevant lines in 4 files are covered.
  • 4 unchanged lines in 4 files lost coverage.
  • Overall coverage increased (+0.004%) to 96.268%

Files with Coverage Reduction New Missed Lines %
modules/excoBidAdapter.js 1 78.17%
modules/kinessoIdSystem.js 1 83.15%
test/spec/creative/crossDomainCreative_spec.js 1 93.75%
test/spec/modules/id5AnalyticsAdapter_spec.js 1 96.13%
Totals Coverage Status
Change from base Build 22149413522: 0.004%
Covered Lines: 212695
Relevant Lines: 220940

💛 - Coveralls

if (element) return element;
};

export const getViewportDistance = (adUnitCode?: string): number | undefined => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

we just added another library for this, let us know if you can use that or if it needs modifications

Copy link
Collaborator

@patmmccann patmmccann left a comment

Choose a reason for hiding this comment

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

@patmmccann
Copy link
Collaborator

I ran the ESLint, but I still have semicolon and formatting issues. How can I configure it and add it as a hook before committing the files to avoid being spammed by Codex/Copilot?

only copilot is complaining about your styling and I agree with it, while you do pass linting it looks strange to randomly omit semicolons on some lines

@patmmccann patmmccann self-assigned this Feb 20, 2026
@patmmccann patmmccann changed the title feat: add pubstackBidAdapter (#1) pubstackBidAdapter: initial release Feb 20, 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.

4 participants