-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Synapse HX Bid Adapter : initial release #15331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
e8a3686
c4cb58f
c74bf96
5fddad7
02915df
7f52687
03601a4
1ea3ace
935f135
4c2a029
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| # Overview | ||
|
|
||
| ``` | ||
| Module Name: Synapse HX Bidder Adapter | ||
| Module Type: Bidder Adapter | ||
| Maintainer: prebid@compas-inc.com | ||
| ``` | ||
|
|
||
| # Description | ||
|
|
||
| The Synapse HX Bidder Adapter enables publishers to integrate with Synapse HX exchange for banner and video ad formats. The adapter supports OpenRTB standards and processes bid requests efficiently using the Prebid.js framework. | ||
|
|
||
| # Test Parameters | ||
|
|
||
| ## Sample Banner Ad Unit | ||
| ``` | ||
| var adUnits = [ | ||
| { | ||
| code: 'test-div', | ||
| mediaTypes: { | ||
| banner: { | ||
| sizes: [[300,250]] | ||
| } | ||
| }, | ||
| bids: [ | ||
| { | ||
| bidder: 'synapsehx', | ||
| params: { | ||
| // REQUIRED - Synapse HX tenant identifier | ||
| tenantId: 'your-account-id', | ||
| // OPTIONAL - Synapse HX ad unit identifier | ||
| adUnitId: 'ad-unit-id' | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ]; | ||
| ``` | ||
|
|
||
| ## Sample Video Ad Unit | ||
| ``` | ||
| var videoAdUnits = [ | ||
| { | ||
| code: 'test-div-video', | ||
| mediaTypes: { | ||
| video: { | ||
| context: 'instream', | ||
| placement: 1, | ||
| playerSize: [640, 360], | ||
| mimes: ['video/mp4'], | ||
| protocols: [2, 3, 5, 6], | ||
| api: [2], | ||
| maxduration: 30, | ||
| linearity: 1, | ||
| playbackmethod: [2] | ||
| } | ||
| }, | ||
| bids: [ | ||
| { | ||
| bidder: 'synapsehx', | ||
| params: { | ||
| // REQUIRED - Synapse HX tenant identifier | ||
| tenantId: 'your-account-id', | ||
| // OPTIONAL - Synapse HX ad unit identifier | ||
| adUnitId: 'ad-unit-id' | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| ]; | ||
| ``` | ||
|
|
||
| # Additional Notes | ||
| - The adapter processes requests via OpenRTB 2.6 standards. | ||
| - Ensure that the `tenantId` parameter is set correctly for your integration. | ||
| - The `adUnitId` parameter is optional. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| import { BidderSpec, registerBidder } from '../src/adapters/bidderFactory.js'; | ||
| import { BANNER, VIDEO } from '../src/mediaTypes.js'; | ||
| import { logError, formatQS, triggerPixel } from '../src/utils.js'; | ||
| import { getBidFloor } from '../libraries/adrelevantisUtils/bidderUtils.js'; | ||
| import { ortbConverter } from '../libraries/ortbConverter/converter.js'; | ||
| import { toOrtb26 } from '../libraries/ortb2.5Translator/translator.js'; | ||
| import { getUserSyncParams } from '../libraries/userSyncUtils/userSyncUtils.js'; | ||
|
|
||
| const BIDDER_CODE = 'synapsehx'; | ||
| const METHOD = 'POST'; | ||
| const ENDPOINT_URL = `https://rtb.hx.compasonline.com/pbjs`; | ||
|
|
||
| type SynapsehxBidderParams = { | ||
| /** | ||
| * Synapse HX tenant identifier | ||
| */ | ||
| tenantId: string; | ||
| /** | ||
| * Synapse HX ad unit identifier | ||
| */ | ||
| adUnitId?: string; | ||
| }; | ||
|
|
||
| declare module '../src/adUnits' { | ||
| interface BidderParams { | ||
| [BIDDER_CODE]: SynapsehxBidderParams; | ||
| } | ||
| } | ||
|
|
||
| function getMediaType(bid) { | ||
| const mtypeToMediaType = { 1: BANNER, 2: VIDEO }; | ||
| return mtypeToMediaType[bid.mtype]; | ||
| } | ||
|
|
||
| const converter = ortbConverter<typeof BIDDER_CODE>({ | ||
| imp(buildImp, bidRequest, context) { | ||
| const imp = buildImp(bidRequest, context); | ||
|
|
||
| if (bidRequest?.params?.adUnitId) { | ||
| imp.tagid = bidRequest.params.adUnitId; | ||
| } | ||
|
|
||
| const floor = getBidFloor(bidRequest, 'USD'); | ||
| if (floor) { | ||
| imp.bidfloor = floor; | ||
| imp.bidfloorcur = 'USD'; | ||
| } | ||
|
|
||
| return imp; | ||
| }, | ||
| request(buildRequest, imps, bidderRequest, context) { | ||
| return buildRequest(imps, bidderRequest, context); | ||
| }, | ||
| bidResponse(buildBidResponse, bid, context) { | ||
| const isValidBidType = Object.keys(context.bidRequest.mediaTypes).includes(getMediaType(bid)); | ||
|
|
||
| if (isValidBidType) { | ||
| return buildBidResponse(bid, context); | ||
| } | ||
|
|
||
| logError('Incorrect bid type for bid: ', bid.id); | ||
| }, | ||
| context: { | ||
| netRevenue: true, | ||
| ttl: 30 | ||
| } | ||
| }); | ||
|
|
||
| function isValidBidFloorCurrency(bid) { | ||
| const currency = bid.ortb2Imp?.bidfloorcur; | ||
| return currency == null || currency === 'USD'; | ||
| } | ||
|
|
||
| function isValidParams(bid) { | ||
| const tenantId = bid?.params?.tenantId; | ||
| const adUnitId = bid?.params?.adUnitId; | ||
| return typeof tenantId === 'string' && tenantId.length > 0 && | ||
| (adUnitId == null || (typeof adUnitId === 'string' && adUnitId.length > 0)); | ||
| } | ||
|
|
||
| function makeUrl(bidRequests) { | ||
| return `${ENDPOINT_URL}?${formatQS({ pid: bidRequests[0].params.tenantId })}`; | ||
|
Comment on lines
+81
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a page has multiple Synapse HX bids with different Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| export const spec: BidderSpec<typeof BIDDER_CODE> = { | ||
| code: BIDDER_CODE, | ||
| supportedMediaTypes: [VIDEO, BANNER], | ||
| isBidRequestValid: (bid) => !!bid && isValidParams(bid) && isValidBidFloorCurrency(bid), | ||
|
|
||
| buildRequests: (bidRequests, bidderRequest) => { | ||
| const data = toOrtb26(converter.toORTB({ bidRequests, bidderRequest })); | ||
|
|
||
| return [{ | ||
| method: METHOD, | ||
| url: makeUrl(bidRequests), | ||
| options: { | ||
| contentType: 'text/plain', | ||
| withCredentials: true, | ||
| crossOrigin: true | ||
| }, | ||
| data: data, | ||
| }]; | ||
| }, | ||
|
|
||
| interpretResponse: ({ body }, req) => { | ||
| if (!body || !body.seatbid || body.seatbid.length === 0) { | ||
| return []; | ||
| } | ||
| body.cur ??= "USD"; | ||
| return converter.fromORTB({ | ||
| response: body, | ||
| request: req.data | ||
| }); | ||
| }, | ||
|
|
||
| onTimeout: (data) => { }, | ||
|
|
||
| onBidWon: (bid: { nurl?: string, cpm: number }) => { | ||
| if (bid.nurl) { | ||
| const url = new URL(bid.nurl); | ||
| url.searchParams.set('cpm', String(bid.cpm)); | ||
| triggerPixel(url.toString()); | ||
|
Comment on lines
+119
to
+122
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When Synapse returns a normal ORTB Useful? React with 👍 / 👎. |
||
| } | ||
| }, | ||
|
|
||
| onSetTargeting: (bid) => { }, | ||
|
|
||
| getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) { | ||
| const syncs = []; | ||
|
|
||
| if (serverResponses && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) { | ||
| const params = formatQS(getUserSyncParams(gdprConsent, uspConsent, gppConsent)); | ||
|
|
||
| if (syncOptions.iframeEnabled) { | ||
| serverResponses.forEach(response => { | ||
| const iframeUrl = response?.body?.ext?.[BIDDER_CODE]?.sync?.iframe; | ||
| if (iframeUrl) { | ||
| syncs.push({ | ||
| type: "iframe", | ||
| url: `${iframeUrl}${params ? `${iframeUrl.lastIndexOf('?') !== -1 ? '&' : '?'}${params}` : ''}`, | ||
| }); | ||
| } | ||
| }); | ||
| } else if (syncOptions.pixelEnabled) { | ||
| serverResponses.forEach(response => { | ||
| const images = response?.body?.ext?.[BIDDER_CODE]?.sync?.image || []; | ||
| images.forEach(image => { | ||
| syncs.push({ | ||
| type: "image", | ||
| url: `${image}${params ? `${image.lastIndexOf('?') !== -1 ? '&' : '?'}${params}` : ''}`, | ||
| }); | ||
| }); | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| return syncs; | ||
| } | ||
| }; | ||
|
|
||
| registerBidder(spec); | ||
Uh oh!
There was an error while loading. Please reload this page.