Skip to content

Commit

Permalink
TargetVideo Bid Adapter : add video support (prebid#11867)
Browse files Browse the repository at this point in the history
* Add video support

* Refactor code to library

* Fix lint errors

* Fix code duplication

* Fix lint errors

---------

Co-authored-by: Danijel Ristic <[email protected]>
  • Loading branch information
2 people authored and DecayConstant committed Jul 18, 2024
1 parent 04fc9ee commit de92f66
Show file tree
Hide file tree
Showing 7 changed files with 501 additions and 240 deletions.
178 changes: 178 additions & 0 deletions libraries/targetVideoUtils/bidderUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import {VIDEO} from '../../src/mediaTypes.js';
import {getRefererInfo} from '../../src/refererDetection.js';
import {createTrackPixelHtml, deepAccess, getBidRequest} from '../../src/utils.js';

export function getSizes(request) {
let sizes = request.sizes;
if (!sizes && request.mediaTypes && request.mediaTypes.banner && request.mediaTypes.banner.sizes) {
sizes = request.mediaTypes.banner.sizes;
}
if (Array.isArray(sizes) && !Array.isArray(sizes[0])) {
sizes = [sizes[0], sizes[1]];
}
if (!Array.isArray(sizes) || !Array.isArray(sizes[0])) {
sizes = [[0, 0]];
}

return sizes;
}

export function formatRequest({payload, url, bidderRequest, bidId}) {
const request = {
method: 'POST',
data: JSON.stringify(payload),
url,
options: {
withCredentials: true,
}
}

if (bidderRequest) {
request.bidderRequest = bidderRequest;
}

if (bidId) {
request.bidId = bidId;
}

return request;
}

export function createVideoTag(bid) {
const tag = {};
tag.id = parseInt(bid.params.placementId, 10);
tag.gpid = 'targetVideo';
tag.sizes = getSizes(bid);
tag.primary_size = tag.sizes[0];
tag.ad_types = [VIDEO];
tag.uuid = bid.bidId;
tag.allow_smaller_sizes = false;
tag.use_pmt_rule = false;
tag.prebid = true;
tag.disable_psa = true;
tag.hb_source = 1;
tag.require_asset_url = true;
tag.video = {
playback_method: 2,
skippable: true
};

return tag;
}

export function bannerBid(serverBid, rtbBid, bidderRequest, margin) {
const bidRequest = getBidRequest(serverBid.uuid, [bidderRequest]);
const sizes = getSizes(bidRequest);
const bid = {
requestId: serverBid.uuid,
cpm: rtbBid.cpm / margin,
creativeId: rtbBid.creative_id,
dealId: rtbBid.deal_id,
currency: 'USD',
netRevenue: true,
width: sizes[0][0],
height: sizes[0][1],
ttl: 300,
adUnitCode: bidRequest.adUnitCode,
appnexus: {
buyerMemberId: rtbBid.buyer_member_id,
dealPriority: rtbBid.deal_priority,
dealCode: rtbBid.deal_code
}
};

if (rtbBid.rtb.video) {
Object.assign(bid, {
vastImpUrl: rtbBid.notify_url,
ad: getBannerHtml(rtbBid.notify_url + '&redir=' + encodeURIComponent(rtbBid.rtb.video.asset_url)),
ttl: 3600
});
}

return bid;
}

export function videoBid(serverBid, requestId, currency, params, ttl) {
const {ad, adUrl, vastUrl, vastXml} = getAd(serverBid);

const bid = {
requestId,
params,
currency,
cpm: serverBid.price,
width: serverBid.w,
height: serverBid.h,
creativeId: serverBid.adid || serverBid.crid,
netRevenue: false,
ttl,
meta: {
advertiserDomains: serverBid.adomain || []
}
};

if (vastUrl || vastXml) {
bid.mediaType = VIDEO;
if (vastUrl) bid.vastUrl = vastUrl;
if (vastXml) bid.vastXml = vastXml;
} else {
bid.ad = ad;
bid.adUrl = adUrl;
};

return bid;
}

export function getRtbBid(tag) {
return tag && tag.ads && tag.ads.length && tag.ads.find(ad => ad.rtb);
}

export function getBannerHtml(vastUrl) {
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>html, body {width: 100%; height: 100%; margin: 0;}</style>
</head>
<body>
<div id="targetVideoPlayer"></div>
<script src="https://player.target-video.com/custom/targetvideo-banner.js"></script>
<script>initPlayer("${vastUrl}");</script>
</body>
</html>`;
}

export function getAd(bid) {
let ad, adUrl, vastXml, vastUrl;

switch (deepAccess(bid, 'ext.prebid.type')) {
case VIDEO:
if (bid.adm.substr(0, 4) === 'http') {
vastUrl = bid.adm;
} else {
vastXml = bid.adm;
};
break;
default:
if (bid.adm && bid.nurl) {
ad = bid.adm;
ad += createTrackPixelHtml(decodeURIComponent(bid.nurl));
} else if (bid.adm) {
ad = bid.adm;
} else if (bid.nurl) {
adUrl = bid.nurl;
};
}

return {ad, adUrl, vastXml, vastUrl};
}

export function getSiteObj() {
const refInfo = (getRefererInfo && getRefererInfo()) || {};

return {
page: refInfo.page,
ref: refInfo.ref,
domain: refInfo.domain
}
}
23 changes: 23 additions & 0 deletions libraries/targetVideoUtils/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const SOURCE = 'pbjs';
const GVLID = 786;
const MARGIN = 1.35;
const BIDDER_CODE = 'targetVideo';

const TIME_TO_LIVE = 300;
const BANNER_ENDPOINT_URL = 'https://ib.adnxs.com/ut/v3/prebid';
const VIDEO_ENDPOINT_URL = 'https://pbs.prebrid.tv/openrtb2/auction';
const VIDEO_PARAMS = [
'api', 'linearity', 'maxduration', 'mimes', 'minduration',
'plcmt', 'playbackmethod', 'protocols', 'startdelay'
];

export {
SOURCE,
GVLID,
MARGIN,
BIDDER_CODE,
TIME_TO_LIVE,
BANNER_ENDPOINT_URL,
VIDEO_ENDPOINT_URL,
VIDEO_PARAMS
}
94 changes: 47 additions & 47 deletions modules/bridBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {createTrackPixelHtml, _each, deepAccess, getDefinedParams, parseGPTSingleSizeArrayToRtbSize} from '../src/utils.js';
import {_each, deepAccess, getDefinedParams, parseGPTSingleSizeArrayToRtbSize} from '../src/utils.js';
import {VIDEO} from '../src/mediaTypes.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {getRefererInfo} from '../src/refererDetection.js';
import {getAd, getSiteObj} from '../libraries/targetVideoUtils/bidderUtils.js'

/**
* @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest
Expand Down Expand Up @@ -180,50 +180,50 @@ export const spec = {

}

/**
* Helper function to get ad
*
* @param {object} bid The bid.
* @return {object} ad object.
*/
function getAd(bid) {
let ad, adUrl, vastXml, vastUrl;

switch (deepAccess(bid, 'ext.prebid.type')) {
case VIDEO:
if (bid.adm.substr(0, 4) === 'http') {
vastUrl = bid.adm;
} else {
vastXml = bid.adm;
};
break;
default:
if (bid.adm && bid.nurl) {
ad = bid.adm;
ad += createTrackPixelHtml(decodeURIComponent(bid.nurl));
} else if (bid.adm) {
ad = bid.adm;
} else if (bid.nurl) {
adUrl = bid.nurl;
};
}

return {ad, adUrl, vastXml, vastUrl};
}

/**
* Helper function to get site object
*
* @return {object} siteObj.
*/
function getSiteObj() {
const refInfo = (getRefererInfo && getRefererInfo()) || {};

return {
page: refInfo.page,
ref: refInfo.ref,
domain: refInfo.domain
};
}
// /**
// * Helper function to get ad
// *
// * @param {object} bid The bid.
// * @return {object} ad object.
// */
// function getAd(bid) {
// let ad, adUrl, vastXml, vastUrl;

// switch (deepAccess(bid, 'ext.prebid.type')) {
// case VIDEO:
// if (bid.adm.substr(0, 4) === 'http') {
// vastUrl = bid.adm;
// } else {
// vastXml = bid.adm;
// };
// break;
// default:
// if (bid.adm && bid.nurl) {
// ad = bid.adm;
// ad += createTrackPixelHtml(decodeURIComponent(bid.nurl));
// } else if (bid.adm) {
// ad = bid.adm;
// } else if (bid.nurl) {
// adUrl = bid.nurl;
// };
// }

// return {ad, adUrl, vastXml, vastUrl};
// }

// /**
// * Helper function to get site object
// *
// * @return {object} siteObj.
// */
// function getSiteObj() {
// const refInfo = (getRefererInfo && getRefererInfo()) || {};

// return {
// page: refInfo.page,
// ref: refInfo.ref,
// domain: refInfo.domain
// };
// }

registerBidder(spec);
28 changes: 1 addition & 27 deletions modules/nextMillenniumBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {
_each,
createTrackPixelHtml,
deepAccess,
deepSetValue,
getBidIdParameter,
Expand All @@ -12,6 +11,7 @@ import {
parseUrl,
triggerPixel,
} from '../src/utils.js';
import {getAd} from '../libraries/targetVideoUtils/bidderUtils.js';

import {getGlobal} from '../src/prebidGlobal.js';
import { EVENTS } from '../src/constants.js';
Expand Down Expand Up @@ -455,32 +455,6 @@ function getTopWindow(curWindow, nesting = 0) {
};
}

function getAd(bid) {
let ad, adUrl, vastXml, vastUrl;

switch (deepAccess(bid, 'ext.prebid.type')) {
case VIDEO:
if (bid.adm.substr(0, 4) === 'http') {
vastUrl = bid.adm;
} else {
vastXml = bid.adm;
};

break;
default:
if (bid.adm && bid.nurl) {
ad = bid.adm;
ad += createTrackPixelHtml(decodeURIComponent(bid.nurl));
} else if (bid.adm) {
ad = bid.adm;
} else if (bid.nurl) {
adUrl = bid.nurl;
};
};

return {ad, adUrl, vastXml, vastUrl};
}

function getSiteObj() {
const refInfo = (getRefererInfo && getRefererInfo()) || {};

Expand Down
Loading

0 comments on commit de92f66

Please sign in to comment.