Skip to content

Commit

Permalink
Synacormedia: Added video support to adapter. (prebid#3695)
Browse files Browse the repository at this point in the history
* Synacormedia: Added video support to adapter.
Added playerSize to video test page.

* Synacormedia: Updated test case for IE/Edge

* Synacormedia: Updates based on PR review
  • Loading branch information
amuraco authored and Isaac Dettman committed Apr 22, 2019
1 parent 71d5753 commit 1ef6197
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 57 deletions.
83 changes: 53 additions & 30 deletions modules/synacormediaBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@

import { getAdUnitSizes, logWarn } from '../src/utils';
import { registerBidder } from '../src/adapters/bidderFactory';
import { BANNER } from '../src/mediaTypes';
import { BANNER, VIDEO } from '../src/mediaTypes';
import includes from 'core-js/library/fn/array/includes';

const BID_HOST = '//prebid.technoratimedia.com';
const USER_SYNC_HOST = '//ad-cdn.technoratimedia.com';
const VIDEO_PARAMS = [ 'minduration', 'maxduration' ];

export const spec = {
code: 'synacormedia',
supportedMediaTypes: [ BANNER ],
supportedMediaTypes: [ BANNER, VIDEO ],
sizeMap: {},

isVideoBid: function(bid) {
return bid.mediaTypes !== undefined &&
bid.mediaTypes.hasOwnProperty('video');
},
isBidRequestValid: function(bid) {
return !!(bid && bid.params && bid.params.placementId && bid.params.seatId);
},

buildRequests: function(validBidReqs, bidderRequest) {
if (!validBidReqs || !validBidReqs.length || !bidderRequest) {
return;
Expand Down Expand Up @@ -49,20 +57,33 @@ export const spec = {
logWarn(`Synacormedia: there is an invalid POS: ${bid.params.pos}`);
pos = 0;
}
let videoOrBannerKey = this.isVideoBid(bid) ? 'video' : 'banner';
getAdUnitSizes(bid).forEach((size, i) => {
let request = {
id: bid.bidId + '~' + size[0] + 'x' + size[1],
tagid: placementId,
banner: {
w: size[0],
h: size[1],
pos
}
if (!size || size.length != 2) {
return;
}
let size0 = size[0];
let size1 = size[1];
let imp = {
id: `${videoOrBannerKey.substring(0, 1)}${bid.bidId}-${size0}x${size1}`,
tagid: placementId
};
if (bidFloor !== null && !isNaN(bidFloor)) {
request.bidfloor = bidFloor;
imp.bidfloor = bidFloor;
}

let videoOrBannerValue = {
w: size0,
h: size1,
pos
};
if (videoOrBannerKey === 'video' && bid.params.video) {
Object.keys(bid.params.video)
.filter(param => includes(VIDEO_PARAMS, param) && !isNaN(parseInt(bid.params.video[param], 10)))
.forEach(param => videoOrBannerValue[param] = parseInt(bid.params.video[param], 10));
}
openRtbBidRequest.imp.push(request);
imp[videoOrBannerKey] = videoOrBannerValue;
openRtbBidRequest.imp.push(imp);
});
});

Expand All @@ -79,41 +100,43 @@ export const spec = {
}
},
interpretResponse: function(serverResponse) {
var updateMacros = (bid, r) => {
return r ? r.replace(/\${AUCTION_PRICE}/g, bid.price) : r;
};

if (!serverResponse.body || typeof serverResponse.body != 'object') {
logWarn('Synacormedia: server returned empty/non-json response: ' + JSON.stringify(serverResponse.body));
return;
}

const {id, seatbid: seatbids} = serverResponse.body;
let bids = [];
if (id && seatbids) {
seatbids.forEach(seatbid => {
seatbid.bid.forEach(bid => {
let price = parseFloat(bid.price);
let creative = bid.adm.replace(/\${([^}]*)}/g, (match, key) => {
switch (key) {
case 'AUCTION_SEAT_ID': return seatbid.seat;
case 'AUCTION_ID': return id;
case 'AUCTION_BID_ID': return bid.id;
case 'AUCTION_IMP_ID': return bid.impid;
case 'AUCTION_PRICE': return price;
case 'AUCTION_CURRENCY': return 'USD';
}
return match;
});
let [, impid, width, height] = bid.impid.match(/^(.*)~(.*)x(.*)$/);
bids.push({
let creative = updateMacros(bid, bid.adm);
let nurl = updateMacros(bid, bid.nurl);
let [, impType, impid, width, height] = bid.impid.match(/^([vb])(.*)-(.*)x(.*)$/);
let isVideo = impType == 'v';
let bidObj = {
requestId: impid,
adId: bid.id.replace(/~/g, '-'),
cpm: price,
cpm: parseFloat(bid.price),
width: parseInt(width, 10),
height: parseInt(height, 10),
creativeId: seatbid.seat + '~' + bid.crid,
creativeId: `${seatbid.seat}_${bid.crid}`,
currency: 'USD',
netRevenue: true,
mediaType: BANNER,
mediaType: isVideo ? VIDEO : BANNER,
ad: creative,
ttl: 60
});
};
if (isVideo) {
let [, uuid] = nurl.match(/ID=([^&]*)&?/);
bidObj.videoCacheKey = encodeURIComponent(uuid);
bidObj.vastUrl = nurl;
}
bids.push(bidObj);
});
});
}
Expand Down
32 changes: 24 additions & 8 deletions modules/synacormediaBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@ Maintainer: eng-demand@synacor.com
The Synacor Media adapter requires setup and approval from Synacor.
Please reach out to your account manager for more information.

### DFP Video Creative
To use video, setup a `VAST redirect` creative within Google AdManager (DFP) with the following VAST tag URL:

```
https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_cache_id_synacorm%%&AUCTION_PRICE=%%PATTERN:hb_pb_synacormedia%%
```

# Test Parameters

## Web
Expand All @@ -24,23 +31,32 @@ Please reach out to your account manager for more information.
bidder: "synacormedia",
params: {
seatId: "prebid",
placementId: "81416",
bidfloor: "0.10",
placementId: "demo1",
bidfloor: 0.10,
pos: 1
}
}]
},{
code: 'test-div2',
sizes: [
[300, 250]
],
mediaType: {
video: {
context: 'instream',
playerSizes: [
[300, 250]
],
}
},
bids: [{
bidder: "synacormedia",
params: {
seatId: "prebid",
placementId: "demo2"
bidfloor: "0.10",
pos: 1
placementId: "demo1"
bidfloor: 0.20,
pos: 1,
video: {
minduration: 15,
maxduration: 30
}
}
}]
}];
Expand Down
2 changes: 1 addition & 1 deletion test/pages/video.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
code: 'video1',
sizes: [640,480],
mediaTypes: {
video: {context: 'instream'}
video: {context: 'instream', playerSize: [640, 480]}
},
bids: [
{
Expand Down
Loading

0 comments on commit 1ef6197

Please sign in to comment.