Skip to content

Commit

Permalink
Smartadserver Bid Adapter: support floors per media type (prebid#9437)
Browse files Browse the repository at this point in the history
* Smartadserver Bid Adapter: Add support for SDA user and site

* Smartadserver Bid Adapter: Fix SDA support getConfig and add to unit testing

* support floors per media type

* Rework payloads enriching

Co-authored-by: Meven Courouble <mcourouble@smartadserver.com>
  • Loading branch information
2 people authored and jorgeluisrocha committed May 18, 2023
1 parent d41426f commit 9ebafad
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 29 deletions.
48 changes: 24 additions & 24 deletions modules/smartadserverBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const spec = {
gvlid: GVL_ID,
aliases: ['smart'], // short code
supportedMediaTypes: [BANNER, VIDEO],

/**
* Determines whether or not the given bid request is valid.
*
Expand Down Expand Up @@ -131,7 +132,6 @@ export const spec = {
*/
buildRequests: function (validBidRequests, bidderRequest) {
// use bidderRequest.bids[] to get bidder-dependent request info

const adServerCurrency = config.getConfig('currency.adServerCurrency');
const sellerDefinedAudience = deepAccess(bidderRequest, 'ortb2.user.data', config.getAnyConfig('ortb2.user.data'));
const sellerDefinedContext = deepAccess(bidderRequest, 'ortb2.site.content.data', config.getAnyConfig('ortb2.site.content.data'));
Expand All @@ -144,7 +144,6 @@ export const spec = {
pageid: bid.params.pageId,
formatid: bid.params.formatId,
currencyCode: adServerCurrency,
bidfloor: bid.params.bidfloor || spec.getBidFloor(bid, adServerCurrency),
targeting: bid.params.target && bid.params.target !== '' ? bid.params.target : undefined,
buid: bid.params.buId && bid.params.buId !== '' ? bid.params.buId : undefined,
appname: bid.params.appName && bid.params.appName !== '' ? bid.params.appName : undefined,
Expand Down Expand Up @@ -175,24 +174,28 @@ export const spec = {
payload.us_privacy = bidderRequest.uspConsent;
}

const videoMediaType = deepAccess(bid, 'mediaTypes.video');
const bannerMediaType = deepAccess(bid, 'mediaTypes.banner');
const isAdUnitContainingVideo = videoMediaType && (videoMediaType.context === 'instream' || videoMediaType.context === 'outstream');
if (!isAdUnitContainingVideo && bannerMediaType) {
payload.sizes = spec.adaptBannerSizes(bannerMediaType.sizes);
bidRequests.push(spec.createServerRequest(payload, bid.params.domain));
} else if (isAdUnitContainingVideo && !bannerMediaType) {
spec.fillPayloadForVideoBidRequest(payload, videoMediaType, bid.params.video);
bidRequests.push(spec.createServerRequest(payload, bid.params.domain));
} else if (isAdUnitContainingVideo && bannerMediaType) {
// If there are video and banner media types in the ad unit, we clone the payload
// to create a specific one for video.
let videoPayload = deepClone(payload);
const videoMediaType = deepAccess(bid, 'mediaTypes.video');
const isSupportedVideoContext = videoMediaType && (videoMediaType.context === 'instream' || videoMediaType.context === 'outstream');

spec.fillPayloadForVideoBidRequest(videoPayload, videoMediaType, bid.params.video);
bidRequests.push(spec.createServerRequest(videoPayload, bid.params.domain));
if (bannerMediaType || isSupportedVideoContext) {
let type;
if (bannerMediaType) {
type = BANNER;
payload.sizes = spec.adaptBannerSizes(bannerMediaType.sizes);

payload.sizes = spec.adaptBannerSizes(bannerMediaType.sizes);
if (isSupportedVideoContext) {
let videoPayload = deepClone(payload);
spec.fillPayloadForVideoBidRequest(videoPayload, videoMediaType, bid.params.video);
videoPayload.bidfloor = bid.params.bidfloor || spec.getBidFloor(bid, adServerCurrency, VIDEO);
bidRequests.push(spec.createServerRequest(videoPayload, bid.params.domain));
}
} else {
type = VIDEO;
spec.fillPayloadForVideoBidRequest(payload, videoMediaType, bid.params.video);
}

payload.bidfloor = bid.params.bidfloor || spec.getBidFloor(bid, adServerCurrency, type);
bidRequests.push(spec.createServerRequest(payload, bid.params.domain));
} else {
bidRequests.push({});
Expand Down Expand Up @@ -253,24 +256,21 @@ export const spec = {
*
* @param {object} bid Bid request object
* @param {string} currency Ad server currency
* @param {string} mediaType Bid media type
* @return {number} Floor price
*/
getBidFloor: function (bid, currency) {
getBidFloor: function (bid, currency, mediaType) {
if (!isFn(bid.getFloor)) {
return DEFAULT_FLOOR;
}

const floor = bid.getFloor({
currency: currency || 'USD',
mediaType: '*',
mediaType,
size: '*'
});

if (isPlainObject(floor) && !isNaN(floor.floor)) {
return floor.floor;
}

return DEFAULT_FLOOR;
return isPlainObject(floor) && !isNaN(floor.floor) ? floor.floor : DEFAULT_FLOOR;
},

/**
Expand Down
97 changes: 92 additions & 5 deletions test/spec/modules/smartadserverBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { expect } from 'chai';
import { BANNER, VIDEO } from 'src/mediaTypes.js';
import { config } from 'src/config.js';
import { spec } from 'modules/smartadserverBidAdapter.js';

Expand Down Expand Up @@ -394,7 +395,6 @@ describe('Smart bid adapter tests', function () {
afterEach(function () {
config.setConfig({ ortb2: undefined });
config.resetConfig();
$$PREBID_GLOBAL$$.requestBids.removeAll();
});

it('Verify build request with GDPR', function () {
Expand Down Expand Up @@ -446,7 +446,6 @@ describe('Smart bid adapter tests', function () {
describe('ccpa/us privacy tests', function () {
afterEach(function () {
config.resetConfig();
$$PREBID_GLOBAL$$.requestBids.removeAll();
});

it('Verify build request with us privacy', function () {
Expand Down Expand Up @@ -475,7 +474,6 @@ describe('Smart bid adapter tests', function () {
describe('Instream video tests', function () {
afterEach(function () {
config.resetConfig();
$$PREBID_GLOBAL$$.requestBids.removeAll();
});

const INSTREAM_DEFAULT_PARAMS = [{
Expand Down Expand Up @@ -746,7 +744,6 @@ describe('Smart bid adapter tests', function () {
describe('Outstream video tests', function () {
afterEach(function () {
config.resetConfig();
$$PREBID_GLOBAL$$.requestBids.removeAll();
});

const OUTSTREAM_DEFAULT_PARAMS = [{
Expand Down Expand Up @@ -1055,6 +1052,17 @@ describe('Smart bid adapter tests', function () {
});

describe('Floors module', function () {
const getFloor = (bid) => {
switch (bid.mediaType) {
case BANNER:
return { currency: 'USD', floor: 1.93 };
case VIDEO:
return { currency: 'USD', floor: 2.72 };
default:
return {};
}
};

it('should include floor from bid params', function() {
const bidRequest = JSON.parse((spec.buildRequests(DEFAULT_PARAMS))[0].data);
expect(bidRequest.bidfloor).to.deep.equal(DEFAULT_PARAMS[0].params.bidfloor);
Expand Down Expand Up @@ -1094,12 +1102,91 @@ describe('Smart bid adapter tests', function () {
const floor = spec.getBidFloor(bidRequest, null);
expect(floor).to.deep.equal(0);
});

it('should take floor from bidder params over ad unit', function() {
const bidRequest = [{
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
},
getFloor,
params: { siteId: 1234, pageId: 678, formatId: 73, bidfloor: 1.25 }
}];

const request = spec.buildRequests(bidRequest);
const requestContent = JSON.parse(request[0].data);

expect(requestContent).to.have.property('bidfloor').and.to.equal(1.25);
});

it('should take floor from banner ad unit', function() {
const bidRequest = [{
mediaTypes: {
banner: {
sizes: [[300, 250], [300, 600]]
}
},
getFloor,
params: { siteId: 1234, pageId: 678, formatId: 73 }
}];

const request = spec.buildRequests(bidRequest);
const requestContent = JSON.parse(request[0].data);

expect(requestContent).to.have.property('bidfloor').and.to.equal(1.93);
});

it('should take floor from video ad unit', function() {
const bidRequest = [{
mediaTypes: {
video: {
context: 'outstream',
playerSize: [[640, 480]]
}
},
getFloor,
params: { siteId: 1234, pageId: 678, formatId: 73 }
}];

const request = spec.buildRequests(bidRequest);
const requestContent = JSON.parse(request[0].data);

expect(requestContent).to.have.property('bidfloor').and.to.equal(2.72);
});

it('should take floor from multiple media type ad unit', function() {
const bidRequest = [{
mediaTypes: {
banner: {
sizes: [[300, 600]]
},
video: {
context: 'outstream',
playerSize: [[640, 480]]
}
},
getFloor,
params: { siteId: 1234, pageId: 678, formatId: 73 }
}];

const requests = spec.buildRequests(bidRequest);
expect(requests).to.have.lengthOf(2);

const requestContents = requests.map(r => JSON.parse(r.data));
const videoRequest = requestContents.filter(r => r.videoData)[0];
expect(videoRequest).to.not.equal(null).and.to.not.be.undefined;
expect(videoRequest).to.have.property('bidfloor').and.to.equal(2.72);

const bannerRequest = requestContents.filter(r => !r.videoData)[0];
expect(bannerRequest).to.not.equal(null).and.to.not.be.undefined;
expect(bannerRequest).to.have.property('bidfloor').and.to.equal(1.93);
});
});

describe('Verify bid requests with multiple mediaTypes', function () {
afterEach(function () {
config.resetConfig();
$$PREBID_GLOBAL$$.requestBids.removeAll();
});

var DEFAULT_PARAMS_MULTIPLE_MEDIA_TYPES = [{
Expand Down

0 comments on commit 9ebafad

Please sign in to comment.