forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Playground XYZ - new adapter (prebid#2606)
* add playground adapters * clean up * update with upstream master * add test file clean up adapter by removing native referecnes * test file * replace appnexus with playground reference in error logs * remove commented code * change key in response object from appnexus to playgroundxyz * change tests so we test for ordering by cpm as well * dont drop other bids, just set cpm to 0 and send it through * clean up * restore glulp file * fix documentation * remove cpm logic from adapter * change application type to application\json for playground adapter * update adaptor to use openRtb * add device and site to bid * add extra space on error msg * remove package-lock * update pg details * Update playgroundxyzBidAdapter.md
- Loading branch information
1 parent
e2154e3
commit df08a1b
Showing
3 changed files
with
368 additions
and
0 deletions.
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,160 @@ | ||
import * as utils from 'src/utils'; | ||
import { registerBidder } from 'src/adapters/bidderFactory'; | ||
import { BANNER } from 'src/mediaTypes'; | ||
|
||
const BIDDER_CODE = 'playgroundxyz'; | ||
const URL = 'https://ads.playground.xyz/host-config/prebid'; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
aliases: ['playgroundxyz'], | ||
supportedMediaTypes: [BANNER], | ||
|
||
/** | ||
* Determines whether or not the given bid request is valid. | ||
* | ||
* @param {object} bid The bid to validate. | ||
* @return boolean True if this is a valid bid, and false otherwise. | ||
*/ | ||
isBidRequestValid: function (bid) { | ||
return !!(bid.params.placementId); | ||
}, | ||
|
||
/** | ||
* Make a server request from the list of BidRequests. | ||
* | ||
* @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. | ||
* @return ServerRequest Info describing the request to the server. | ||
*/ | ||
buildRequests: function (bidRequests, bidderRequest) { | ||
const topLocation = utils.getTopWindowLocation(); | ||
const payload = JSON.stringify({ | ||
id: bidRequests[0].auctionId, | ||
site: { | ||
domain: window.location.protocol + '//' + topLocation.hostname, | ||
name: topLocation.hostname, | ||
page: topLocation.href, | ||
}, | ||
device: { | ||
ua: navigator.userAgent, | ||
language: navigator.language, | ||
devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, | ||
}, | ||
imp: bidRequests.map(mapImpression) | ||
}); | ||
|
||
const options = { | ||
contentType: 'application/json', | ||
withCredentials: false | ||
}; | ||
|
||
return { | ||
method: 'POST', | ||
url: URL, | ||
data: payload, | ||
options, | ||
bidderRequest | ||
}; | ||
}, | ||
|
||
/** | ||
* Unpack the response from the server into a list of bids. | ||
* | ||
* @param {*} serverResponse A successful response from the server. | ||
* @return {Bid[]} An array of bids which were nested inside the server. | ||
*/ | ||
interpretResponse: function (serverResponse, { bidderRequest }) { | ||
serverResponse = serverResponse.body; | ||
const bids = []; | ||
|
||
if (!serverResponse || serverResponse.error) { | ||
let errorMessage = `in response for ${bidderRequest.bidderCode} adapter`; | ||
if (serverResponse && serverResponse.error) { errorMessage += `: ${serverResponse.error}`; } | ||
utils.logError(errorMessage); | ||
return bids; | ||
} | ||
|
||
if (!utils.isArray(serverResponse.seatbid)) { | ||
let errorMessage = `in response for ${bidderRequest.bidderCode} adapter `; | ||
utils.logError(errorMessage += 'Malformed seatbid response'); | ||
return bids; | ||
} | ||
|
||
serverResponse.seatbid.forEach(sBid => { | ||
if (sBid.hasOwnProperty('bid')) { | ||
sBid.bid.forEach(iBid => { | ||
if (iBid.price !== 0) { | ||
const bid = newBid(iBid); | ||
bids.push(bid); | ||
} | ||
}); | ||
} | ||
}); | ||
return bids; | ||
}, | ||
|
||
getUserSyncs: function (syncOptions) { | ||
if (syncOptions.iframeEnabled) { | ||
return [{ | ||
type: 'iframe', | ||
url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' | ||
}]; | ||
} | ||
} | ||
} | ||
|
||
function newBid(bid) { | ||
return { | ||
requestId: bid.impid, | ||
mediaType: BANNER, | ||
cpm: bid.price, | ||
creativeId: bid.adid, | ||
ad: bid.adm, | ||
width: bid.w, | ||
height: bid.h, | ||
ttl: 300, | ||
netRevenue: true, | ||
currency: 'USD', | ||
}; | ||
} | ||
|
||
function mapImpression(bid) { | ||
return { | ||
id: bid.bidId, | ||
banner: mapBanner(bid), | ||
ext: { | ||
appnexus: { | ||
placement_id: parseInt(bid.params.placementId, 10) | ||
} | ||
} | ||
}; | ||
} | ||
|
||
function mapBanner(bid) { | ||
return { | ||
w: parseInt(bid.sizes[0][0], 10), | ||
h: parseInt(bid.sizes[0][1], 10), | ||
format: mapSizes(bid.sizes) | ||
}; | ||
} | ||
|
||
function mapSizes(bidSizes) { | ||
const format = []; | ||
bidSizes.forEach(size => { | ||
format.push({ | ||
w: parseInt(size[0], 10), | ||
h: parseInt(size[1], 10) | ||
}); | ||
}); | ||
return format; | ||
} | ||
|
||
function isMobile() { | ||
return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent); | ||
} | ||
|
||
function isConnectedTV() { | ||
return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(global.navigator.userAgent); | ||
} | ||
|
||
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,72 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Playground XYZ Bid Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: tech+prebid@playgroundxyz.com | ||
``` | ||
|
||
# Description | ||
|
||
Connects to playgroundxyz ad server for bids. | ||
|
||
Playground XYZ bid adapter supports Banner. | ||
|
||
# Test Parameters | ||
``` | ||
var adUnits = [ | ||
// Banner adUnit | ||
{ | ||
code: 'banner-div', | ||
sizes: [[300, 250], [300,600]], | ||
bids: [{ | ||
bidder: 'playgroundxyz', | ||
params: { | ||
placementId: '10433394' | ||
} | ||
}] | ||
}, | ||
// Video instream adUnit | ||
{ | ||
code: 'video-instream', | ||
sizes: [640, 480], | ||
mediaTypes: { | ||
video: { | ||
context: 'instream' | ||
}, | ||
}, | ||
bids: [{ | ||
bidder: 'playgroundxyz', | ||
params: { | ||
placementId: '9333431', | ||
video: { | ||
skippable: true, | ||
playback_methods: ['auto_play_sound_off'] | ||
} | ||
} | ||
}] | ||
}, | ||
// Video outstream adUnit | ||
{ | ||
code: 'video-outstream', | ||
sizes: [[640, 480]], | ||
mediaTypes: { | ||
video: { | ||
context: 'outstream' | ||
} | ||
}, | ||
bids: [ | ||
{ | ||
bidder: 'playgroundxyz', | ||
params: { | ||
placementId: '5768085', | ||
video: { | ||
skippable: true, | ||
playback_method: ['auto_play_sound_off'] | ||
} | ||
} | ||
} | ||
] | ||
} | ||
]; | ||
``` |
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,136 @@ | ||
import { expect } from 'chai'; | ||
import { spec } from 'modules/playgroundxyzBidAdapter'; | ||
import { newBidder } from 'src/adapters/bidderFactory'; | ||
import { deepClone } from 'src/utils'; | ||
|
||
const URL = 'https://ads.playground.xyz/host-config/prebid'; | ||
|
||
describe('playgroundxyzBidAdapter', () => { | ||
const adapter = newBidder(spec); | ||
|
||
describe('inherited functions', () => { | ||
it('exists and is a function', () => { | ||
expect(adapter.callBids).to.exist.and.to.be.a('function'); | ||
}); | ||
}); | ||
|
||
describe('isBidRequestValid', () => { | ||
let bid = { | ||
'bidder': 'playgroundxyz', | ||
'params': { | ||
'placementId': '10433394' | ||
}, | ||
'adUnitCode': 'adunit-code', | ||
'sizes': [[300, 250], [320, 50]], | ||
'bidId': '30b31c1838de1e', | ||
'bidderRequestId': '22edbae2733bf6', | ||
'auctionId': '1d1a030790a475', | ||
}; | ||
|
||
it('should return true when required params found', () => { | ||
expect(spec.isBidRequestValid(bid)).to.equal(true); | ||
}); | ||
|
||
it('should return false when required params are not passed', () => { | ||
let bid = Object.assign({}, bid); | ||
delete bid.params; | ||
bid.params = { | ||
'placementId': 0 | ||
}; | ||
expect(spec.isBidRequestValid(bid)).to.equal(false); | ||
}); | ||
}); | ||
|
||
describe('buildRequests', () => { | ||
let bidRequests = [ | ||
{ | ||
'bidder': 'playgroundxyz', | ||
'params': { | ||
'placementId': '10433394' | ||
}, | ||
'adUnitCode': 'adunit-code', | ||
'sizes': [[300, 250], [300, 600]], | ||
'bidId': '30b31c1838de1e', | ||
'bidderRequestId': '22edbae2733bf6', | ||
'auctionId': '1d1a030790a475', | ||
} | ||
]; | ||
|
||
it('sends bid request to ENDPOINT via POST', () => { | ||
let bidRequest = Object.assign([], bidRequests); | ||
|
||
const request = spec.buildRequests(bidRequest); | ||
const data = JSON.parse(request.data); | ||
const banner = data.imp[0].banner; | ||
|
||
expect(Object.keys(data.imp[0].ext)).to.have.members(['appnexus']); | ||
expect([banner.w, banner.h]).to.deep.equal([300, 250]); | ||
expect(banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); | ||
expect(request.url).to.equal(URL); | ||
expect(request.method).to.equal('POST'); | ||
}); | ||
}) | ||
|
||
describe('interpretResponse', () => { | ||
let response = { | ||
'id': 'bidd_id', | ||
'seatbid': [ { | ||
'bid': [ | ||
{ | ||
'id': '4434762738980910431', | ||
'impid': '221f2bdc1fbc31', | ||
'price': 1, | ||
'adid': '91673066', | ||
'adm': '<script src=\'pgxyz\'></script>', | ||
'adomain': [ 'pg.xyz' ], | ||
'iurl': 'http://pgxyz.com/cr?id=91673066', | ||
'cid': 'c_id', | ||
'crid': 'c_rid', | ||
'h': 50, | ||
'w': 320, | ||
'ext': { | ||
'appnexus': { | ||
'brand_id': 1, | ||
'auction_id': 1087655594852566000, | ||
'bidder_id': 2, | ||
'bid_ad_type': 0 | ||
} | ||
} | ||
} | ||
], | ||
'seat': '4321' | ||
}], | ||
'bidid': '6894227111893743356', | ||
'cur': 'USD' | ||
}; | ||
|
||
let bidderRequest = { | ||
'bidderCode': 'playgroundxyz' | ||
}; | ||
|
||
it('should get correct bid response', () => { | ||
let expectedResponse = [ | ||
{ | ||
'requestId': '221f2bdc1fbc31', | ||
'cpm': 1, | ||
'creativeId': 91673066, | ||
'width': 300, | ||
'height': 50, | ||
'ad': '<script src=\'pgxyz\'></script>', | ||
'mediaType': 'banner', | ||
'currency': 'USD', | ||
'ttl': 300, | ||
'netRevenue': true | ||
} | ||
]; | ||
let result = spec.interpretResponse({ body: response }, {bidderRequest}); | ||
expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); | ||
}); | ||
|
||
it('handles nobid responses', () => { | ||
let response = ''; | ||
let result = spec.interpretResponse({ body: response }, {bidderRequest}); | ||
expect(result.length).to.equal(0); | ||
}); | ||
}); | ||
}); |