-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* quantumBidAdapter initial commit * eslint errors fixed * updating quantumBidAdapter for reviews, fixed tests to work with native * set new prebid location for testing and some fixing * added supportedMediaTypes * Tests fixed * Fixed issues with image assets. Tested with the example provided
- Loading branch information
1 parent
1d76429
commit 853a762
Showing
3 changed files
with
662 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,301 @@ | ||
import * as utils from 'src/utils'; | ||
import { BANNER, NATIVE } from 'src/mediaTypes'; | ||
import {registerBidder} from 'src/adapters/bidderFactory'; | ||
|
||
const BIDDER_CODE = 'quantum'; | ||
const ENDPOINT_URL = '//s.sspqns.com/hb'; | ||
export const spec = { | ||
code: BIDDER_CODE, | ||
aliases: ['quantx', 'qtx'], // short code | ||
supportedMediaTypes: [BANNER, NATIVE], | ||
|
||
/** | ||
* 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 && bid.params.placementId); | ||
}, | ||
/** | ||
* Make a server request from the list of BidRequests. | ||
* | ||
* @param {validBidRequests[]} - an array of bids | ||
* @return ServerRequest Info describing the request to the server. | ||
*/ | ||
buildRequests: function (bidRequests) { | ||
return bidRequests.map(bid => { | ||
const qtxRequest = {}; | ||
let bidId = ''; | ||
|
||
const params = bid.params; | ||
let placementId = params.placementId; | ||
|
||
let devEnpoint = false; | ||
if (params.useDev && params.useDev === '1') { | ||
devEnpoint = '//sdev.sspqns.com/hb'; | ||
} | ||
let renderMode = 'native'; | ||
for (let i = 0; i < bid.sizes.length; i++) { | ||
if (bid.sizes[i][0] > 1 && bid.sizes[i][1] > 1) { | ||
renderMode = 'banner'; | ||
break; | ||
} | ||
} | ||
|
||
let mediaType = (bid.mediaType === 'native' || utils.deepAccess(bid, 'mediaTypes.native')) ? 'native' : 'banner'; | ||
|
||
if (mediaType === 'native') { | ||
renderMode = 'native'; | ||
} | ||
|
||
if (!bidId) { | ||
bidId = bid.bidId; | ||
} | ||
qtxRequest.auid = placementId; | ||
const url = devEnpoint || ENDPOINT_URL; | ||
|
||
return { | ||
method: 'GET', | ||
bidId: bidId, | ||
sizes: bid.sizes, | ||
mediaType: mediaType, | ||
renderMode: renderMode, | ||
url: url, | ||
'data': qtxRequest | ||
}; | ||
}); | ||
}, | ||
/** | ||
* Unpack the response from the server into a list of bids. | ||
* | ||
* @param {ServerResponse} serverResponse A successful response from the server. | ||
* @return {Bid[]} An array of bids which were nested inside the server. | ||
*/ | ||
interpretResponse: function (serverResponse, bidRequest) { | ||
const serverBody = serverResponse.body; | ||
const bidResponses = []; | ||
let responseCPM; | ||
let bid = {}; | ||
let id = bidRequest.bidId; | ||
|
||
if (serverBody.price && serverBody.price !== 0) { | ||
responseCPM = parseFloat(serverBody.price); | ||
|
||
bid.creativeId = serverBody.creative_id || '0'; | ||
bid.cpm = responseCPM; | ||
bid.requestId = bidRequest.bidId; | ||
bid.width = 1; | ||
bid.height = 1; | ||
bid.ttl = 200; | ||
bid.netRevenue = true; | ||
bid.currency = 'USD'; | ||
|
||
if (serverBody.native) { | ||
bid.native = serverBody.native; | ||
} | ||
if (serverBody.cobj) { | ||
bid.cobj = serverBody.cobj; | ||
} | ||
|
||
bid.nurl = serverBody.nurl; | ||
bid.sync = serverBody.sync; | ||
if (bidRequest.renderMode && bidRequest.renderMode === 'banner') { | ||
bid.width = 300; | ||
bid.height = 225; | ||
if (serverBody.native) { | ||
const adAssetsUrl = '//cdn.elasticad.net/native/serve/js/quantx/quantumAd/'; | ||
let assets = serverBody.native.assets; | ||
let link = serverBody.native.link; | ||
|
||
let trackers = []; | ||
if (serverBody.native.imptrackers) { | ||
trackers = serverBody.native.imptrackers; | ||
} | ||
|
||
let jstracker = ''; | ||
if (serverBody.native.jstracker) { | ||
jstracker = serverBody.native.jstracker; | ||
} | ||
|
||
if (serverBody.nurl) { | ||
trackers.push(serverBody.nurl); | ||
} | ||
|
||
let ad = {}; | ||
ad['trackers'] = trackers; | ||
ad['jstrackers'] = jstracker; | ||
|
||
for (let i = 0; i < assets.length; i++) { | ||
let asset = assets[i]; | ||
switch (asset['id']) { | ||
case 1: | ||
ad['title'] = asset['title']['text']; | ||
break; | ||
case 2: | ||
ad['sponsor_logo'] = asset['img']['url']; | ||
break; | ||
case 3: | ||
ad['content'] = asset['data']['value']; | ||
break; | ||
case 4: | ||
ad['main_image'] = asset['img']['url']; | ||
break; | ||
case 6: | ||
ad['teaser_type'] = 'vast'; | ||
ad['video_url'] = asset['video']['vasttag']; | ||
break; | ||
case 10: | ||
ad['sponsor_name'] = asset['data']['value']; | ||
break; | ||
case 2001: | ||
ad['expanded_content_type'] = 'embed'; | ||
ad['expanded_summary'] = asset['data']['value']; | ||
break; | ||
case 2002: | ||
ad['expanded_content_type'] = 'vast'; | ||
ad['expanded_summary'] = asset['data']['value']; | ||
break; | ||
case 2003: | ||
ad['sponsor_url'] = asset['data']['value']; | ||
break; | ||
case 2004: // prism | ||
ad['content_type'] = 'prism'; | ||
break; | ||
case 2005: // internal_landing_page | ||
ad['content_type'] = 'internal_landing_page'; | ||
ad['internal_content_link'] = asset['data']['value']; | ||
break; | ||
case 2006: // teaser as vast | ||
ad['teaser_type'] = 'vast'; | ||
ad['video_url'] = asset['data']['value']; | ||
break; | ||
case 2007: | ||
ad['autoexpand_content_type'] = asset['data']['value']; | ||
break; | ||
case 2022: // content page | ||
ad['content_type'] = 'full_text'; | ||
ad['full_text'] = asset['data']['value']; | ||
break; | ||
} | ||
} | ||
|
||
ad['action_url'] = link.url; | ||
|
||
if (!ad['sponsor_url']) { | ||
ad['sponsor_url'] = ad['action_url']; | ||
} | ||
|
||
ad['clicktrackers'] = []; | ||
if (link.clicktrackers) { | ||
ad['clicktrackers'] = link.clicktrackers; | ||
} | ||
|
||
ad['main_image'] = '//resize-ssp.elasticad.net/scalecrop-290x130/' + window.btoa(ad['main_image']) + '/external'; | ||
|
||
bid.ad = '<div id="ead_' + id + '\">' + | ||
'<div class="ad_container ead_' + id + '" style="clear: both; display:inline-block;width:100%">' + | ||
' <div class="image_content">' + | ||
' <a href="' + ad['action_url'] + '" class="ea_expand" target="_blank"><img src="' + ad['main_image'] + '" class="ea_image ead_image">' + | ||
' </a>' + | ||
' </div>' + | ||
' <div class="ead_content"><a href="' + ad['action_url'] + '" class="ea_expand" style="text-decoration: none" target="_blank"><h2 style="margin:0px;">' + ad['title'] + '</h2></a>' + | ||
' <p class="ea_summary">' + ad['content'] + ' </p></div>' + | ||
' <div style="text-align:right;" class="ea_hide_brand_logo ea_hide_brand_name">' + | ||
' <p style="margin:0;"><span class="ea_creative_var_label">Sponsored by</span>' + | ||
' <a href="' + ad['sponsor_url'] + '" class="ea_link" target="_blank" style="display:inline;" target="_blank"><img src="' + ad['sponsor_logo'] + '" class="ea_image" style="vertical-align:middle;"></a>' + | ||
' </p>' + | ||
' </div>' + | ||
'</div>' + | ||
'<script type="application/javascript">var eanAD = ' + JSON.stringify(ad) + ';</script>' + | ||
'<script src="' + adAssetsUrl + 'qad.js" type="application/javascript"></script>' + | ||
'<link rel="stylesheet" href="' + adAssetsUrl + 'qad.css">' + | ||
'</div>'; | ||
} | ||
} else { | ||
// native | ||
if (bidRequest.mediaType === 'native') { | ||
if (serverBody.native) { | ||
let assets = serverBody.native.assets; | ||
let link = serverBody.native.link; | ||
|
||
let trackers = []; | ||
if (serverBody.native.imptrackers) { | ||
trackers = serverBody.native.imptrackers; | ||
} | ||
|
||
if (serverBody.nurl) { | ||
trackers.push(serverBody.nurl); | ||
} | ||
|
||
let native = {}; | ||
|
||
for (let i = 0; i < assets.length; i++) { | ||
let asset = assets[i]; | ||
switch (asset['id']) { | ||
case 1: | ||
native.title = asset['title']['text']; | ||
break; | ||
case 2: | ||
native.icon = asset['img']; | ||
break; | ||
case 3: | ||
native.body = asset['data']['value']; | ||
break; | ||
case 4: | ||
native.image = asset['img']; | ||
break; | ||
case 10: | ||
native.sponsoredBy = asset['data']['value']; | ||
break; | ||
} | ||
} | ||
native.cta = 'read more'; | ||
if (serverBody.language) { | ||
native.cta = 'read more'; | ||
} | ||
|
||
native.clickUrl = link.url; | ||
native.impressionTrackers = trackers; | ||
if (link.clicktrackers) { | ||
native.clickTrackers = link.clicktrackers; | ||
} | ||
|
||
bid.qtx_native = utils.deepClone(serverBody.native); | ||
bid.native = native; | ||
} | ||
} | ||
} | ||
bidResponses.push(bid); | ||
} | ||
|
||
return bidResponses; | ||
}, | ||
|
||
/** | ||
* Register the user sync pixels which should be dropped after the auction. | ||
* | ||
* @param {SyncOptions} syncOptions Which user syncs are allowed? | ||
* @param {ServerResponse[]} serverResponses List of server's responses. | ||
* @return {UserSync[]} The user syncs which should be dropped. | ||
*/ | ||
getUserSyncs: function (syncOptions, serverResponses) { | ||
const syncs = [] | ||
if (syncOptions.iframeEnabled) { | ||
syncs.push({ | ||
type: 'iframe', | ||
url: '//acdn.adnxs.com/ib/static/usersync/v3/async_usersync.html' | ||
}); | ||
} | ||
if (syncOptions.pixelEnabled && serverResponses.length > 0) { | ||
syncs.push({ | ||
type: 'image', | ||
url: serverResponses[0].body.sync[0] | ||
}); | ||
} | ||
return syncs; | ||
} | ||
} | ||
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,94 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Quantum Advertising Bid Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: sami@elasticad.com | ||
``` | ||
|
||
# Description | ||
|
||
Connects to Quantum's ssp for bids. | ||
|
||
# Sample Ad Unit: For Publishers | ||
``` | ||
var adUnits = [{ | ||
code: 'quantum-adUnit-id-1', | ||
sizes: [[300, 250]], | ||
bids: [{ | ||
bidder: 'quantum', | ||
params: { | ||
placementId: 21546 //quantum adUnit id | ||
} | ||
}] | ||
},{ | ||
code: 'quantum-native-adUnit-id-1', | ||
sizes: [[0, 0]], | ||
mediaTypes: 'native', | ||
bids: [{ | ||
bidder: 'quantum', | ||
params: { | ||
placementId: 21546 //quantum adUnit id | ||
} | ||
}] | ||
}]; | ||
``` | ||
|
||
# Ad Unit and Setup: For Testing | ||
|
||
``` | ||
<html> | ||
<body style="margin:0;padding:0"> | ||
<script> | ||
var pbjs = eanpbjs = pbjs || {}; | ||
pbjs.que = pbjs.que || []; | ||
pbjs.logging = true; | ||
(function() { | ||
var pbjsEl = document.createElement("script"); | ||
pbjsEl.type = "text/javascript"; | ||
pbjsEl.async = true; | ||
var isHttps = 'https:' === document.location.protocol; | ||
pbjsEl.src = "//cdn.elasticad.net/native/serve/js/quantx/quantumPrebidAdapter/prebid.js"; | ||
var pbjsTargetEl = document.getElementsByTagName("head")[0]; | ||
pbjsTargetEl.insertBefore(pbjsEl, pbjsTargetEl.firstChild); | ||
})(); | ||
var adUnitID = 'pl-100'; | ||
pbjs.que.push(function() { | ||
var adUnits = [{ | ||
code: adUnitID, | ||
sizes: [[300, 250]], | ||
bids: [{ | ||
bidder: 'quantum', | ||
params: { | ||
placementId: 21546 //quantum adUnit id | ||
} | ||
}] | ||
}]; | ||
pbjs.addAdUnits(adUnits); | ||
pbjs.requestBids({ | ||
timeout: 800, | ||
bidsBackHandler: function() { | ||
var adUnitData = pbjs.getAdserverTargetingForAdUnitCode(adUnitID); | ||
//console.log('adUnitData', adUnitData); | ||
if(adUnitData['hb_adid']){ | ||
var iframe = document.getElementById('placement'); | ||
var iframeDoc = iframe.contentWindow.document; | ||
pbjs.renderAd(iframeDoc, adUnitData['hb_adid']); | ||
} | ||
} | ||
}); | ||
}); | ||
</script> | ||
<iframe id='placement' FRAMEBORDER="0" SCROLLING="no" MARGINHEIGHT="0" MARGINWIDTH="0" TOPMARGIN="0" LEFTMARGIN="0" ALLOWTRANSPARENCY="true" WIDTH="0" HEIGHT="0"></iframe> | ||
</body> | ||
</html> | ||
``` |
Oops, something went wrong.