Skip to content

Commit

Permalink
PubMatic: Support for Outstream Renderer (BlueBilyWig Renderer) (#5553)
Browse files Browse the repository at this point in the history
* changes to support native in pubmaticbid adapter

* Removed port from endpoint

* Removed protocol from endpoint

* Formatting

* Fix request payload

* Updated test case

* Changed request and response as per ortb spec

* Change in request and response

* Removed comments and extra code

* Code Review comments

* Code Review Comments and Test cases for request and response

* Removed data type as all data asset types are handled

* Code Review Changes

* Code Review Comments

* Supporting both banner and native and sending 0x0 in case of native

* Bug Fixes

* Bug response not processed by prebid

* Change warning message

* Fixed typo

* Do not send request in case of invalid native bid

* Do not send request in case of invalid native requests

* objects converted to strings in log for debug purposes

* Fixed logic to check for required parmas

* Fixed typo for stringify

* documentation for native

* Review comments from Prebid

* Typo

* Typo

* Updated pub id for native

* Code Review

* Support for pubid

* Test Cases for PubCommonId in PubMatic adapter

* Delete yarn.lock

* Rename adaptermanager.js to adapterManager.js

* Rename yieldNexusBidAdapter.js to yieldnexusBidAdapter.js

* Rename yieldNexusBidAdapter.md to yieldnexusBidAdapter.md

* Rename yieldNexusBidAdapter_spec.js to yieldnexusBidAdapter_spec.yieldnexusBidAdaptera

* Rename yieldnexusBidAdapter_spec.yieldnexusBidAdaptera to yieldnexusBidAdapter_spec.js

* bluebillywig outstream player support in pubmatic adapter

* removed pubcommon id test cases

* BBW Renderer
  • Loading branch information
pm-shashank-jain authored Aug 14, 2020
1 parent 7ede93b commit db02d8a
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 5 deletions.
91 changes: 90 additions & 1 deletion modules/pubmaticBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as utils from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js';
import {config} from '../src/config.js';
import { Renderer } from '../src/Renderer.js';

const BIDDER_CODE = 'pubmatic';
const LOG_WARN_PREFIX = 'PubMatic: ';
Expand All @@ -14,6 +15,8 @@ const UNDEFINED = undefined;
const DEFAULT_WIDTH = 0;
const DEFAULT_HEIGHT = 0;
const PREBID_NATIVE_HELP_LINK = 'http://prebid.org/dev-docs/show-native-ads.html';
const PUBLICATION = 'pubmatic'; // Your publication on Blue Billywig, potentially with environment (e.g. publication.bbvms.com or publication.test.bbvms.com)
const RENDERER_URL = 'https://pubmatic.bbvms.com/r/'.concat('$RENDERER', '.js'); // URL of the renderer application
const CUSTOM_PARAMS = {
'kadpageurl': '', // Custom page url
'gender': '', // User gender
Expand Down Expand Up @@ -104,6 +107,60 @@ const dealChannelValues = {
5: 'PREF',
6: 'PMPG'
};
// BB stands for Blue BillyWig
const BB_RENDERER = {
bootstrapPlayer: function(bid) {
const config = {
code: bid.adUnitCode,
};

if (bid.vastXml) config.vastXml = bid.vastXml;
else if (bid.vastUrl) config.vastUrl = bid.vastUrl;

if (!bid.vastXml && !bid.vastUrl) {
utils.logWarn(`${LOG_WARN_PREFIX}: No vastXml or vastUrl on bid, bailing...`);
return;
}

const rendererId = BB_RENDERER.getRendererId(PUBLICATION, bid.rendererCode);

const ele = document.getElementById(bid.adUnitCode); // NB convention

let renderer;

for (let rendererIndex = 0; rendererIndex < window.bluebillywig.renderers.length; rendererIndex++) {
if (window.bluebillywig.renderers[rendererIndex]._id === rendererId) {
renderer = window.bluebillywig.renderers[rendererIndex];
break;
}
}

if (renderer) renderer.bootstrap(config, ele);
else utils.logWarn(`${LOG_WARN_PREFIX}: Couldn't find a renderer with ${rendererId}`);
},
newRenderer: function(rendererCode, adUnitCode) {
var rendererUrl = RENDERER_URL.replace('$RENDERER', rendererCode);
const renderer = Renderer.install({
url: rendererUrl,
loaded: false,
adUnitCode
});

try {
renderer.setRender(BB_RENDERER.outstreamRender);
} catch (err) {
utils.logWarn(`${LOG_WARN_PREFIX}: Error tying to setRender on renderer`, err);
}

return renderer;
},
outstreamRender: function(bid) {
bid.renderer.push(function() { BB_RENDERER.bootstrapPlayer(bid) });
},
getRendererId: function(pub, renderer) {
return `${pub}-${renderer}`; // NB convention!
}
};

let publisherId = 0;
let isInvalidNativeRequest = false;
Expand Down Expand Up @@ -760,6 +817,23 @@ function _handleDealCustomTargetings(payload, dctrArr, validBidRequests) {
}
}

function _assignRenderer(newBid, request) {
let bidParams, context, adUnitCode;
if (request.bidderRequest && request.bidderRequest.bids) {
for (let bidderRequestBidsIndex = 0; bidderRequestBidsIndex < request.bidderRequest.bids.length; bidderRequestBidsIndex++) {
if (request.bidderRequest.bids[bidderRequestBidsIndex].bidId === newBid.requestId) {
bidParams = request.bidderRequest.bids[bidderRequestBidsIndex].params;
context = request.bidderRequest.bids[bidderRequestBidsIndex].mediaTypes[VIDEO].context;
adUnitCode = request.bidderRequest.bids[bidderRequestBidsIndex].adUnitCode;
}
}
if (context && context === 'outstream' && bidParams && bidParams.outstreamAU && adUnitCode) {
newBid.rendererCode = bidParams.outstreamAU;
newBid.renderer = BB_RENDERER.newRenderer(newBid.rendererCode, adUnitCode);
}
}
};

export const spec = {
code: BIDDER_CODE,
gvlid: 76,
Expand All @@ -782,6 +856,19 @@ export const spec = {
utils.logWarn(LOG_WARN_PREFIX + 'Error: For video ads, mimes is mandatory and must specify atlease 1 mime value. Call to OpenBid will not be sent for ad unit:' + JSON.stringify(bid));
return false;
}
if (bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty(VIDEO)) {
if (!bid.mediaTypes[VIDEO].hasOwnProperty('context')) {
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);
return false;
}
} else {
utils.logError(`${LOG_WARN_PREFIX}: mediaTypes or mediaTypes.video is not specified. Rejecting bid: `, bid);
return false;
}
}
return true;
}
Expand Down Expand Up @@ -926,7 +1013,8 @@ export const spec = {
return {
method: 'POST',
url: ENDPOINT,
data: JSON.stringify(payload)
data: JSON.stringify(payload),
bidderRequest: bidderRequest
};
},

