Skip to content

Commit

Permalink
Adtelligent new features (#5203)
Browse files Browse the repository at this point in the history
* Adtelligent support adpods

* Adtelligent support bid chunks

* Adtelligent support userId, schain

* Adtelligent Rename params to be supported in post

* Coppa support

* Rewritten tests

* Add param transform for aid for ServerAdapter

* Lint
  • Loading branch information
GeneGenie authored May 27, 2020
1 parent f4dc9c4 commit efcba5a
Show file tree
Hide file tree
Showing 2 changed files with 322 additions and 197 deletions.
168 changes: 104 additions & 64 deletions modules/adtelligentBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import * as utils from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {VIDEO, BANNER} from '../src/mediaTypes.js';
import {Renderer} from '../src/Renderer.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { ADPOD, BANNER, VIDEO } from '../src/mediaTypes.js';
import { config } from '../src/config.js';
import { Renderer } from '../src/Renderer.js';
import find from 'core-js-pure/features/array/find.js';

const URL = 'https://ghb.adtelligent.com/auction/';
const subdomainSuffixes = ['', 1, 2];
const getUri = (function () {
let num = 0;
return function () {
return 'https://ghb' + subdomainSuffixes[num++ % subdomainSuffixes.length] + '.adtelligent.com/v2/auction/'
}
}())
const OUTSTREAM_SRC = 'https://player.adtelligent.com/outstream-unit/2.01/outstream.min.js';
const BIDDER_CODE = 'adtelligent';
const OUTSTREAM = 'outstream';
Expand All @@ -30,8 +37,8 @@ export const spec = {
uris.forEach((uri, i) => {
const type = types[i] || 'image';

if ((!syncOptions.pixelEnabled && type == 'image') ||
(!syncOptions.iframeEnabled && type == 'iframe') ||
if ((!syncOptions.pixelEnabled && type === 'image') ||
(!syncOptions.iframeEnabled && type === 'iframe') ||
syncsCache[uri]) {
return;
}
Expand Down Expand Up @@ -63,15 +70,21 @@ export const spec = {
/**
* Make a server request from the list of BidRequests
* @param bidRequests
* @param bidderRequest
* @param adapterRequest
*/
buildRequests: function (bidRequests, bidderRequest) {
return {
data: bidToTag(bidRequests, bidderRequest),
bidderRequest,
method: 'GET',
url: URL
};
buildRequests: function (bidRequests, adapterRequest) {
const adapterSettings = config.getConfig(adapterRequest.bidderCode)
const chunkSize = utils.deepAccess(adapterSettings, 'chunkSize', 10);
const { tag, bids } = bidToTag(bidRequests, adapterRequest);
const bidChunks = utils.chunk(bids, chunkSize);
return utils._map(bidChunks, (bids) => {
return {
data: Object.assign({}, tag, { BidRequests: bids }),
adapterRequest,
method: 'POST',
url: getUri()
};
})
},

/**
Expand All @@ -80,43 +93,43 @@ export const spec = {
* @param bidderRequest
* @return {Bid[]} An array of bids which were nested inside the server
*/
interpretResponse: function (serverResponse, {bidderRequest}) {
interpretResponse: function (serverResponse, { adapterRequest }) {
serverResponse = serverResponse.body;
let bids = [];

if (!utils.isArray(serverResponse)) {
return parseRTBResponse(serverResponse, bidderRequest);
return parseRTBResponse(serverResponse, adapterRequest);
}

serverResponse.forEach(serverBidResponse => {
bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, bidderRequest));
bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, adapterRequest));
});

return bids;
},

transformBidParams(params) {
return utils.convertTypes({
'aid': 'number',
}, params);
}
};

function parseRTBResponse(serverResponse, bidderRequest) {
const isInvalidValidResp = !serverResponse || !utils.isArray(serverResponse.bids);

function parseRTBResponse(serverResponse, adapterRequest) {
const isEmptyResponse = !serverResponse || !utils.isArray(serverResponse.bids);
const bids = [];

if (isInvalidValidResp) {
const extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : '';
const errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`;

utils.logError(errorMessage);

if (isEmptyResponse) {
return bids;
}

serverResponse.bids.forEach(serverBid => {
const request = find(bidderRequest.bids, (bidRequest) => {
const request = find(adapterRequest.bids, (bidRequest) => {
return bidRequest.bidId === serverBid.requestId;
});

if (serverBid.cpm !== 0 && request !== undefined) {
const bid = createBid(serverBid, getMediaType(request));
const bid = createBid(serverBid, request);

bids.push(bid);
}
Expand All @@ -125,43 +138,59 @@ function parseRTBResponse(serverResponse, bidderRequest) {
return bids;
}

function bidToTag(bidRequests, bidderRequest) {
function bidToTag(bidRequests, adapterRequest) {
// start publisher env
const tag = {
domain: utils.deepAccess(bidderRequest, 'refererInfo.referer')
Domain: utils.deepAccess(adapterRequest, 'refererInfo.referer')
};

if (utils.deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) {
tag.gdpr = 1;
tag.gdpr_consent = utils.deepAccess(bidderRequest, 'gdprConsent.consentString');
if (config.getConfig('coppa') === true) {
tag.Coppa = 1;
}

if (utils.deepAccess(bidderRequest, 'bidderRequest.uspConsent')) {
tag.us_privacy = bidderRequest.uspConsent;
if (utils.deepAccess(adapterRequest, 'gdprConsent.gdprApplies')) {
tag.GDPR = 1;
tag.GDPRConsent = utils.deepAccess(adapterRequest, 'gdprConsent.consentString');
}
if (utils.deepAccess(adapterRequest, 'uspConsent')) {
tag.USP = utils.deepAccess(adapterRequest, 'uspConsent');
}
if (utils.deepAccess(bidRequests[0], 'schain')) {
tag.Schain = utils.deepAccess(bidRequests[0], 'schain');
}
if (utils.deepAccess(bidRequests[0], 'userId')) {
tag.UserIds = utils.deepAccess(bidRequests[0], 'userId');
}
// end publisher env
const bids = []

for (let i = 0, length = bidRequests.length; i < length; i++) {
Object.assign(tag, prepareRTBRequestParams(i, bidRequests[i]));
const bid = prepareBidRequests(bidRequests[i]);
bids.push(bid);
}

return tag;
return { tag, bids };
}

/**
* Parse mediaType
* @param _index {number}
* @param bid {object}
* @param bidReq {object}
* @returns {object}
*/
function prepareRTBRequestParams(_index, bid) {
const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY;
const index = !_index ? '' : `${_index + 1}`;
const sizes = mediaType === VIDEO ? utils.deepAccess(bid, 'mediaTypes.video.playerSize') : utils.deepAccess(bid, 'mediaTypes.banner.sizes');
return {
['callbackId' + index]: bid.bidId,
['aid' + index]: bid.params.aid,
['ad_type' + index]: mediaType,
['sizes' + index]: utils.parseSizesInput(sizes).join()
function prepareBidRequests(bidReq) {
const mediaType = utils.deepAccess(bidReq, 'mediaTypes.video') ? VIDEO : DISPLAY;
const sizes = mediaType === VIDEO ? utils.deepAccess(bidReq, 'mediaTypes.video.playerSize') : utils.deepAccess(bidReq, 'mediaTypes.banner.sizes');
const bidReqParams = {
'CallbackId': bidReq.bidId,
'Aid': bidReq.params.aid,
'AdType': mediaType,
'Sizes': utils.parseSizesInput(sizes).join(',')
};
if (mediaType === VIDEO) {
const context = utils.deepAccess(bidReq, 'mediaTypes.video.context');
if (context === ADPOD) {
bidReqParams.Adpod = utils.deepAccess(bidReq, 'mediaTypes.video');
}
}
return bidReqParams;
}

/**
Expand All @@ -170,19 +199,18 @@ function prepareRTBRequestParams(_index, bid) {
* @returns {object}
*/
function getMediaType(bidderRequest) {
const videoMediaType = utils.deepAccess(bidderRequest, 'mediaTypes.video');
const context = utils.deepAccess(bidderRequest, 'mediaTypes.video.context');

return !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO;
return utils.deepAccess(bidderRequest, 'mediaTypes.video') ? VIDEO : BANNER;
}

/**
* Configure new bid by response
* @param bidResponse {object}
* @param mediaType {Object}
* @param bidRequest {Object}
* @returns {object}
*/
function createBid(bidResponse, mediaType) {
function createBid(bidResponse, bidRequest) {
const mediaType = getMediaType(bidRequest)
const context = utils.deepAccess(bidRequest, 'mediaTypes.video.context');
const bid = {
requestId: bidResponse.requestId,
creativeId: bidResponse.cmpId,
Expand All @@ -192,24 +220,34 @@ function createBid(bidResponse, mediaType) {
cpm: bidResponse.cpm,
netRevenue: true,
mediaType,
ttl: 3600
ttl: 300
};

if (mediaType === DISPLAY) {
if (mediaType === BANNER) {
return Object.assign(bid, {
ad: bidResponse.ad
});
}
if (context === ADPOD) {
Object.assign(bid, {
meta: {
iabSubCatId: bidResponse.iabSubCatId,
},
video: {
context: ADPOD,
durationSeconds: bidResponse.durationSeconds
}
});
}

Object.assign(bid, {
vastUrl: bidResponse.vastUrl
});

if (mediaType === OUTSTREAM) {
if (context === OUTSTREAM) {
Object.assign(bid, {
mediaType: 'video',
adResponse: bidResponse,
renderer: newRenderer(bidResponse.requestId)
renderer: newRenderer(bidResponse.requestId, bidRequest.params)
});
}

Expand All @@ -221,10 +259,11 @@ function createBid(bidResponse, mediaType) {
* @param requestId
* @returns {*}
*/
function newRenderer(requestId) {
function newRenderer(requestId, bidderParams) {
const renderer = Renderer.install({
id: requestId,
url: OUTSTREAM_SRC,
config: bidderParams.outstream || {},
loaded: false
});

Expand All @@ -239,12 +278,13 @@ function newRenderer(requestId) {
*/
function outstreamRender(bid) {
bid.renderer.push(() => {
window.VOutstreamAPI.initOutstreams([{
const opts = Object.assign({}, bid.renderer.getConfig(), {
width: bid.width,
height: bid.height,
vastUrl: bid.vastUrl,
elId: bid.adUnitCode
}]);
});
window.VOutstreamAPI.initOutstreams([opts]);
});
}

Expand Down
Loading

0 comments on commit efcba5a

Please sign in to comment.