Skip to content

Commit

Permalink
multiformat size validation checks (prebid#1964)
Browse files Browse the repository at this point in the history
* initial commit for multiformat size validation checks

* adding unit tests and changes to checkBidRequestSizes function

* updates to appnexusBidAdapter
  • Loading branch information
jsnellbaker authored and Justas Pupelis committed Jan 10, 2018
1 parent cf3bf61 commit d4712be
Show file tree
Hide file tree
Showing 5 changed files with 376 additions and 11 deletions.
24 changes: 14 additions & 10 deletions modules/appnexusBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,20 +216,24 @@ function newBid(serverBid, rtbBid) {
body: nativeAd.desc,
cta: nativeAd.ctatext,
sponsoredBy: nativeAd.sponsored,
image: {
url: nativeAd.main_img && nativeAd.main_img.url,
height: nativeAd.main_img && nativeAd.main_img.height,
width: nativeAd.main_img && nativeAd.main_img.width,
},
icon: {
url: nativeAd.icon && nativeAd.icon.url,
height: nativeAd.icon && nativeAd.icon.height,
width: nativeAd.icon && nativeAd.icon.width,
},
clickUrl: nativeAd.link.url,
clickTrackers: nativeAd.link.click_trackers,
impressionTrackers: nativeAd.impression_trackers,
};
if (nativeAd.main_img) {
bid['native'].image = {
url: nativeAd.main_img.url,
height: nativeAd.main_img.height,
width: nativeAd.main_img.width,
};
}
if (nativeAd.icon) {
bid['native'].icon = {
url: nativeAd.icon.url,
height: nativeAd.icon.height,
width: nativeAd.icon.width,
};
}
} else {
Object.assign(bid, {
width: rtbBid.rtb.banner.width,
Expand Down
51 changes: 51 additions & 0 deletions src/adaptermanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ function getAdUnitCopyForClientAdapters(adUnits) {

exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout, labels) {
let bidRequests = [];

adUnits = exports.checkBidRequestSizes(adUnits);

let bidderCodes = getBidderCodes(adUnits);
if (config.getConfig('bidderSequence') === RANDOM) {
bidderCodes = shuffle(bidderCodes);
Expand Down Expand Up @@ -211,6 +214,54 @@ exports.makeBidRequests = function(adUnits, auctionStart, auctionId, cbTimeout,
return bidRequests;
};

exports.checkBidRequestSizes = (adUnits) => {
Array.prototype.forEach.call(adUnits, adUnit => {
if (adUnit.sizes) {
utils.logWarn('Usage of adUnits.sizes will eventually be deprecated. Please define size dimensions within the corresponding area of the mediaTypes.<object> (eg mediaTypes.banner.sizes).');
}

const mediaTypes = adUnit.mediaTypes;
if (mediaTypes && mediaTypes.banner) {
const banner = mediaTypes.banner;
if (banner.sizes) {
adUnit.sizes = banner.sizes;
} else {
utils.logError('Detected a mediaTypes.banner object did not include sizes. This is a required field for the mediaTypes.banner object. Removing invalid mediaTypes.banner object from request.');
delete adUnit.mediaTypes.banner;
}
}

if (mediaTypes && mediaTypes.video) {
const video = mediaTypes.video;
if (video.playerSize) {
if (Array.isArray(video.playerSize) && video.playerSize.length === 2 && Number.isInteger(video.playerSize[0]) && Number.isInteger(video.playerSize[1])) {
adUnit.sizes = video.playerSize;
} else {
utils.logError('Detected incorrect configuration of mediaTypes.video.playerSize. Please specify only one set of dimensions in a format like: [640, 480]. Removing invalid mediaTypes.video.playerSize property from request.');
delete adUnit.mediaTypes.video.playerSize;
}
}
}

if (mediaTypes && mediaTypes.native) {
const native = mediaTypes.native;
if (native.image && native.image.sizes && !Array.isArray(native.image.sizes)) {
utils.logError('Please use an array of sizes for native.image.sizes field. Removing invalid mediaTypes.native.image.sizes property from request.');
delete adUnit.mediaTypes.native.image.sizes;
}
if (native.image && native.image.aspect_ratios && !Array.isArray(native.image.aspect_ratios)) {
utils.logError('Please use an array of sizes for native.image.aspect_ratios field. Removing invalid mediaTypes.native.image.aspect_ratios property from request.');
delete adUnit.mediaTypes.native.image.aspect_ratios;
}
if (native.icon && native.icon.sizes && !Array.isArray(native.icon.sizes)) {
utils.logError('Please use an array of sizes for native.icon.sizes field. Removing invalid mediaTypes.native.icon.sizes property from request.');
delete adUnit.mediaTypes.native.icon.sizes;
}
}
});
return adUnits;
}

exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => {
if (!bidRequests.length) {
utils.logWarn('callBids executed with no bidRequests. Were they filtered by labels or sizing?');
Expand Down
12 changes: 12 additions & 0 deletions src/native.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ export function nativeBidIsValid(bid, bidRequests) {
return false;
}

if (deepAccess(bid, 'native.image')) {
if (!deepAccess(bid, 'native.image.height') || !deepAccess(bid, 'native.image.width')) {
return false;
}
}

if (deepAccess(bid, 'native.icon')) {
if (!deepAccess(bid, 'native.icon.height') || !deepAccess(bid, 'native.icon.width')) {
return false;
}
}

const requestedAssets = bidRequest.nativeParams;
if (!requestedAssets) {
return true;
Expand Down
112 changes: 111 additions & 1 deletion test/spec/native_spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai';
import { fireNativeTrackers, getNativeTargeting } from 'src/native';
import { fireNativeTrackers, getNativeTargeting, nativeBidIsValid } from 'src/native';
const utils = require('src/utils');

const bid = {
Expand Down Expand Up @@ -44,3 +44,113 @@ describe('native.js', () => {
sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]);
});
});

describe('validate native', () => {
let bidReq = [{
bids: [{
bidderCode: 'test_bidder',
bidId: 'test_bid_id',
mediaTypes: {
native: {
title: {
required: true,
},
body: {
required: true,
},
image: {
required: true,
sizes: [150, 50],
aspect_ratios: [150, 50]
},
icon: {
required: true,
sizes: [50, 50]
},
}
}
}]
}];

let validBid = {
adId: 'test_bid_id',
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
clickTrackers: ['http://my.click.tracker/url'],
icon: {
url: 'http://my.image.file/ad_image.jpg',
height: 75,
width: 75
},
image: {
url: 'http://my.icon.file/ad_icon.jpg',
height: 2250,
width: 3000
},
clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html',
impressionTrackers: ['http://my.imp.tracker/url'],
title: 'This is an example Prebid Native creative'
}
};

let noIconDimBid = {
adId: 'test_bid_id',
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
clickTrackers: ['http://my.click.tracker/url'],
icon: {
url: 'http://my.image.file/ad_image.jpg',
height: 0,
width: 0
},
image: {
url: 'http://my.icon.file/ad_icon.jpg',
height: 2250,
width: 3000
},
clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html',
impressionTrackers: ['http://my.imp.tracker/url'],
title: 'This is an example Prebid Native creative'
}
};

let noImgDimBid = {
adId: 'test_bid_id',
adUnitCode: '123/prebid_native_adunit',
bidder: 'test_bidder',
native: {
body: 'This is a Prebid Native Creative. There are many like it, but this one is mine.',
clickTrackers: ['http://my.click.tracker/url'],
icon: {
url: 'http://my.image.file/ad_image.jpg',
height: 75,
width: 75
},
image: {
url: 'http://my.icon.file/ad_icon.jpg',
height: 0,
width: 0
},
clickUrl: 'http://prebid.org/dev-docs/show-native-ads.html',
impressionTrackers: ['http://my.imp.tracker/url'],
title: 'This is an example Prebid Native creative'
}
};

beforeEach(() => {});

afterEach(() => {});

it('should reject bid if no image sizes are defined', () => {
let result = nativeBidIsValid(validBid, bidReq);
expect(result).to.be.true;
result = nativeBidIsValid(noIconDimBid, bidReq);
expect(result).to.be.false;
result = nativeBidIsValid(noImgDimBid, bidReq);
expect(result).to.be.false;
});
});
Loading

0 comments on commit d4712be

Please sign in to comment.