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.
Merge branch 'master' of https://github.com/prebid/Prebid.js
* 'master' of https://github.com/prebid/Prebid.js: Add note about docs needed before merge (prebid#1959) Prebid 1.1.1 Release Fixes unit tests in browsers other than chrome (prebid#1987) remove hardcoded localhost port for tests (prebid#1988) S2s defaults fix in serverbidServerBidAdapter (prebid#1986) Increment pre version Prebid 1.1.0 Release added hb_source to default keys (prebid#1969) ServerBid Server BidAdapter (prebid#1819) [Add BidAdapter] rxrtb adapter for Perbid.js 1.0 (prebid#1950) Remove duplicate request id and fix empty response from getHighesCpmBids, getAdserverTargeting (prebid#1970) Remove stray console.log (prebid#1975) Added iQM Bid Adapter for Prebid.js 1.0 (prebid#1880) + fixed endpoint request data property names - width to w and height to h (prebid#1955) Add freewheel ssp bidder adapter for prebid 1.0 (prebid#1793) use auctionId instead of requestId (prebid#1968) Serverbid bid adapter: update alias config (prebid#1963) Typo correction of YIELDONE md file (prebid#1954) allow non-mappable sizes to be passed and used in rubicon adapter (prebid#1893) Add user-facing docs reminder to PR template (prebid#1956)
- Loading branch information
Showing
58 changed files
with
2,029 additions
and
389 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
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
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
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,317 @@ | ||
import * as utils from 'src/utils'; | ||
import { registerBidder } from 'src/adapters/bidderFactory'; | ||
// import { config } from 'src/config'; | ||
|
||
const BIDDER_CODE = 'freewheel-ssp'; | ||
|
||
const PROTOCOL = getProtocol(); | ||
const FREEWHEEL_ADSSETUP = PROTOCOL + '://ads.stickyadstv.com/www/delivery/swfIndex.php'; | ||
const MUSTANG_URL = PROTOCOL + '://cdn.stickyadstv.com/mustang/mustang.min.js'; | ||
const PRIMETIME_URL = PROTOCOL + '://cdn.stickyadstv.com/prime-time/'; | ||
const USER_SYNC_URL = PROTOCOL + '://ads.stickyadstv.com/auto-user-sync'; | ||
|
||
function getProtocol() { | ||
if (location.protocol && location.protocol.indexOf('https') === 0) { | ||
return 'https'; | ||
} else { | ||
return 'http'; | ||
} | ||
} | ||
|
||
function isValidUrl(str) { | ||
if (!str) { | ||
return false; | ||
} | ||
|
||
// regExp for url validation | ||
var pattern = /^(https?|ftp|file):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/; | ||
return pattern.test(str); | ||
} | ||
|
||
function getBiggerSize(array) { | ||
var result = [0, 0]; | ||
for (var i = 0; i < array.length; i++) { | ||
if (array[i][0] * array[i][1] > result[0] * result[1]) { | ||
result = array[i]; | ||
} | ||
} | ||
return result; | ||
} | ||
|
||
/* | ||
* read the pricing extension with this format: <Extension type='StickyPricing'><Price currency="EUR">1.0000</Price></Extension> | ||
* @return {object} pricing data in format: {currency: "EUR", price:"1.000"} | ||
*/ | ||
function getPricing(xmlNode) { | ||
var pricingExtNode; | ||
var princingData = {}; | ||
|
||
var extensions = xmlNode.querySelectorAll('Extension'); | ||
// Nodelist.forEach is not supported in IE and Edge | ||
// Workaround given here https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10638731/ | ||
Array.prototype.forEach.call(extensions, function(node) { | ||
if (node.getAttribute('type') === 'StickyPricing') { | ||
pricingExtNode = node; | ||
} | ||
}); | ||
|
||
if (pricingExtNode) { | ||
var priceNode = pricingExtNode.querySelector('Price'); | ||
princingData = { | ||
currency: priceNode.getAttribute('currency'), | ||
price: priceNode.textContent || priceNode.innerText | ||
}; | ||
} else { | ||
utils.logWarn('PREBID - ' + BIDDER_CODE + ': Can\'t get pricing data. Is price awareness enabled?'); | ||
} | ||
|
||
return princingData; | ||
} | ||
|
||
function getCreativeId(xmlNode) { | ||
var creaId = ''; | ||
var adNodes = xmlNode.querySelectorAll('Ad'); | ||
// Nodelist.forEach is not supported in IE and Edge | ||
// Workaround given here https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10638731/ | ||
Array.prototype.forEach.call(adNodes, function(el) { | ||
creaId += '[' + el.getAttribute('id') + ']'; | ||
}); | ||
|
||
return creaId; | ||
} | ||
|
||
/** | ||
* returns the top most accessible window | ||
*/ | ||
function getTopMostWindow() { | ||
var res = window; | ||
|
||
try { | ||
while (top !== res) { | ||
if (res.parent.location.href.length) { res = res.parent; } | ||
} | ||
} catch (e) {} | ||
|
||
return res; | ||
} | ||
|
||
function getComponentId(inputFormat) { | ||
var component = 'mustang'; // default component id | ||
|
||
if (inputFormat && inputFormat !== 'inbanner') { | ||
// format identifiers are equals to their component ids. | ||
component = inputFormat; | ||
} | ||
|
||
return component; | ||
} | ||
|
||
function getAPIName(componentId) { | ||
componentId = componentId || ''; | ||
|
||
// remove dash in componentId to get API name | ||
return componentId.replace('-', ''); | ||
} | ||
|
||
function formatAdHTML(bid, size) { | ||
var integrationType = bid.params.format; | ||
|
||
var divHtml = '<div id="freewheelssp_prebid_target"></div>'; | ||
|
||
var script = ''; | ||
var libUrl = ''; | ||
if (integrationType && integrationType !== 'inbanner') { | ||
libUrl = PRIMETIME_URL + getComponentId(bid.params.format) + '.min.js'; | ||
script = getOutstreamScript(bid, size); | ||
} else { | ||
libUrl = MUSTANG_URL; | ||
script = getInBannerScript(bid, size); | ||
} | ||
|
||
return divHtml + | ||
'<script type=\'text/javascript\'>' + | ||
'(function() {' + | ||
' var st = document.createElement(\'script\'); st.type = \'text/javascript\'; st.async = true;' + | ||
' st.src = \'' + libUrl + '\';' + | ||
' st.onload = function(){' + | ||
' var vastLoader = new window.com.stickyadstv.vast.VastLoader();' + | ||
' var vast = vastLoader.getVast();' + | ||
// get the top most accessible window | ||
' var topWindow = (function(){var res=window; try{while(top != res){if(res.parent.location.href.length)res=res.parent;}}catch(e){}return res;})();' + | ||
// inject the xml in the Vast object as string | ||
' vast.setXmlString(topWindow.freewheelssp_cache["' + bid.adUnitCode + '"]);' + | ||
// force ad parsing on the given vast xml | ||
' vastLoader.parseAds(vast, {' + | ||
' onSuccess: function() {' + script + ' }' + | ||
' });' + | ||
' };' + | ||
' document.head.appendChild(st);' + | ||
'})();' + | ||
'</script>'; | ||
} | ||
|
||
var getInBannerScript = function(bid, size) { | ||
return 'var config = {' + | ||
' preloadedVast:vast,' + | ||
' autoPlay:true' + | ||
' };' + | ||
' var ad = new window.com.stickyadstv.vpaid.Ad(document.getElementById("freewheelssp_prebid_target"),config);' + | ||
' (new window.com.stickyadstv.tools.ASLoader(' + bid.params.zoneId + ', \'' + getComponentId(bid.params.format) + '\')).registerEvents(ad);' + | ||
' ad.initAd(' + size[0] + ',' + size[1] + ',"",0,"","");'; | ||
}; | ||
|
||
var getOutstreamScript = function(bid) { | ||
var placementCode = bid.adUnitCode; | ||
|
||
var config = bid.params; | ||
|
||
// default placement if no placement is set | ||
if (!config.hasOwnProperty('domId') && !config.hasOwnProperty('auto') && !config.hasOwnProperty('p') && !config.hasOwnProperty('article')) { | ||
config.domId = placementCode; | ||
} | ||
|
||
var script = 'var config = {' + | ||
' preloadedVast:vast,' + | ||
' ASLoader:new window.com.stickyadstv.tools.ASLoader(' + bid.params.zoneId + ', \'' + getComponentId(bid.params.format) + '\')'; | ||
|
||
for (var key in config) { | ||
// dont' send format parameter | ||
// neither zone nor vastUrlParams value as Vast is already loaded | ||
if (config.hasOwnProperty(key) && key !== 'format' && key !== 'zone' && key !== 'zoneId' && key !== 'vastUrlParams') { | ||
script += ',' + key + ':"' + config[key] + '"'; | ||
} | ||
} | ||
script += '};' + | ||
|
||
'window.com.stickyadstv.' + getAPIName(bid.params.format) + '.start(config);'; | ||
|
||
return script; | ||
}; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedMediaTypes: ['video'], | ||
aliases: ['stickyadstv'], // former name for freewheel-ssp | ||
/** | ||
* 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.zoneId); | ||
}, | ||
|
||
/** | ||
* 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) { | ||
// var currency = config.getConfig(currency); | ||
|
||
var currentBidRequest = bidRequests[0]; | ||
if (bidRequests.length > 1) { | ||
utils.logMessage('Prebid.JS - freewheel bid adapter: only one ad unit is required.'); | ||
} | ||
|
||
var requestParams = { | ||
reqType: 'AdsSetup', | ||
protocolVersion: '2.0', | ||
zoneId: currentBidRequest.params.zoneId, | ||
componentId: getComponentId(currentBidRequest.params.format) | ||
}; | ||
|
||
var location = utils.getTopWindowUrl(); | ||
if (isValidUrl(location)) { | ||
requestParams.loc = location; | ||
} | ||
|
||
var playerSize = getBiggerSize(currentBidRequest.sizes); | ||
if (playerSize[0] > 0 || playerSize[1] > 0) { | ||
requestParams.playerSize = playerSize[0] + 'x' + playerSize[1]; | ||
} | ||
|
||
return { | ||
method: 'GET', | ||
url: FREEWHEEL_ADSSETUP, | ||
data: requestParams, | ||
bidRequest: currentBidRequest | ||
}; | ||
}, | ||
|
||
/** | ||
* Unpack the response from the server into a list of bids. | ||
* | ||
* @param {*} serverResponse A successful response from the server. | ||
* @param {object} request: the built request object containing the initial bidRequest. | ||
* @return {Bid[]} An array of bids which were nested inside the server. | ||
*/ | ||
interpretResponse: function(serverResponse, request) { | ||
var bidrequest = request.bidRequest; | ||
var playerSize = getBiggerSize(bidrequest.sizes); | ||
|
||
if (typeof serverResponse == 'object' && typeof serverResponse.body == 'string') { | ||
serverResponse = serverResponse.body; | ||
} | ||
|
||
var xmlDoc; | ||
try { | ||
var parser = new DOMParser(); | ||
xmlDoc = parser.parseFromString(serverResponse, 'application/xml'); | ||
} catch (err) { | ||
utils.logWarn('Prebid.js - ' + BIDDER_CODE + ' : ' + err); | ||
return; | ||
} | ||
|
||
const princingData = getPricing(xmlDoc); | ||
const creativeId = getCreativeId(xmlDoc); | ||
|
||
const topWin = getTopMostWindow(); | ||
if (!topWin.freewheelssp_cache) { | ||
topWin.freewheelssp_cache = {}; | ||
} | ||
topWin.freewheelssp_cache[bidrequest.adUnitCode] = serverResponse; | ||
|
||
const bidResponses = []; | ||
|
||
if (princingData.price) { | ||
const bidResponse = { | ||
requestId: bidrequest.bidId, | ||
cpm: princingData.price, | ||
width: playerSize[0], | ||
height: playerSize[1], | ||
creativeId: creativeId, | ||
currency: princingData.currency, | ||
netRevenue: true, | ||
ttl: 360 | ||
}; | ||
|
||
var mediaTypes = bidrequest.mediaTypes || {}; | ||
if (mediaTypes.video) { | ||
// bidResponse.vastXml = serverResponse; | ||
bidResponse.mediaType = 'video'; | ||
|
||
var blob = new Blob([serverResponse], {type: 'application/xml'}); | ||
bidResponse.vastUrl = window.URL.createObjectURL(blob); | ||
} else { | ||
bidResponse.ad = formatAdHTML(bidrequest, playerSize); | ||
} | ||
|
||
bidResponses.push(bidResponse); | ||
} | ||
|
||
return bidResponses; | ||
}, | ||
|
||
getUserSyncs: function(syncOptions) { | ||
if (syncOptions.pixelEnabled) { | ||
return [{ | ||
type: 'image', | ||
url: USER_SYNC_URL | ||
}]; | ||
} | ||
} | ||
} | ||
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,27 @@ | ||
# Overview | ||
|
||
Module Name: Freewheel SSP Bidder Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: clientsidesdk@freewheel.tv | ||
|
||
# Description | ||
|
||
Module that connects to Freewheel ssp's demand sources | ||
|
||
# Test Parameters | ||
``` | ||
var adUnits = [ | ||
{ | ||
code: 'test-div', | ||
sizes: [[300, 250]], // a display size | ||
bids: [ | ||
{ | ||
bidder: "freewheel-ssp", | ||
params: { | ||
zoneId : '277225' | ||
} | ||
} | ||
] | ||
} | ||
]; | ||
``` |
Oops, something went wrong.