AdSmartx Bid Adapter : New Bidder Adapter#14559
AdSmartx Bid Adapter : New Bidder Adapter#14559pritishmd-talentica wants to merge 12 commits intoprebid:masterfrom
Conversation
Update Master Branch From Upstream Master
…s-adapter-smart-exchange Rm 1476 prebid js adapter smart exchange
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c4fe9eae4c
ℹ️ 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".
| const responses = []; | ||
| bidResp.seatbid.forEach(seatbid => { | ||
| if (!Array.isArray(seatbid.bid) || seatbid.bid.length === 0) return; | ||
| const bid = seatbid.bid[0]; |
There was a problem hiding this comment.
Iterate all bids in each seatbid entry
interpretResponse only reads seatbid.bid[0], so additional bids in the same seatbid are dropped. If the exchange returns multiple bids for multiple impressions in one seatbid (a valid ORTB response shape), this adapter will silently lose eligible bids and reduce auction competitiveness/revenue.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
The ad server will return only one bid that has won the auction conducted in our ad server but since the ad server is OpenRTB compliant, the bid variable is an array.
There was a problem hiding this comment.
Pull request overview
Adds a new AdSmartX bidder adapter and introduces shared ORTB conversion/response/sync utilities, also refactoring the existing RiseMediaTech adapter to use those utilities.
Changes:
- Added
adsmartxbidder adapter (module + in-repo markdown doc). - Added shared helper library
libraries/adsmartxUtils/bidderUtils.js(converter, request builder, response interpreter, user sync builder). - Updated/added unit tests for
adsmartxand adjusted one RiseMediaTech response expectation.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
modules/adsmartxBidAdapter.js |
New AdSmartX bidder adapter wired to shared bidderUtils helpers. |
modules/adsmartxBidAdapter.md |
New adapter documentation (currently missing bid params table). |
libraries/adsmartxUtils/bidderUtils.js |
New shared ORTB converter/request/response/sync helpers used by adapters. |
modules/risemediatechBidAdapter.js |
Refactored to use adsmartxUtils helpers; behavior changes in consent mapping and user sync return. |
test/spec/modules/adsmartxBidAdapter_spec.js |
New AdSmartX adapter tests (currently contains JS syntax errors). |
test/spec/libraries/adsmartxUtils/bidderUtils_spec.js |
New unit tests for shared bidderUtils helpers. |
test/spec/modules/risemediatechBidAdapter_spec.js |
Adjusted expectation for unknown mtype to default to banner. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| request.user = request.user || {}; | ||
| } | ||
| if (bidderRequest.gdprConsent) { | ||
| logInfo('Adding GDPR consent information to request:', bidderRequest.gdprConsent); | ||
| request.regs.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; | ||
| request.user.consent = bidderRequest.gdprConsent.consentString; |
There was a problem hiding this comment.
createConverter currently maps GDPR consent to request.regs.gdpr and request.user.consent. This is a behavioral change vs the previous risemediatech adapter implementation and will fail existing tests that expect regs.ext.gdpr and user.ext.consent (e.g. test/spec/modules/risemediatechBidAdapter_spec.js). Please keep the same ORTB field locations as before (or update the adapter + tests together and confirm the endpoint expects the new fields).
| request.user = request.user || {}; | |
| } | |
| if (bidderRequest.gdprConsent) { | |
| logInfo('Adding GDPR consent information to request:', bidderRequest.gdprConsent); | |
| request.regs.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; | |
| request.user.consent = bidderRequest.gdprConsent.consentString; | |
| request.regs.ext = request.regs.ext || {}; | |
| request.user = request.user || {}; | |
| request.user.ext = request.user.ext || {}; | |
| } | |
| if (bidderRequest.gdprConsent) { | |
| logInfo('Adding GDPR consent information to request:', bidderRequest.gdprConsent); | |
| request.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies ? 1 : 0; | |
| request.user.ext.consent = bidderRequest.gdprConsent.consentString; |
| const bidResponse = { | ||
| requestId: bid.impid, | ||
| cpm: bid.price, | ||
| currency: bidResp.cur || defaultCurrency, | ||
| width: bid.w, | ||
| height: bid.h, | ||
| ad: bid.adm, | ||
| creativeId: bid.crid, | ||
| netRevenue: true, | ||
| ttl: defaultTtl, | ||
| meta: { advertiserDomains: bid.adomain || [] }, | ||
| }; |
There was a problem hiding this comment.
interpretResponse unconditionally uses bid.price for cpm and pushes the bid even if price is missing/undefined. That produces bid objects with cpm: undefined which will be filtered out later (or cause downstream issues). Consider skipping bids that are missing required OpenRTB fields like impid and price (and optionally adm).
| Connects to AdSmartX Exchange for bids | ||
| AdSmartX supports Display & Video(Instream) currently. | ||
|
|
||
| This adapter is maintained by Smart Exchange, the legal entity behind this implementation. Our official domain is [AI Digital](https://www.aidigital.com/). |
There was a problem hiding this comment.
This module doc is missing a "Bid Parameters" section/table (required/optional params, types, descriptions) which is the established format for bidder adapter docs in this repo (see many other modules/*BidAdapter.md files). Please add a parameter table for bidfloor, testMode, sspId, siteId, sspUserId, etc. so integrators know what to pass.
| This adapter is maintained by Smart Exchange, the legal entity behind this implementation. Our official domain is [AI Digital](https://www.aidigital.com/). | |
| This adapter is maintained by Smart Exchange, the legal entity behind this implementation. Our official domain is [AI Digital](https://www.aidigital.com/). | |
| # Bid Parameters | |
| | Name | Scope | Type | Required | Description | | |
| |------------|--------------|---------|----------|-----------------------------------------------------------------------------| | |
| | `sspId` | Banner,Video | number | Yes | Publisher/SSP identifier assigned by AdSmartX. | | |
| | `siteId` | Banner,Video | number | Yes | Site or app identifier assigned by AdSmartX. | | |
| | `bidfloor` | Banner,Video | number | No | Minimum bid price in USD for the impression. | | |
| | `testMode` | Banner,Video | number | No | Test mode flag (e.g. `1` to enable test requests; omit or `0` for live). | | |
| | `sspUserId`| Banner,Video | string | No | External user identifier to help AdSmartX recognize the user (if desired). | |
| // TODO: set gvlid once confirmed with AI Digital / AdSmartX team | ||
| gvlid: undefined, |
There was a problem hiding this comment.
Setting gvlid: undefined is unusual and makes it look like the adapter intentionally declares a GVL ID value. Since gvlid is optional, it’s clearer to omit the property entirely until you have the correct numeric ID (or set a real value once assigned).
| // TODO: set gvlid once confirmed with AI Digital / AdSmartX team | |
| gvlid: undefined, | |
| // TODO: add numeric gvlid once confirmed with AI Digital / AdSmartX team |
| logInfo('Using SSP user ID from bid params:', bidParams.sspUserId); | ||
| return bidParams.sspUserId; | ||
| } | ||
| const ortb2UserId = deepAccess(bidderRequest, 'ortb2.user.id'); | ||
| if (ortb2UserId) { | ||
| logInfo('Using SSP user ID from ORTB2 user.id:', ortb2UserId); |
There was a problem hiding this comment.
Be careful about logging user identifiers: getPublisherUserId logs the raw sspUserId / ortb2.user.id. Even though logInfo is gated by debug, it can still expose user IDs in console logs. Consider removing these logs or redacting/truncating the ID value.
| logInfo('Using SSP user ID from bid params:', bidParams.sspUserId); | |
| return bidParams.sspUserId; | |
| } | |
| const ortb2UserId = deepAccess(bidderRequest, 'ortb2.user.id'); | |
| if (ortb2UserId) { | |
| logInfo('Using SSP user ID from ORTB2 user.id:', ortb2UserId); | |
| logInfo('Using SSP user ID from bid params'); | |
| return bidParams.sspUserId; | |
| } | |
| const ortb2UserId = deepAccess(bidderRequest, 'ortb2.user.id'); | |
| if (ortb2UserId) { | |
| logInfo('Using SSP user ID from ORTB2 user.id'); |
| video: { | ||
| w: 640, | ||
| h: 480 | ||
| // mimes missing | ||
| } | ||
| } | ||
| }; | ||
| expect(spec.isBidRequestValid(invalidVideoRequest)).to.equal(false); |
There was a problem hiding this comment.
This test file contains invalid object literal syntax (missing commas / braces), which will prevent the test suite from even parsing. For example, h: 480 is missing a trailing comma and the surrounding braces/commas are inconsistent in this block; please fix the syntax throughout the file and run the linter/tests to catch similar issues.
| import { logInfo } from '../src/utils.js'; | ||
| import { | ||
| createConverter, | ||
| isBidRequestValid as validateBidRequest, | ||
| createBuildRequests, | ||
| interpretResponse as interpretResponseUtil, | ||
| } from '../libraries/adsmartxUtils/bidderUtils.js'; |
There was a problem hiding this comment.
The PR description is for adding a new AdSmartX adapter, but this change also refactors the existing risemediatech adapter to depend on the new libraries/adsmartxUtils/* helpers. Please call this out in the PR description (or split into a separate refactor PR), since it changes behavior for an existing bidder adapter and increases review risk.
| type: syncOptions.iframeEnabled ? 'iframe' : 'image', | ||
| url: syncUrl + queryString, | ||
| }]; | ||
| logInfo('Returning user syncs:', syncs); |
There was a problem hiding this comment.
createGetUserSyncs logs the full sync URL (including gdpr_consent / gpp strings) via logInfo('Returning user syncs:', syncs). That can leak consent strings into logs when debug is enabled. Consider removing this log line or logging only the sync type without query parameters.
| logInfo('Returning user syncs:', syncs); | |
| // Log only non-sensitive metadata to avoid leaking consent strings in URLs | |
| logInfo('Returning user syncs:', syncs.map(sync => ({ type: sync.type }))); |
| h: 250, | ||
| crid: 'creative123', | ||
| adomain: ['example.com'] | ||
| // mtype missing | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| }; |
There was a problem hiding this comment.
Another syntax error here: adomain: ['example.com'] is missing a trailing comma before the comment, which will break parsing. There are multiple similar missing commas in response fixtures in this spec; please ensure all object/array literals are valid JS.
Type of change
Bugfix
Feature
[ x] New bidder adapter
[ x] Updated bidder adapter RiseMediaTech 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
Added a bidder adapter for AdSmartX
Maintainer : prebid@aidigital.com
Sample Ad Unit : Banner
Sample Ad Unit : Video
Other information
Documentation PR:
prebid/prebid.github.io#6467