Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/prebid/Prebid.js
Browse files Browse the repository at this point in the history
* '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
m.sorochuk committed Jan 3, 2018
2 parents 77316ea + 2b1b1fe commit ae13f88
Show file tree
Hide file tree
Showing 58 changed files with 2,029 additions and 389 deletions.
4 changes: 4 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Thank you for your pull request. Please make sure this PR is scoped to one chang
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] CI related changes
- [ ] Does this change affect user-facing APIs or examples documented on http://prebid.org?
- [ ] Other

## Description of change
Expand All @@ -32,6 +33,9 @@ Be sure to test the integration with your adserver using the [Hello World](/inte
- contact email of the adapter’s maintainer
- [ ] official adapter submission

For any changes that affect user-facing APIs or example code documented on http://prebid.org, please provide:

- A link to a PR on the docs repo at https://github.com/prebid/prebid.github.io/

## Other information
<!-- References to related PR or issue #s, @mentions of the person or team responsible for reviewing changes, etc. -->
2 changes: 1 addition & 1 deletion modules/adomikAnalyticsAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ let adomikAdapter = Object.assign(adapter({}),
track({ eventType, args }) {
switch (eventType) {
case auctionInit:
adomikAdapter.currentContext.id = args.requestId
adomikAdapter.currentContext.id = args.auctionId
adomikAdapter.currentContext.timeout = args.timeout
if (args.config.bidwonTimeout !== undefined && typeof args.config.bidwonTimeout === 'number') {
bidwonTimeout = args.config.bidwonTimeout;
Expand Down
2 changes: 1 addition & 1 deletion modules/conversantBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const spec = {
const secure = isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0);

siteId = utils.getBidIdParameter('site_id', bid.params);
requestId = bid.requestId;
requestId = bid.auctionId;

const format = convertSizes(bid.sizes);

Expand Down
317 changes: 317 additions & 0 deletions modules/freewheelSSPBidAdapter.js
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);
27 changes: 27 additions & 0 deletions modules/freewheelSSPBidAdapter.md
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'
}
}
]
}
];
```
Loading

0 comments on commit ae13f88

Please sign in to comment.