Skip to content

Commit

Permalink
Supply2 Bid Adapter (prebid#3335)
Browse files Browse the repository at this point in the history
* Added Supply2 Bid Adapter with spec file

* Supply2BidAdapter: fix typo
  • Loading branch information
Vishalrkanse authored and Pedro López Jiménez committed Mar 18, 2019
1 parent 4bf1d02 commit 31c789f
Show file tree
Hide file tree
Showing 3 changed files with 538 additions and 0 deletions.
166 changes: 166 additions & 0 deletions modules/supply2BidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import * as utils from 'src/utils';
import {registerBidder} from 'src/adapters/bidderFactory';
const BIDDER_CODE = 'supply2';
const ENDPOINT_URL = '//pool.supply2.com/hb';
const TIME_TO_LIVE = 360;
const ADAPTER_SYNC_URL = '//pool.supply2.com/push_sync';
const LOG_ERROR_MESS = {
noAuid: 'Bid from response has no auid parameter - ',
noAdm: 'Bid from response has no adm parameter - ',
noBid: 'Array of bid objects is empty',
noPlacementCode: 'Can\'t find in requested bids the bid with auid - ',
emptyUids: 'Uids should be not empty',
emptySeatbid: 'Seatbid array from response has empty item',
emptyResponse: 'Response is empty',
hasEmptySeatbidArray: 'Response has empty seatbid array',
hasNoArrayOfBids: 'Seatbid from response has no array of bid objects - '
};
export const spec = {
code: BIDDER_CODE,
/**
* Determines whether or not the given bid request is valid.
*
* @param {BidRequest} bid The bid params to validate.
* @return boolean True if this is a valid bid, and false otherwise.
*/
isBidRequestValid: function(bid) {
return !!bid.params.uid;
},
/**
* Make a server request from the list of BidRequests.
*
* @param {BidRequest[]} validBidRequests - an array of bids
* @param {bidderRequest} bidderRequest - bidder request object
* @return ServerRequest Info describing the request to the server.
*/
buildRequests: function(validBidRequests, bidderRequest) {
const auids = [];
const bidsMap = {};
const bids = validBidRequests || [];
let priceType = 'net';
let reqId;

bids.forEach(bid => {
if (bid.params.priceType === 'gross') {
priceType = 'gross';
}
reqId = bid.bidderRequestId;
if (!bidsMap[bid.params.uid]) {
bidsMap[bid.params.uid] = [bid];
auids.push(bid.params.uid);
} else {
bidsMap[bid.params.uid].push(bid);
}
});

const payload = {
u: utils.getTopWindowUrl(),
pt: priceType,
auids: auids.join(','),
r: reqId
};

if (bidderRequest) {
if (bidderRequest.timeout) {
payload.wtimeout = bidderRequest.timeout;
}
if (bidderRequest.gdprConsent) {
if (bidderRequest.gdprConsent.consentString) {
payload.gdpr_consent = bidderRequest.gdprConsent.consentString;
}
payload.gdpr_applies =
(typeof bidderRequest.gdprConsent.gdprApplies === 'boolean')
? Number(bidderRequest.gdprConsent.gdprApplies) : 1;
}
}

return {
method: 'GET',
url: ENDPOINT_URL,
data: utils.parseQueryStringParameters(payload).replace(/\&$/, ''),
bidsMap: bidsMap,
};
},
/**
* Unpack the response from the server into a list of bids.
*
* @param {*} serverResponse A successful response from the server.
* @param {*} bidRequest
* @return {Bid[]} An array of bids which were nested inside the server.
*/
interpretResponse: function(serverResponse, bidRequest) {
serverResponse = serverResponse && serverResponse.body;
const bidResponses = [];
const bidsMap = bidRequest.bidsMap;
const priceType = bidRequest.data.pt;

let errorMessage;

if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse;
else if (serverResponse.seatbid && !serverResponse.seatbid.length) {
errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray;
}

if (!errorMessage && serverResponse.seatbid) {
serverResponse.seatbid.forEach(respItem => {
_addBidResponse(_getBidFromResponse(respItem), bidsMap, priceType, bidResponses);
});
}
if (errorMessage) utils.logError(errorMessage);
return bidResponses;
},
getUserSyncs: function(syncOptions) {
if (syncOptions.pixelEnabled) {
return [{
type: 'image',
url: ADAPTER_SYNC_URL
}];
}
}
}

function _getBidFromResponse(respItem) {
if (!respItem) {
utils.logError(LOG_ERROR_MESS.emptySeatbid);
} else if (!respItem.bid) {
utils.logError(LOG_ERROR_MESS.hasNoArrayOfBids + JSON.stringify(respItem));
} else if (!respItem.bid[0]) {
utils.logError(LOG_ERROR_MESS.noBid);
}
return respItem && respItem.bid && respItem.bid[0];
}

function _addBidResponse(serverBid, bidsMap, priceType, bidResponses) {
if (!serverBid) return;
let errorMessage;
if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid);
if (!serverBid.adm) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid);
else {
const awaitingBids = bidsMap[serverBid.auid];
if (awaitingBids) {
awaitingBids.forEach(bid => {
const bidResponse = {
requestId: bid.bidId, // bid.bidderRequestId,
bidderCode: spec.code,
cpm: serverBid.price,
width: serverBid.w,
height: serverBid.h,
creativeId: serverBid.auid, // bid.bidId,
currency: 'USD',
netRevenue: priceType !== 'gross',
ttl: TIME_TO_LIVE,
ad: serverBid.adm,
dealId: serverBid.dealid
};
bidResponses.push(bidResponse);
});
} else {
errorMessage = LOG_ERROR_MESS.noPlacementCode + serverBid.auid;
}
}
if (errorMessage) {
utils.logError(errorMessage);
}
}

registerBidder(spec);
40 changes: 40 additions & 0 deletions modules/supply2BidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Overview

Module Name: Supply2 Bidder Adapter
Module Type: Bidder Adapter
Maintainer: vishal@mediadonuts.com

# Description

Module that connects to Media Donuts demand source to fetch bids.

# Test Parameters
```
var adUnits = [
{
code: 'test-div',
sizes: [[300, 250]],
bids: [
{
bidder: "supply2",
params: {
uid: '23',
priceType: 'gross' // by default is 'net'
}
}
]
},{
code: 'test-div',
sizes: [[728, 90]],
bids: [
{
bidder: "supply2",
params: {
uid: 24,
priceType: 'gross'
}
}
]
}
];
```
Loading

0 comments on commit 31c789f

Please sign in to comment.