Skip to content
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

OpenWrap Nightly Release v21.1.0 #417

Merged
merged 18 commits into from
Oct 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions modules/pubmaticAnalyticsAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,23 @@ function getDomainFromUrl(url) {
return a.hostname;
}

function getDevicePlatform() {
var deviceType = 3;
try {
var ua = navigator.userAgent;
if (ua && utils.isStr(ua) && ua.trim() != '') {
ua = ua.toLowerCase().trim();
var isMobileRegExp = new RegExp('(mobi|tablet|ios).*');
if (ua.match(isMobileRegExp)) {
deviceType = 2;
} else {
deviceType = 1;
}
}
} catch (ex) {}
return deviceType;
}

function getValueForKgpv(bid, adUnitId) {
if (bid.params.regexPattern) {
return bid.params.regexPattern;
Expand Down Expand Up @@ -233,6 +250,7 @@ function executeBidsLoggerCall(e, highestCpmBids) {
outputObj['tst'] = Math.round((new window.Date()).getTime() / 1000);
outputObj['pid'] = '' + profileId;
outputObj['pdvid'] = '' + profileVersionId;
outputObj['dvc'] = {'plt': getDevicePlatform()};
outputObj['tgid'] = (function() {
var testGroupId = parseInt(config.getConfig('testGroupId') || 0);
if (testGroupId <= 15 && testGroupId >= 0) {
Expand Down
6 changes: 3 additions & 3 deletions modules/pubmaticBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Renderer } from '../src/Renderer.js';

const BIDDER_CODE = 'pubmatic';
const LOG_WARN_PREFIX = 'PubMatic: ';
const ENDPOINT = 'https://hbopenbid.pubmatic.com/translator?source=prebid-client';
const ENDPOINT = 'https://hbopenbid.pubmatic.com/translator?source=ow-client';
const USER_SYNC_URL_IFRAME = 'https://ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p=';
const USER_SYNC_URL_IMAGE = 'https://image8.pubmatic.com/AdServer/ImgSync?p=';
const DEFAULT_CURRENCY = 'USD';
Expand Down Expand Up @@ -883,8 +883,8 @@ export const spec = {
utils.logError(`${LOG_WARN_PREFIX}: no context specified in bid. Rejecting bid: `, bid);
return false;
}
if (bid.mediaTypes[VIDEO].context === 'outstream' && !utils.isStr(bid.params.outstreamAU)) {
utils.logError(`${LOG_WARN_PREFIX}: for "outstream" bids outstreamAU is required. Rejecting bid: `, bid);
if (bid.mediaTypes[VIDEO].context === 'outstream' && !utils.isStr(bid.params.outstreamAU) && !bid.hasOwnProperty('renderer')) {
utils.logError(`${LOG_WARN_PREFIX}: for "outstream" bids either outstreamAU parameter must be provided or ad unit supplied renderer is required. Rejecting bid: `, bid);
return false;
}
} else {
Expand Down
149 changes: 135 additions & 14 deletions modules/pubmaticServerBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import * as ajax from '../src/ajax.js';
import {userSync} from '../src/userSync.js';
import { config } from '../src/config.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
const constants = require('../src/constants.json');
const LOG_WARN_PREFIX = 'PubMatic: ';

const BIDDER_CODE = 'pubmaticServer';
const ENDPOINT = 'https://ow.pubmatic.com/openrtb/2.5/';
Expand All @@ -16,6 +18,29 @@ const IMAGE = 'image';
const REDIRECT = 'redirect';
const DEFAULT_VERSION_ID = '0';
const PUBMATIC_DIGITRUST_KEY = 'nFIn8aLzbd';
const DATA_TYPES = {
'NUMBER': 'number',
'STRING': 'string',
'BOOLEAN': 'boolean',
'ARRAY': 'array',
'OBJECT': 'object'
};
const VIDEO_CUSTOM_PARAMS = {
'mimes': DATA_TYPES.ARRAY,
'minduration': DATA_TYPES.NUMBER,
'maxduration': DATA_TYPES.NUMBER,
'startdelay': DATA_TYPES.NUMBER,
'playbackmethod': DATA_TYPES.ARRAY,
'api': DATA_TYPES.ARRAY,
'protocols': DATA_TYPES.ARRAY,
'w': DATA_TYPES.NUMBER,
'h': DATA_TYPES.NUMBER,
'battr': DATA_TYPES.ARRAY,
'linearity': DATA_TYPES.NUMBER,
'placement': DATA_TYPES.NUMBER,
'minbitrate': DATA_TYPES.NUMBER,
'maxbitrate': DATA_TYPES.NUMBER
}

const CUSTOM_PARAMS = {
'kadpageurl': '', // Custom page url
Expand Down Expand Up @@ -127,12 +152,54 @@ function _createOrtbTemplate(conf) {
}

function _createImpressionObject(bid, conf) {
return {
var mediaTypes = '';

var impObj = {
id: bid.bidId,
tagid: bid.params.adUnitId,
bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor),
secure: 1,
banner: {
ext: {
wrapper: {
div: bid.params.divId
},
bidder: {
pubmatic: {
pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid)
}
}
}
};
if (bid.hasOwnProperty('mediaTypes')) {
for (mediaTypes in bid.mediaTypes) {
switch (mediaTypes) {
case BANNER:
var bannerObj = {
pos: 0,
topframe: utils.inIframe() ? 0 : 1,
format: (function() {
let arr = [];
for (let i = 0, l = bid.sizes.length; i < l; i++) {
arr.push({
w: bid.sizes[i][0],
h: bid.sizes[i][1]
});
}
return arr.length > 0 ? arr : UNDEFINED;
})()
}
impObj.banner = bannerObj;
break;
case VIDEO:
var videoObj = _createVideoRequest(bid);
if (videoObj !== UNDEFINED) {
impObj.video = videoObj;
}
break;
}
}
} else {
bannerObj = {
pos: 0,
topframe: utils.inIframe() ? 0 : 1,
format: (function() {
Expand All @@ -145,18 +212,10 @@ function _createImpressionObject(bid, conf) {
}
return arr.length > 0 ? arr : UNDEFINED;
})()
},
ext: {
wrapper: {
div: bid.params.divId
},
bidder: {
pubmatic: {
pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid)
}
}
}
};
impObj.banner = bannerObj;
}
return impObj;
}

function mandatoryParamCheck(paramName, paramValue) {
Expand Down Expand Up @@ -348,9 +407,64 @@ function _handleEids(payload, validBidRequests) {
}
}

function _checkParamDataType(key, value, datatype) {
var errMsg = 'Ignoring param key: ' + key + ', expects ' + datatype + ', found ' + typeof value;
var functionToExecute;
switch (datatype) {
case DATA_TYPES.BOOLEAN:
functionToExecute = utils.isBoolean;
break;
case DATA_TYPES.NUMBER:
functionToExecute = utils.isNumber;
break;
case DATA_TYPES.STRING:
functionToExecute = utils.isStr;
break;
case DATA_TYPES.ARRAY:
functionToExecute = utils.isArray;
break;
}
if (functionToExecute(value)) {
return value;
}
utils.logWarn(LOG_WARN_PREFIX + errMsg);
return UNDEFINED;
}

function _createVideoRequest(bid) {
var videoData = bid.params.video;
var videoObj;

if (videoData !== UNDEFINED) {
videoObj = {};
for (var key in VIDEO_CUSTOM_PARAMS) {
if (videoData.hasOwnProperty(key)) {
videoObj[key] = _checkParamDataType(key, videoData[key], VIDEO_CUSTOM_PARAMS[key]);
}
}
// read playersize and assign to h and w.
if (utils.isArray(bid.mediaTypes.video.playerSize[0])) {
videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0][0], 10);
videoObj.h = parseInt(bid.mediaTypes.video.playerSize[0][1], 10);
} else if (utils.isNumber(bid.mediaTypes.video.playerSize[0])) {
videoObj.w = parseInt(bid.mediaTypes.video.playerSize[0], 10);
videoObj.h = parseInt(bid.mediaTypes.video.playerSize[1], 10);
}
if (bid.params.video.hasOwnProperty('skippable')) {
videoObj.ext = {
'video_skippable': bid.params.video.skippable ? 1 : 0
};
}
} else {
videoObj = UNDEFINED;
utils.logWarn(LOG_WARN_PREFIX + 'Error: Video config params missing for adunit: ' + bid.params.adUnit + ' with mediaType set as video. Ignoring video impression in the adunit.');
}
return videoObj;
}

export const spec = {
code: BIDDER_CODE,

supportedMediaTypes: [BANNER, VIDEO],
/**
* Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid
*
Expand Down Expand Up @@ -517,6 +631,13 @@ export const spec = {
mi: miObj.hasOwnProperty(summary.bidder) ? miObj[summary.bidder] : UNDEFINED,
regexPattern: summary.regex || undefined
}
if (bid.ext.crtype) {
switch (bid.ext.crtype) {
case 'video':
newBid.vastXml = bid.adm;
}
newBid.mediaType = bid.ext.crtype;
}
if (bid.ext.prebid && bid.ext.prebid.targeting) {
newBid.adserverTargeting = bid.ext.prebid.targeting
}
Expand Down
12 changes: 12 additions & 0 deletions test/spec/modules/pubmaticAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ let events = require('src/events');
let ajax = require('src/ajax');
let utils = require('src/utils');

const DEFAULT_USER_AGENT = window.navigator.userAgent;
const MOBILE_USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Mobile/15E148 Safari/604.1';
const setUADefault = () => { window.navigator.__defineGetter__('userAgent', function () { return DEFAULT_USER_AGENT }) };
const setUAMobile = () => { window.navigator.__defineGetter__('userAgent', function () { return MOBILE_USER_AGENT }) };
const setUANull = () => { window.navigator.__defineGetter__('userAgent', function () { return null }) };

const {
EVENTS: {
AUCTION_INIT,
Expand Down Expand Up @@ -247,6 +253,7 @@ describe('pubmatic analytics adapter', function () {
let clock;

beforeEach(function () {
setUADefault();
sandbox = sinon.sandbox.create();

xhr = sandbox.useFakeXMLHttpRequest();
Expand Down Expand Up @@ -643,6 +650,7 @@ describe('pubmatic analytics adapter', function () {
});

it('Logger: currency conversion check', function() {
setUANull();
setConfig({
adServerCurrency: 'JPY',
rates: {
Expand Down Expand Up @@ -695,9 +703,11 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].af).to.equal('banner');
expect(data.s[1].ps[0].ocpm).to.equal(100);
expect(data.s[1].ps[0].ocry).to.equal('JPY');
expect(data.dvc).to.deep.equal({'plt': 3});
});

it('Logger: regexPattern in bid.params', function() {
setUAMobile();
const BID_REQUESTED_COPY = utils.deepClone(MOCK.BID_REQUESTED);
BID_REQUESTED_COPY.bids[1].params.regexPattern = '*';
events.emit(AUCTION_INIT, MOCK.AUCTION_INIT);
Expand Down Expand Up @@ -738,6 +748,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].af).to.equal('banner');
expect(data.s[1].ps[0].ocpm).to.equal(1.52);
expect(data.s[1].ps[0].ocry).to.equal('USD');
expect(data.dvc).to.deep.equal({'plt': 2});
// respective tracker slot
let firstTracker = requests[1].url;
expect(firstTracker.split('?')[0]).to.equal('https://t.pubmatic.com/wt');
Expand Down Expand Up @@ -790,6 +801,7 @@ describe('pubmatic analytics adapter', function () {
expect(data.s[1].ps[0].af).to.equal('banner');
expect(data.s[1].ps[0].ocpm).to.equal(1.52);
expect(data.s[1].ps[0].ocry).to.equal('USD');
expect(data.dvc).to.deep.equal({'plt': 1});
// respective tracker slot
let firstTracker = requests[1].url;
expect(firstTracker.split('?')[0]).to.equal('https://t.pubmatic.com/wt');
Expand Down
49 changes: 48 additions & 1 deletion test/spec/modules/pubmaticServerBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as utils from 'src/utils';
const constants = require('src/constants.json');

describe('PubMaticServer adapter', () => {
let bidRequests;
let bidRequests, videoBidRequests;
let bidResponses;
let errorCodeBidResponses;

Expand Down Expand Up @@ -79,6 +79,37 @@ describe('PubMaticServer adapter', () => {
}
];

videoBidRequests = [{
code: 'video1',
mediaTypes: {
video: {
playerSize: [640, 480],
context: 'instream'
}
},
bidder: 'pubmaticServer',
bidId: '22bddb28db77d',
params: {
publisherId: '5890',
adSlot: 'Div1', // ad_id or tagid
video: {
mimes: ['video/mp4', 'video/x-flv'],
skippable: true,
minduration: 5,
maxduration: 30,
startdelay: 5,
playbackmethod: [1, 3],
api: [1, 2],
protocols: [2, 3],
battr: [13, 14],
linearity: 1,
placement: 2,
minbitrate: 10,
maxbitrate: 10
}
}
}];

bidResponses = {
'body': {
'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865',
Expand Down Expand Up @@ -327,6 +358,22 @@ describe('PubMaticServer adapter', () => {
expect(data.imp[0].banner.format[0].h).to.equal(250); // height from 1st element of sizes array
});

it('request should have video params', () => {
let request = spec.buildRequests(videoBidRequests);
let data = JSON.parse(request.data);
// expect(data.at).to.equal(1); // auction type
expect(data.cur[0]).to.equal('USD'); // currency
expect(data.ext.wrapper.wp).to.equal('pbjs'); // Prebid TransactionId
expect(data.ext.wrapper.wiid).to.equal(videoBidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID
// expect(data.ext.wrapper.profileid).to.equal(parseInt(videoBidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID
// expect(data.ext.wrapper.versionid).to.equal(parseInt(videoBidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID
expect(data.imp[0].id).to.equal(videoBidRequests[0].bidId); // Prebid bid id is passed as id
expect(data.imp[0].tagid).to.equal(videoBidRequests[0].params.adUnitId); // tagid
expect(data.imp[0].video.mimes).to.deep.equal(videoBidRequests[0].params.video.mimes);
expect(data.imp[0].video.minduration).to.equal(videoBidRequests[0].params.video.minduration);
expect(data.imp[0].video.maxduration).to.equal(videoBidRequests[0].params.video.maxduration);
});

it('Request params check with GDPR consent', () => {
let bidRequest = {
gdprConsent: {
Expand Down