Skip to content
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

Sovrn 1.0 compliance #1796

Merged
merged 24 commits into from
Nov 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1a04f1f
Update Sovrn adapter. Add test coverage. Enable deal IDs.
Jul 26, 2017
bf9478b
Merge remote-tracking branch 'upstream/master'
Aug 7, 2017
75337df
HS-271: Avoid using private variables such as _bidsRequested and _bid…
Aug 8, 2017
62d965a
Merge remote-tracking branch 'upstream/master'
Aug 8, 2017
60b2be6
lint
Aug 8, 2017
97b89cc
Add bidfloor param to test.
Aug 8, 2017
f69f45b
Merge remote-tracking branch 'upstream/master'
Oct 10, 2017
60f4d1e
Merge branch 'master' of https://github.com/prebid/Prebid.js
Oct 11, 2017
0338ce7
changed post content-type in bidder factory to 'application/json', as…
Oct 11, 2017
a02635b
Revert "changed post content-type in bidder factory to 'application/j…
Oct 11, 2017
5af81a8
Changed method for altering contentType so that it is configurable vi…
Oct 11, 2017
9bd1397
Altered PR to conform to change reviews. added unit tests.
Oct 12, 2017
07b4dc6
Added comment to pass Trion adapter test.
Oct 12, 2017
dbfae1e
Removed false-y check for request.options. Added request.options conf…
Oct 13, 2017
1c4016f
small optimization to request.options to remove extra object declarat…
Oct 13, 2017
a497aa8
Re-wrote the Sovrn bid adapter to be compliant with Prebid 1.0.0.
tedrand11 Oct 20, 2017
a5689a1
Pushed bugfix found during whatismyip beta test, and small refactor.
tedrand11 Nov 1, 2017
d261720
Added README for adapter with test ad units.
tedrand11 Nov 6, 2017
17ada25
Merge branch 'master' of https://github.com/prebid/Prebid.js into sov…
tedrand11 Nov 9, 2017
72a6cf2
Adjusted Sovrn bid adapter to correspond to new JSON structure passed…
tedrand11 Nov 9, 2017
9680417
removed unneeded biddercode param in adapter and fixed JSON spacing o…
tedrand11 Nov 9, 2017
5638b98
Final updates to remove bidder code from expected response in unit te…
tedrand11 Nov 9, 2017
bb55cea
Reversed changes made to package.json and package-lock.json so that t…
tedrand11 Nov 13, 2017
fb34ecb
Removed package-lock.json file.
tedrand11 Nov 14, 2017
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
216 changes: 71 additions & 145 deletions modules/sovrnBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,156 +1,82 @@
var CONSTANTS = require('src/constants.json');
var utils = require('src/utils.js');
var bidfactory = require('src/bidfactory.js');
var bidmanager = require('src/bidmanager.js');
var adloader = require('src/adloader');
var adaptermanager = require('src/adaptermanager');

