-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
CPMStar Bid Adapter #3820
Merged
Merged
CPMStar Bid Adapter #3820
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
cd66b75
Added CPMStar Bid Adapter
JoshuaMGoldstein 1f60e6c
Updated getPlayerSize for cpmstarBidAdapter
JoshuaMGoldstein 8020923
Improved cpmstarBidAdapter code coverage
JoshuaMGoldstein 06911ae
updated test spec, removed empty functions, made imports relative, ad…
c43d765
added test video ad unit
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
|
||
import * as utils from '../src/utils'; | ||
import { registerBidder } from '../src/adapters/bidderFactory'; | ||
import {VIDEO, BANNER} from '../src/mediaTypes'; | ||
|
||
const BIDDER_CODE = 'cpmstar'; | ||
|
||
const ENDPOINT_DEV = '//dev.server.cpmstar.com/view.aspx'; | ||
const ENDPOINT_STAGING = '//staging.server.cpmstar.com/view.aspx'; | ||
const ENDPOINT_PRODUCTION = '//server.cpmstar.com/view.aspx'; | ||
|
||
const DEFAULT_TTL = 300; | ||
const DEFAULT_CURRENCY = 'USD'; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedMediaTypes: [BANNER, VIDEO], | ||
pageID: Math.floor(Math.random() * 10e6), | ||
|
||
getMediaType: function(bidRequest) { | ||
if (bidRequest == null) return BANNER; | ||
return !utils.deepAccess(bidRequest, 'mediaTypes.video') ? BANNER : VIDEO; | ||
}, | ||
|
||
getPlayerSize: function(bidRequest) { | ||
var playerSize = utils.deepAccess(bidRequest, 'mediaTypes.video.playerSize'); | ||
if (playerSize == null) return [640, 440]; | ||
if (playerSize[0] != null) playerSize = playerSize[0]; | ||
if (playerSize == null || playerSize[0] == null || playerSize[1] == null) return [640, 440]; | ||
return playerSize; | ||
}, | ||
|
||
isBidRequestValid: function (bid) { | ||
return ((typeof bid.params.placementId === 'string') && !!bid.params.placementId.length) || (typeof bid.params.placementId === 'number'); | ||
}, | ||
|
||
buildRequests: function (validBidRequests, bidderRequest) { | ||
var requests = []; | ||
// This reference to window.top can cause issues when loaded in an iframe if not protected with a try/catch. | ||
|
||
for (var i = 0; i < validBidRequests.length; i++) { | ||
var bidRequest = validBidRequests[i]; | ||
var referer = encodeURIComponent(bidderRequest.refererInfo.referer); | ||
var e = utils.getBidIdParameter('endpoint', bidRequest.params); | ||
var ENDPOINT = e == 'dev' ? ENDPOINT_DEV : e == 'staging' ? ENDPOINT_STAGING : ENDPOINT_PRODUCTION; | ||
var mediaType = spec.getMediaType(bidRequest); | ||
var playerSize = spec.getPlayerSize(bidRequest); | ||
var videoArgs = '&fv=0' + (playerSize ? ('&w=' + playerSize[0] + '&h=' + playerSize[1]) : ''); | ||
requests.push({ | ||
method: 'GET', | ||
url: ENDPOINT + '?media=' + mediaType + (mediaType == VIDEO ? videoArgs : '') + '&json=c_b&mv=1&poolid=' + utils.getBidIdParameter('placementId', bidRequest.params) + '&reachedTop=' + encodeURIComponent(bidderRequest.refererInfo.reachedTop) + '&requestid=' + bidRequest.bidId + '&referer=' + referer, | ||
bidRequest: bidRequest, | ||
}); | ||
} | ||
|
||
return requests; | ||
}, | ||
|
||
interpretResponse: function (serverResponse, request) { | ||
var bidRequest = request.bidRequest; | ||
var mediaType = spec.getMediaType(bidRequest); | ||
|
||
var bidResponses = []; | ||
|
||
if (!Array.isArray(serverResponse.body)) { | ||
serverResponse.body = [serverResponse.body]; | ||
} | ||
|
||
for (var i = 0; i < serverResponse.body.length; i++) { | ||
var raw = serverResponse.body[i]; | ||
var rawBid = raw.creatives[0]; | ||
if (!rawBid) { | ||
utils.logWarn('cpmstarBidAdapter: server response failed check'); | ||
return; | ||
} | ||
var cpm = (parseFloat(rawBid.cpm) || 0); | ||
|
||
if (!cpm) { | ||
utils.logWarn('cpmstarBidAdapter: server response failed check. Missing cpm') | ||
return; | ||
} | ||
|
||
var bidResponse = { | ||
requestId: rawBid.requestid, | ||
cpm: cpm, | ||
width: rawBid.width || 0, | ||
height: rawBid.height || 0, | ||
currency: rawBid.currency ? rawBid.currency : DEFAULT_CURRENCY, | ||
netRevenue: rawBid.netRevenue ? rawBid.netRevenue : true, | ||
ttl: rawBid.ttl ? rawBid.ttl : DEFAULT_TTL, | ||
creativeId: rawBid.creativeid || 0, | ||
}; | ||
|
||
if (rawBid.hasOwnProperty('dealId')) { | ||
bidResponse.dealId = rawBid.dealId | ||
} | ||
|
||
if (mediaType == BANNER && rawBid.code) { | ||
bidResponse.ad = rawBid.code + (rawBid.px_cr ? "\n<img width=0 height=0 src='" + rawBid.px_cr + "' />" : ''); | ||
} else if (mediaType == VIDEO && rawBid.creativemacros && rawBid.creativemacros.HTML5VID_VASTSTRING) { | ||
var playerSize = spec.getPlayerSize(bidRequest); | ||
if (playerSize != null) { | ||
bidResponse.width = playerSize[0]; | ||
bidResponse.height = playerSize[1]; | ||
} | ||
bidResponse.mediaType = VIDEO; | ||
bidResponse.vastXml = rawBid.creativemacros.HTML5VID_VASTSTRING; | ||
} else { | ||
return utils.logError('bad response', rawBid); | ||
} | ||
|
||
bidResponses.push(bidResponse); | ||
} | ||
|
||
return bidResponses; | ||
} | ||
}; | ||
registerBidder(spec); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Cpmstar Bidder Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: [email protected] | ||
``` | ||
|
||
# Description | ||
|
||
Module that connects to Cpmstar's demand sources | ||
|
||
# Test Parameters | ||
``` | ||
var adUnits = [ | ||
{ | ||
code: 'banner-ad-div', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250]], | ||
} | ||
}, | ||
bids: [ | ||
{ | ||
bidder: 'cpmstar', | ||
params: { | ||
placementId: 81006 | ||
} | ||
}, | ||
] | ||
}, | ||
{ | ||
code: 'video-ad-div', | ||
mediaTypes: { | ||
video: { | ||
context: 'instream', | ||
sizes: [[640, 480]] | ||
} | ||
}, | ||
bids:[ | ||
{ | ||
bidder: 'cpmstar', | ||
params: { | ||
placementId: 81007 | ||
} | ||
} | ||
] | ||
} | ||
]; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import { expect } from 'chai'; | ||
import { spec } from 'modules/cpmstarBidAdapter'; | ||
import { deepClone } from 'src/utils'; | ||
|
||
describe('Cpmstar Bid Adapter', function () { | ||
describe('isBidRequestValid', function () { | ||
it('should return true since the bid is valid', | ||
function () { | ||
var bid = { params: { placementId: 123456 } }; | ||
expect(spec.isBidRequestValid(bid)).to.equal(true); | ||
}) | ||
|
||
it('should return false since the bid is invalid', function () { | ||
var bid = { params: { placementId: '' } }; | ||
expect(spec.isBidRequestValid(bid)).to.equal(false); | ||
}) | ||
|
||
it('should return a valid player size', function() { | ||
var bid = { mediaTypes: { | ||
video: { | ||
playerSize: [[960, 540]] | ||
} | ||
}} | ||
expect(spec.getPlayerSize(bid)[0]).to.equal(960); | ||
expect(spec.getPlayerSize(bid)[1]).to.equal(540); | ||
}) | ||
|
||
it('should return a default player size', function() { | ||
var bid = { mediaTypes: { | ||
video: { | ||
playerSize: null | ||
} | ||
}} | ||
expect(spec.getPlayerSize(bid)[0]).to.equal(640); | ||
expect(spec.getPlayerSize(bid)[1]).to.equal(440); | ||
}) | ||
}); | ||
|
||
describe('buildRequests', function () { | ||
const valid_bid_requests = [{ | ||
'bidder': 'cpmstar', | ||
'params': { | ||
'placementId': '57' | ||
}, | ||
'sizes': [[300, 250]], | ||
'bidId': 'bidId' | ||
}]; | ||
|
||
const bidderRequest = { | ||
refererInfo: { | ||
referer: 'referer', | ||
reachedTop: false, | ||
} | ||
|
||
}; | ||
|
||
it('should produce a valid production request', function () { | ||
var requests = spec.buildRequests(valid_bid_requests, bidderRequest); | ||
expect(requests[0]).to.have.property('method'); | ||
expect(requests[0]).to.have.property('url'); | ||
expect(requests[0]).to.have.property('bidRequest'); | ||
expect(requests[0].url).to.include('//server.cpmstar.com/view.aspx'); | ||
}); | ||
it('should produce a valid staging request', function () { | ||
var stgReq = deepClone(valid_bid_requests); | ||
stgReq[0].params.endpoint = 'staging'; | ||
var requests = spec.buildRequests(stgReq, bidderRequest); | ||
expect(requests[0]).to.have.property('method'); | ||
expect(requests[0]).to.have.property('url'); | ||
expect(requests[0]).to.have.property('bidRequest'); | ||
expect(requests[0].url).to.include('//staging.server.cpmstar.com/view.aspx'); | ||
}); | ||
it('should produce a valid dev request', function () { | ||
var devReq = deepClone(valid_bid_requests); | ||
devReq[0].params.endpoint = 'dev'; | ||
var requests = spec.buildRequests(devReq, bidderRequest); | ||
expect(requests[0]).to.have.property('method'); | ||
expect(requests[0]).to.have.property('url'); | ||
expect(requests[0]).to.have.property('bidRequest'); | ||
expect(requests[0].url).to.include('//dev.server.cpmstar.com/view.aspx'); | ||
}); | ||
}) | ||
|
||
describe('interpretResponse', function () { | ||
const request = { | ||
bidRequest: { | ||
mediaType: 'BANNER' | ||
} | ||
}; | ||
const serverResponse = { | ||
body: [{ | ||
creatives: [{ | ||
cpm: 1, | ||
width: 0, | ||
height: 0, | ||
currency: 'USD', | ||
netRevenue: true, | ||
ttl: 1, | ||
creativeid: '1234', | ||
requestid: '11123', | ||
code: 'no idea', | ||
media: 'banner', | ||
} | ||
], | ||
}] | ||
}; | ||
|
||
it('should return a valid bidresponse array', function () { | ||
var r = spec.interpretResponse(serverResponse, request) | ||
var c = serverResponse.body[0].creatives[0]; | ||
expect(r[0].length).to.not.equal(0); | ||
expect(r[0].requestId).equal(c.requestid); | ||
expect(r[0].creativeId).equal(c.creativeid); | ||
expect(r[0].cpm).equal(c.cpm); | ||
expect(r[0].width).equal(c.width); | ||
expect(r[0].height).equal(c.height); | ||
expect(r[0].currency).equal(c.currency); | ||
expect(r[0].netRevenue).equal(c.netRevenue); | ||
expect(r[0].ttl).equal(c.ttl); | ||
expect(r[0].ad).equal(c.code); | ||
}); | ||
|
||
it('should return a valid bidresponse array from a non-array-body', function () { | ||
var r = spec.interpretResponse({ body: serverResponse.body[0] }, request) | ||
var c = serverResponse.body[0].creatives[0]; | ||
expect(r[0].length).to.not.equal(0); | ||
expect(r[0].requestId).equal(c.requestid); | ||
expect(r[0].creativeId).equal(c.creativeid); | ||
expect(r[0].cpm).equal(c.cpm); | ||
expect(r[0].width).equal(c.width); | ||
expect(r[0].height).equal(c.height); | ||
expect(r[0].currency).equal(c.currency); | ||
expect(r[0].netRevenue).equal(c.netRevenue); | ||
expect(r[0].ttl).equal(c.ttl); | ||
expect(r[0].ad).equal(c.code); | ||
}); | ||
|
||
it('should return undefined due to an invalid cpm value', function () { | ||
var badServer = deepClone(serverResponse); | ||
badServer.body[0].creatives[0].cpm = 0; | ||
var c = spec.interpretResponse(badServer, request); | ||
expect(c).to.be.undefined; | ||
}); | ||
|
||
it('should return undefined due to a bad response', function () { | ||
var badServer = deepClone(serverResponse); | ||
badServer.body[0].creatives[0].code = null; | ||
var c = spec.interpretResponse(badServer, request); | ||
expect(c).to.be.undefined; | ||
}); | ||
|
||
it('should return a valid response with a dealId', function () { | ||
var dealServer = deepClone(serverResponse); | ||
dealServer.body[0].creatives[0].dealId = 'deal'; | ||
expect(spec.interpretResponse(dealServer, request)[0].dealId).to.equal('deal'); | ||
}); | ||
}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a suggestion, it may nice to add some log messages here (such as
utils.logWarn()
) to indicate something was missing from the bid response. It would make it easier to debug by seeing the message in the browser console.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We added a few log messages, thanks!