Expand Down Expand Up @@ -976,6 +1064,7 @@ export const spec = {
newBid.width = bid.hasOwnProperty('w') ? bid.w : req.video.w;
newBid.height = bid.hasOwnProperty('h') ? bid.h : req.video.h;
newBid.vastXml = bid.adm;
_assignRenderer(newBid, request);
break;
case NATIVE:
_parseNativeResponse(bid, newBid);
Expand Down
1 change: 1 addition & 0 deletions modules/pubmaticBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ var adUnits = [
bidder: 'pubmatic',
params: {
publisherId: '156209', // required
oustreamAU: 'renderer_test_pubmatic', // required if mediaTypes-> video-> context is 'outstream'. This value can be get by BlueBillyWig Team.
adSlot: 'pubmatic_test2', // optional
pmzoneid: 'zone1, zone11', // optional
lat: '40.712775', // optional
Expand Down
132 changes: 128 additions & 4 deletions test/spec/modules/pubmaticBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ describe('PubMatic adapter', function () {
let bannerBidResponse;
let videoBidResponse;
let schainConfig;
let outstreamBidRequest;
let validOutstreamBidRequest;
let outstreamVideoBidResponse;

beforeEach(function () {
schainConfig = {
Expand Down Expand Up @@ -55,7 +58,7 @@ describe('PubMatic adapter', function () {
}
},
params: {
publisherId: '301',
publisherId: '5670',
adSlot: '/15671365/DMDemo@300x250:0',
kadfloor: '1.2',
pmzoneid: 'aabc, ddef',
Expand Down Expand Up @@ -656,7 +659,89 @@ describe('PubMatic adapter', function () {
}]
}]
}
}
};
outstreamBidRequest =
[
{
code: 'video1',
mediaTypes: {
video: {
playerSize: [640, 480],
context: 'outstream'
}
},
bidder: 'pubmatic',
bidId: '47acc48ad47af5',
requestId: '0fb4905b-1234-4152-86be-c6f6d259ba99',
bidderRequestId: '1c56ad30b9b8ca8',
transactionId: '92489f71-1bf2-49a0-adf9-000cea934729',
params: {
publisherId: '5670',
outstreamAU: 'pubmatic-test',
adSlot: 'Div1@0x0', // ad_id or tagid
video: {
mimes: ['video/mp4', 'video/x-flv'],
skippable: true,
minduration: 5,
maxduration: 30
}
}
}
];

validOutstreamBidRequest = {
auctionId: '92489f71-1bf2-49a0-adf9-000cea934729',
auctionStart: 1585918458868,
bidderCode: 'pubmatic',
bidderRequestId: '47acc48ad47af5',
bids: [{
adUnitCode: 'video1',
auctionId: '92489f71-1bf2-49a0-adf9-000cea934729',
bidId: '47acc48ad47af5',
bidRequestsCount: 1,
bidder: 'pubmatic',
bidderRequestId: '47acc48ad47af5',
mediaTypes: {
video: {
context: 'outstream'
}
},
params: {
publisherId: '5670',
outstreamAU: 'pubmatic-test',
adSlot: 'Div1@0x0', // ad_id or tagid
video: {
mimes: ['video/mp4', 'video/x-flv'],
skippable: true,
minduration: 5,
maxduration: 30
}
},
sizes: [[768, 432], [640, 480], [630, 360]],
transactionId: '92489f71-1bf2-49a0-adf9-000cea934729'
}],
start: 11585918458869,
timeout: 3000
};

outstreamVideoBidResponse = {
'body': {
'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865',
'seatbid': [{
'bid': [{
'id': '0fb4905b-1234-4152-86be-c6f6d259ba99',
'impid': '47acc48ad47af5',
'price': 1.3,
'adm': '<VAST version="3.0"><Ad id="601364"><InLine><AdSystem>Acudeo Compatible</AdSystem><AdTitle>VAST 2.0 Instream Test 1</AdTitle><Description>VAST 2.0 Instream Test 1</Description><Impression><![CDATA[http://172.16.4.213/AdServer/AdDisplayTrackerServlet?operId=1&pubId=5890&siteId=47163&adId=1405268&adType=13&adServerId=243&kefact=70.000000&kaxefact=70.000000&kadNetFrequecy=0&kadwidth=0&kadheight=0&kadsizeid=97&kltstamp=1529929473&indirectAdId=0&adServerOptimizerId=2&ranreq=0.1&kpbmtpfact=100.000000&dcId=1&tldId=0&passback=0&svr=MADS1107&ekefact=Ad8wW91TCwCmdG0jlfjXn7Tyzh20hnTVx-m5DoNSep-RXGDr&ekaxefact=Ad8wWwRUCwAGir4Zzl1eF0bKiC-qrCV0D0yp_eE7YizB_BQk&ekpbmtpfact=Ad8wWxRUCwD7qgzwwPE2LnS5-Ou19uO5amJl1YT6-XVFvQ41&imprId=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&oid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&crID=creative-1_1_2&ucrid=160175026529250297&campaignId=17050&creativeId=0&pctr=0.000000&wDSPByrId=511&wDspId=6&wbId=0&wrId=0&wAdvID=3170&isRTB=1&rtbId=EBCA079F-8D7C-45B8-B733-92951F670AA1&pmZoneId=zone1&pageURL=www.yahoo.com&lpu=ae.com]]></Impression><Impression>https://dsptracker.com/{PSPM}</Impression><Error><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&er=[ERRORCODE]]]></Error><Error><![CDATA[https://Errortrack.com?p=1234&er=[ERRORCODE]]]></Error><Creatives><Creative AdID="601364"><Linear skipoffset="20%"><TrackingEvents><Tracking event="close"><![CDATA[https://mytracking.com/linear/close]]></Tracking><Tracking event="skip"><![CDATA[https://mytracking.com/linear/skip]]></Tracking><Tracking event="creativeView"><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&e=1]]></Tracking><Tracking event="start"><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&e=2]]></Tracking><Tracking event="midpoint"><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&e=3]]></Tracking><Tracking event="firstQuartile"><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&e=4]]></Tracking><Tracking event="thirdQuartile"><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&e=5]]></Tracking><Tracking event="complete"><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&e=6]]></Tracking></TrackingEvents><Duration>00:00:04</Duration><VideoClicks><ClickTracking><![CDATA[http://172.16.4.213/track?operId=7&p=5890&s=47163&a=1405268&wa=243&ts=1529929473&wc=17050&crId=creative-1_1_2&ucrid=160175026529250297&impid=48F73E1A-7F23-443D-A53C-30EE6BBF5F7F&advertiser_id=3170&ecpm=70.000000&e=99]]></ClickTracking><ClickThrough>https://www.pubmatic.com</ClickThrough></VideoClicks><MediaFiles><MediaFile delivery="progressive" type="video/mp4" bitrate="500" width="400" height="300" scalable="true" maintainAspectRatio="true"><![CDATA[https://stagingnyc.pubmatic.com:8443/video/Shashank/mediaFileHost/media/mp4-sample-2.mp4]]></MediaFile></MediaFiles></Linear></Creative></Creatives></InLine></Ad></VAST>',
'h': 250,
'w': 300,
'ext': {
'deal_channel': 6
}
}]
}]
}
};
});

describe('implementation', function () {
Expand Down Expand Up @@ -725,7 +810,17 @@ describe('PubMatic adapter', function () {
let request = spec.buildRequests(bidRequests);
expect(request.url).to.equal('https://hbopenbid.pubmatic.com/translator?source=prebid-client');
expect(request.method).to.equal('POST');
});
});

it('should return bidderRequest property', function() {
let request = spec.buildRequests(bidRequests, validOutstreamBidRequest);
expect(request.bidderRequest).to.equal(validOutstreamBidRequest);
});

it('bidderRequest should be undefined if bidderRequest is not present', function() {
let request = spec.buildRequests(bidRequests);
expect(request.bidderRequest).to.be.undefined;
});

it('test flag not sent when pubmaticTest=true is absent in page url', function() {
let request = spec.buildRequests(bidRequests);
Expand Down Expand Up @@ -2454,7 +2549,6 @@ describe('PubMatic adapter', function () {
it('should check for valid video mediaType in case of multiformat request', function() {
let request = spec.buildRequests(videoBidRequests);
let response = spec.interpretResponse(videoBidResponse, request);

expect(response[0].mediaType).to.equal('video');
});

Expand All @@ -2464,6 +2558,36 @@ describe('PubMatic adapter', function () {

expect(response[0].mediaType).to.equal('native');
});

it('should assign renderer if bid is video and request is for outstream', function() {
let request = spec.buildRequests(outstreamBidRequest, validOutstreamBidRequest);
let response = spec.interpretResponse(outstreamVideoBidResponse, request);
expect(response[0].renderer).to.exist;
});

it('should not assign renderer if bidderRequest is not present', function() {
let request = spec.buildRequests(outstreamBidRequest);
let response = spec.interpretResponse(outstreamVideoBidResponse, request);
expect(response[0].renderer).to.not.exist;
});

it('should not assign renderer if bid is video and request is for instream', function() {
let request = spec.buildRequests(videoBidRequests);
let response = spec.interpretResponse(videoBidResponse, request);
expect(response[0].renderer).to.not.exist;
});

it('should not assign renderer if bid is native', function() {
let request = spec.buildRequests(nativeBidRequests);
let response = spec.interpretResponse(nativeBidResponse, request);
expect(response[0].renderer).to.not.exist;
});

it('should not assign renderer if bid is of banner', function() {
let request = spec.buildRequests(bidRequests);
let response = spec.interpretResponse(bidResponses, request);
expect(response[0].renderer).to.not.exist;
});
});

describe('getUserSyncs', function() {
Expand Down

0 comments on commit db02d8a

Please sign in to comment.