/**
* Adapter for requesting bids from Sovrn
*/
var SovrnAdapter = function SovrnAdapter() {
var sovrnUrl = 'ap.lijit.com/rtb/bid';

function _callBids(params) {
var sovrnBids = params.bids || [];

_requestBids(sovrnBids);
}

function _requestBids(bidReqs) {
// build bid request object
var domain = window.location.host;
var page = window.location.pathname + location.search + location.hash;

var sovrnImps = [];

// build impression array for sovrn
import * as utils from 'src/utils';
import { registerBidder } from 'src/adapters/bidderFactory';
import { BANNER } from 'src/mediaTypes';
import { REPO_AND_VERSION } from 'src/constants';

export const spec = {
code: 'sovrn',
supportedMediaTypes: [BANNER],

/**
* Check if the bid is a valid zone ID in either number or string form
* @param {object} bid the Sovrn bid to validate
* @return boolean for whether or not a bid is valid
*/
isBidRequestValid: function(bid) {
return !!(bid.params.tagid && !isNaN(parseFloat(bid.params.tagid)) && isFinite(bid.params.tagid));
},

/**
* Format the bid request object for our endpoint
* @param {BidRequest[]} bidRequests Array of Sovrn bidders
* @return object of parameters for Prebid AJAX request
*/
buildRequests: function(bidReqs) {
let sovrnImps = [];
utils._each(bidReqs, function (bid) {
var tagId = utils.getBidIdParameter('tagid', bid.params);
var bidFloor = utils.getBidIdParameter('bidfloor', bid.params);
var adW = 0;
var adH = 0;

// sovrn supports only one size per tagid, so we just take the first size if there are more
// if we are a 2 item array of 2 numbers, we must be a SingleSize array
var bidSizes = Array.isArray(bid.params.sizes) ? bid.params.sizes : bid.sizes;
var sizeArrayLength = bidSizes.length;
if (sizeArrayLength === 2 && typeof bidSizes[0] === 'number' && typeof bidSizes[1] === 'number') {
adW = bidSizes[0];
adH = bidSizes[1];
} else {
adW = bidSizes[0][0];
adH = bidSizes[0][1];
}

var imp =
{
id: bid.bidId,
banner: {
w: adW,
h: adH
},
tagid: tagId,
bidfloor: bidFloor
};
sovrnImps.push(imp);
sovrnImps.push({
id: bid.bidId,
banner: { w: 1, h: 1 },
Copy link

Choose a reason for hiding this comment

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

@tedrand Is this hardcoded as 1x1 because Sovrn knows the size based on the ID? It seems like the bid.sizes and bid.params.sizes properties will be totally ignored by the adapter. Is that correct?

@mkendall07 If that’s the case, then https://github.com/prebid/Prebid.js/blob/master/modules/sovrnBidAdapter.md should be updated to omit the sizes fields, right?

tagid: utils.getBidIdParameter('tagid', bid.params),
bidfloor: utils.getBidIdParameter('bidfloor', bid.params)
});
});

// build bid request with impressions
var sovrnBidReq = {
const sovrnBidReq = {
id: utils.getUniqueIdentifierStr(),
imp: sovrnImps,
site: {
domain: domain,
page: page
domain: window.location.host,
page: window.location.pathname + location.search + location.hash
}
};

var scriptUrl = '//' + sovrnUrl + '?callback=window.$$PREBID_GLOBAL$$.sovrnResponse' +
'&src=' + CONSTANTS.REPO_AND_VERSION +
'&br=' + encodeURIComponent(JSON.stringify(sovrnBidReq));
adloader.loadScript(scriptUrl);
}

function addBlankBidResponses(impidsWithBidBack) {
var missing = utils.getBidderRequestAllAdUnits('sovrn');
if (missing) {
missing = missing.bids.filter(bid => impidsWithBidBack.indexOf(bid.bidId) < 0);
} else {
missing = [];
}

missing.forEach(function (bidRequest) {
// Add a no-bid response for this bid request.
var bid = {};
bid = bidfactory.createBid(2, bidRequest);
bid.bidderCode = 'sovrn';
bidmanager.addBidResponse(bidRequest.placementCode, bid);
});
}

// expose the callback to the global object:
$$PREBID_GLOBAL$$.sovrnResponse = function (sovrnResponseObj) {
var impidsWithBidBack = [];

// valid response object from sovrn
if (sovrnResponseObj && sovrnResponseObj.id && sovrnResponseObj.seatbid && sovrnResponseObj.seatbid.length !== 0 &&
sovrnResponseObj.seatbid[0].bid && sovrnResponseObj.seatbid[0].bid.length !== 0) {
sovrnResponseObj.seatbid[0].bid.forEach(function (sovrnBid) {
var responseCPM;
var placementCode = '';
var id = sovrnBid.impid;
var bid = {};

var bidObj = utils.getBidRequest(id);

if (bidObj) {
placementCode = bidObj.placementCode;
bidObj.status = CONSTANTS.STATUS.GOOD;

responseCPM = parseFloat(sovrnBid.price);

if (responseCPM !== 0) {
sovrnBid.placementCode = placementCode;
sovrnBid.size = bidObj.sizes;
var responseAd = sovrnBid.adm;

// build impression url from response
var responseNurl = '<img src="' + sovrnBid.nurl + '">';

// store bid response
// bid status is good (indicating 1)
bid = bidfactory.createBid(1, bidObj);
bid.creative_id = sovrnBid.id;
bid.bidderCode = 'sovrn';
bid.cpm = responseCPM;

// set ad content + impression url
// sovrn returns <script> block, so use bid.ad, not bid.adurl
bid.ad = decodeURIComponent(responseAd + responseNurl);

// Set width and height from response now
bid.width = parseInt(sovrnBid.w);
bid.height = parseInt(sovrnBid.h);

if (sovrnBid.dealid) {
bid.dealId = sovrnBid.dealid;
}

bidmanager.addBidResponse(placementCode, bid);
impidsWithBidBack.push(id);
}
}
return {
method: 'POST',
url: `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`,
data: JSON.stringify(sovrnBidReq),
options: {contentType: 'text/plain'}
};
},

/**
* Format Sovrn responses as Prebid bid responses
* @param {id, seatbid} sovrnResponse A successful response from Sovrn.
* @return {Bid[]} An array of formatted bids.
*/
interpretResponse: function({ body: {id, seatbid} }) {
let sovrnBidResponses = [];
if (id &&
seatbid &&
seatbid.length > 0 &&
seatbid[0].bid &&
seatbid[0].bid.length > 0) {
seatbid[0].bid.map(sovrnBid => {
sovrnBidResponses.push({
requestId: sovrnBid.impid,
cpm: parseFloat(sovrnBid.price),
width: parseInt(sovrnBid.w),
height: parseInt(sovrnBid.h),
creativeId: sovrnBid.id,
dealId: sovrnBid.dealId || null,
currency: 'USD',
netRevenue: true,
mediaType: BANNER,
ad: decodeURIComponent(`${sovrnBid.adm}<img src="${sovrnBid.nurl}">`),
ttl: 60000
});
});
}
addBlankBidResponses(impidsWithBidBack);
};

return {
callBids: _callBids
};
return sovrnBidResponses;
}
};

adaptermanager.registerBidAdapter(new SovrnAdapter(), 'sovrn');

module.exports = SovrnAdapter;
registerBidder(spec);
47 changes: 47 additions & 0 deletions modules/sovrnBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Overview

```
Module Name: Sovrn Bid Adapter
Module Type: Bidder Adapter
Maintainer: trand@sovrn.com
```

# Description

Sovrn's adapter integration to the Prebid library. Posts plain-text JSON to the /rtb/bid endpoint.

# Test Parameters

Copy link
Collaborator

Choose a reason for hiding this comment

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

This line and line 46 should mark the code with ```

```
var adUnits = [
{
code: 'test-leaderboard',
sizes: [[728, 90]],
bids: [{
bidder: 'sovrn',
params: {
tagid: '403370',
bidfloor: 0.01
}
}]
}, {
code: 'test-banner',
sizes: [[300, 250]],
bids: [{
bidder: 'sovrn',
params: {
tagid: '403401'
}
}]
}, {
code: 'test-sidebar',
size: [[160, 600]],
bids: [{
bidder: 'sovrn',
params: {
tagid: '531000'
}
}]
}
]
```
Loading