Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 144 additions & 0 deletions modules/synapsehxBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { 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`;

function getMediaType(bid) {
const mtypeToMediaType = { 1: BANNER, 2: VIDEO };
return mtypeToMediaType[bid.mtype];
}

const converter = ortbConverter({
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 })}`;
}

export const spec = {
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
}).bids;
},

onTimeout: (data) => { },

onBidWon: (bid) => {
if (bid.nurl) {
const url = new URL(bid.nurl);
url.searchParams.set('cpm', bid.cpm);
triggerPixel(url.toString());
}
},

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);
76 changes: 76 additions & 0 deletions modules/synapsehxBidAdapter.md
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: {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

please type these by converting your adapter to ts or adding a .d.ts file and importing the types from it

// 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.
Loading
Loading