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

Improve Digital adapter: added video skippability params #6161

Merged
merged 1 commit into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
39 changes: 37 additions & 2 deletions modules/improvedigitalBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { config } from '../src/config.js';
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
import {Renderer} from '../src/Renderer.js';
import { createEidsArray } from './userId/eids.js';
import includes from 'core-js-pure/features/array/includes.js';

const BIDDER_CODE = 'improvedigital';
const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js';
const VIDEO_TARGETING = ['skip', 'skipmin', 'skipafter'];

export const spec = {
version: '7.1.0',
version: '7.2.0',
code: BIDDER_CODE,
gvlid: 253,
aliases: ['id'],
Expand Down Expand Up @@ -202,6 +204,21 @@ function isOutstreamVideo(bid) {
return videoMediaType && context === 'outstream';
}

function getVideoTargetingParams(bid) {
const result = {};
Object.keys(Object(bid.mediaTypes.video))
.filter(key => includes(VIDEO_TARGETING, key))
.forEach(key => {
result[ key ] = bid.mediaTypes.video[ key ];
});
Object.keys(Object(bid.params.video))
.filter(key => includes(VIDEO_TARGETING, key))
.forEach(key => {
result[ key ] = bid.params.video[ key ];
});
return result;
}

function outstreamRender(bid) {
bid.renderer.push(() => {
window.ANOutstreamVideo.renderAd({
Expand Down Expand Up @@ -255,6 +272,9 @@ function getNormalizedBidRequest(bid) {
if (isInstreamVideo(bid)) {
normalizedBidRequest.adTypes = [ VIDEO ];
}
if (isInstreamVideo(bid) || isOutstreamVideo(bid)) {
normalizedBidRequest.video = getVideoTargetingParams(bid);
}
if (placementId) {
normalizedBidRequest.placementId = placementId;
} else {
Expand Down Expand Up @@ -400,7 +420,7 @@ export function ImproveDigitalAdServerJSClient(endPoint) {
AD_SERVER_BASE_URL: 'ice.360yield.com',
END_POINT: endPoint || 'hb',
AD_SERVER_URL_PARAM: 'jsonp=',
CLIENT_VERSION: 'JS-6.3.0',
CLIENT_VERSION: 'JS-6.4.0',
MAX_URL_LENGTH: 2083,
ERROR_CODES: {
MISSING_PLACEMENT_PARAMS: 2,
Expand Down Expand Up @@ -609,6 +629,21 @@ export function ImproveDigitalAdServerJSClient(endPoint) {
if (placementObject.transactionId) {
impressionObject.tid = placementObject.transactionId;
}
if (!utils.isEmpty(placementObject.video)) {
const video = Object.assign({}, placementObject.video);
// skip must be 0 or 1
if (video.skip !== 1) {
delete video.skipmin;
delete video.skipafter;
if (video.skip !== 0) {
utils.logWarn(`video.skip: invalid value '${video.skip}'. Expected 0 or 1`);
delete video.skip;
}
}
if (!utils.isEmpty(video)) {
impressionObject.video = video;
}
}
if (placementObject.keyValues) {
for (let key in placementObject.keyValues) {
for (let valueCounter = 0; valueCounter < placementObject.keyValues[key].length; valueCounter++) {
Expand Down
90 changes: 88 additions & 2 deletions test/spec/modules/improvedigitalBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ describe('Improve Digital Adapter Tests', function () {
sizes: [[300, 250], [160, 600], ['blah', 150], [-1, 300], [300, -5]]
};

const videoParams = {
skip: 1,
skipmin: 5,
skipafter: 30
}

const instreamBidRequest = utils.deepClone(simpleBidRequest);
instreamBidRequest.mediaTypes = {
video: {
Expand Down Expand Up @@ -280,14 +286,23 @@ describe('Improve Digital Adapter Tests', function () {
expect(params.bid_request.referrer).to.equal('https://blah.com/test.html');
});

it('should not add video params for banner', function () {
const bidRequest = JSON.parse(JSON.stringify(simpleBidRequest));
bidRequest.params.video = videoParams;
const request = spec.buildRequests([bidRequest], bidderRequest)[0];
const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.not.exist;
});

it('should add ad type for instream video', function () {
let bidRequest = Object.assign({}, simpleBidRequest);
let bidRequest = JSON.parse(JSON.stringify(simpleBidRequest));
bidRequest.mediaType = 'video';
let request = spec.buildRequests([bidRequest], bidderRequest)[0];
let params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].ad_types).to.deep.equal(['video']);
expect(params.bid_request.imp[0].video).to.not.exist;

bidRequest = Object.assign({}, simpleBidRequest);
bidRequest = JSON.parse(JSON.stringify(simpleBidRequest));
bidRequest.mediaTypes = {
video: {
context: 'instream',
Expand All @@ -297,18 +312,89 @@ describe('Improve Digital Adapter Tests', function () {
request = spec.buildRequests([bidRequest], bidderRequest)[0];
params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].ad_types).to.deep.equal(['video']);
expect(params.bid_request.imp[0].video).to.not.exist;
});

it('should not set ad type for outstream video', function() {
const request = spec.buildRequests([outstreamBidRequest])[0];
const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].ad_types).to.not.exist;
expect(params.bid_request.imp[0].video).to.not.exist;
});

it('should not set ad type for multi-format bids', function() {
const request = spec.buildRequests([multiFormatBidRequest], bidderRequest)[0];
const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].ad_types).to.not.exist;
expect(params.bid_request.imp[0].video).to.not.exist;
});

it('should set video params for instream', function() {
const bidRequest = JSON.parse(JSON.stringify(instreamBidRequest));
bidRequest.params.video = videoParams;
const request = spec.buildRequests([bidRequest])[0];
const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.deep.equal(videoParams);
});

it('should set skip params only if skip=1', function() {
const bidRequest = JSON.parse(JSON.stringify(instreamBidRequest));
// 1
const videoTest = {
skip: 1,
skipmin: 5,
skipafter: 30
}
bidRequest.params.video = videoTest;
let request = spec.buildRequests([bidRequest])[0];
let params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.deep.equal(videoTest);

// 0 - leave out skipmin and skipafter
videoTest.skip = 0;
bidRequest.params.video = videoTest;
request = spec.buildRequests([bidRequest])[0];
params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.deep.equal({ skip: 0 });

// other
videoTest.skip = 'blah';
bidRequest.params.video = videoTest;
request = spec.buildRequests([bidRequest])[0];
params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.not.exist;
});

it('should ignore invalid/unexpected video params', function() {
const bidRequest = JSON.parse(JSON.stringify(instreamBidRequest));
// 1
const videoTest = {
skip: 1,
skipmin: 5,
skipafter: 30
}
const videoTestInvParam = Object.assign({}, videoTest);
videoTestInvParam.blah = 1;
bidRequest.params.video = videoTestInvParam;
let request = spec.buildRequests([bidRequest])[0];
let params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.deep.equal(videoTest);
});

it('should set video params for outstream', function() {
const bidRequest = JSON.parse(JSON.stringify(outstreamBidRequest));
bidRequest.params.video = videoParams;
const request = spec.buildRequests([bidRequest])[0];
const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.deep.equal(videoParams);
});

it('should set video params for multi-format', function() {
const bidRequest = JSON.parse(JSON.stringify(multiFormatBidRequest));
bidRequest.params.video = videoParams;
const request = spec.buildRequests([bidRequest])[0];
const params = JSON.parse(decodeURIComponent(request.data.substring(PARAM_PREFIX.length)));
expect(params.bid_request.imp[0].video).to.deep.equal(videoParams);
});

it('should not set Prebid sizes in bid request for instream video', function () {
Expand Down