Skip to content

Commit

Permalink
Livewrapped Bid Adapter: added support for Price Floors Module (prebi…
Browse files Browse the repository at this point in the history
…d#9540)

* Added support for the Price Floors Module

* Use the ad server's currency when getting prices from the floors module

* Default to USD if the ad server's currency can't be retrieved

* Set the default currency at the right place

* Added tests and made a minor change in how device width and height are calculated

* Only include flrCur when ad requests contain floors
  • Loading branch information
msmeza authored and jorgeluisrocha committed May 18, 2023
1 parent 997778d commit 22529c2
Show file tree
Hide file tree
Showing 2 changed files with 295 additions and 18 deletions.
44 changes: 28 additions & 16 deletions modules/livewrappedBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {deepAccess, getWindowTop, isSafariBrowser, mergeDeep} from '../src/utils.js';
import {deepAccess, getWindowTop, isSafariBrowser, mergeDeep, isFn, isPlainObject} from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {config} from '../src/config.js';
import {find} from '../src/polyfill.js';
Expand Down Expand Up @@ -68,7 +68,9 @@ export const spec = {
bidUrl = bidUrl ? bidUrl.params.bidUrl : URL;
url = url ? url.params.url : (getAppDomain() || getTopWindowLocation(bidderRequest));
test = test ? test.params.test : undefined;
var adRequests = bidRequests.map(bidToAdRequest);
const currency = config.getConfig('currency.adServerCurrency') || 'USD';
var adRequests = bidRequests.map(b => bidToAdRequest(b, currency));
const adRequestsContainFloors = adRequests.some(r => r.flr !== undefined);

if (eids) {
ortb2 = mergeDeep(mergeDeep({}, ortb2 || {}), eids);
Expand Down Expand Up @@ -96,7 +98,8 @@ export const spec = {
rcv: getAdblockerRecovered(),
adRequests: [...adRequests],
rtbData: ortb2,
schain: schain
schain: schain,
flrCur: adRequestsContainFloors ? currency : undefined
};

if (config.getConfig().debug) {
Expand Down Expand Up @@ -223,13 +226,14 @@ function hasPubcid(bid) {
return !!bid.crumbs && !!bid.crumbs.pubcid;
}

function bidToAdRequest(bid) {
function bidToAdRequest(bid, currency) {
var adRequest = {
adUnitId: bid.params.adUnitId,
callerAdUnitId: bid.params.adUnitName || bid.adUnitCode || bid.placementCode,
bidId: bid.bidId,
transactionId: bid.transactionId,
formats: getSizes(bid).map(sizeToFormat),
flr: getBidFloor(bid, currency),
options: bid.params.options
};

Expand Down Expand Up @@ -264,6 +268,22 @@ function sizeToFormat(size) {
}
}

function getBidFloor(bid, currency) {
if (!isFn(bid.getFloor)) {
return undefined;
}

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

return isPlainObject(floor) && !isNaN(floor.floor) && floor.currency == currency
? floor.floor
: undefined;
}

function getAdblockerRecovered() {
try {
return getWindowTop().I12C && getWindowTop().I12C.Morph === 1;
Expand Down Expand Up @@ -302,21 +322,13 @@ function getDeviceIfa() {
}

function getDeviceWidth() {
let device = config.getConfig('device');
if (typeof device === 'object' && device.width) {
return device.width;
}

return window.innerWidth;
const device = config.getConfig('device') || {};
return device.w || window.innerWidth;
}

function getDeviceHeight() {
let device = config.getConfig('device');
if (typeof device === 'object' && device.height) {
return device.height;
}

return window.innerHeight;
const device = config.getConfig('device') || {};
return device.h || window.innerHeight;
}

function getCoppa() {
Expand Down
269 changes: 267 additions & 2 deletions test/spec/modules/livewrappedBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ describe('Livewrapped adapter tests', function () {

window.livewrapped = undefined;

config.setConfig({
device: { w: 100, h: 100 }
});

bidderRequest = {
bidderCode: 'livewrapped',
auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a',
Expand Down Expand Up @@ -43,6 +47,7 @@ describe('Livewrapped adapter tests', function () {

afterEach(function () {
sandbox.restore();
config.resetConfig();
});

describe('isBidRequestValid', function() {
Expand Down Expand Up @@ -351,7 +356,7 @@ describe('Livewrapped adapter tests', function () {
expect(data).to.deep.equal(expectedQuery);
});

it('should make a well-formed single request object with ad blocker revovered parameter', function() {
it('should make a well-formed single request object with ad blocker recovered parameter', function() {
sandbox.stub(utils, 'getWindowTop').returns({ I12C: { Morph: 1 } });
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);
Expand Down Expand Up @@ -489,7 +494,7 @@ describe('Livewrapped adapter tests', function () {
return {bundle: 'bundle', domain: 'https://appdomain.com'};
}
if (key === 'device') {
return {ifa: 'ifa', width: 300, height: 200};
return {ifa: 'ifa', w: 300, h: 200};
}
return origGetConfig.apply(config, arguments);
});
Expand Down Expand Up @@ -839,6 +844,266 @@ describe('Livewrapped adapter tests', function () {

expect(data).to.deep.equal(expectedQuery);
});

it('width and height should default to values from window when not set in config', function() {
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);

config.resetConfig();

let testbidRequest = clone(bidderRequest);
let result = spec.buildRequests(testbidRequest.bids, testbidRequest);
let data = JSON.parse(result.data);

expect(result.url).to.equal('https://lwadm.com/ad');

let expectedQuery = {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
userId: 'user id',
url: 'https://www.domain.com',
seats: {'dsp': ['seat 1']},
version: '1.4',
width: window.innerWidth,
height: window.innerHeight,
cookieSupport: true,
adRequests: [{
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};

expect(data).to.deep.equal(expectedQuery);
});
});

describe('price floors module', function() {
it('price floors module disabled', function() {
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);

let testbidRequest = clone(bidderRequest);
let result = spec.buildRequests(testbidRequest.bids, testbidRequest);
let data = JSON.parse(result.data);

expect(result.url).to.equal('https://lwadm.com/ad');

let expectedQuery = {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
userId: 'user id',
url: 'https://www.domain.com',
seats: {'dsp': ['seat 1']},
version: '1.4',
width: 100,
height: 100,
cookieSupport: true,
adRequests: [{
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};

expect(data).to.deep.equal(expectedQuery);
});

it('getFloor does not return an object', function() {
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);

let testbidRequest = clone(bidderRequest);
let bids = testbidRequest.bids.map(b => {
b.getFloor = function () { return undefined; }
return b;
});
let result = spec.buildRequests(bids, testbidRequest);
let data = JSON.parse(result.data);

expect(result.url).to.equal('https://lwadm.com/ad');

let expectedQuery = {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
userId: 'user id',
url: 'https://www.domain.com',
seats: {'dsp': ['seat 1']},
version: '1.4',
width: 100,
height: 100,
cookieSupport: true,
adRequests: [{
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};

expect(data).to.deep.equal(expectedQuery);
});

it('getFloor returns a NaN floor', function() {
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);

let testbidRequest = clone(bidderRequest);
let bids = testbidRequest.bids.map(b => {
b.getFloor = function () { return { floor: undefined }; }
return b;
});
let result = spec.buildRequests(bids, testbidRequest);
let data = JSON.parse(result.data);

expect(result.url).to.equal('https://lwadm.com/ad');

let expectedQuery = {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
userId: 'user id',
url: 'https://www.domain.com',
seats: {'dsp': ['seat 1']},
version: '1.4',
width: 100,
height: 100,
cookieSupport: true,
adRequests: [{
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};

expect(data).to.deep.equal(expectedQuery);
});

it('getFloor returns unexpected currency', function() {
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);

let testbidRequest = clone(bidderRequest);
let bids = testbidRequest.bids.map(b => {
b.getFloor = function () { return { floor: 10, currency: 'EUR' }; }
return b;
});
let result = spec.buildRequests(bids, testbidRequest);
let data = JSON.parse(result.data);

expect(result.url).to.equal('https://lwadm.com/ad');

let expectedQuery = {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
userId: 'user id',
url: 'https://www.domain.com',
seats: {'dsp': ['seat 1']},
version: '1.4',
width: 100,
height: 100,
cookieSupport: true,
adRequests: [{
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
formats: [{width: 980, height: 240}, {width: 980, height: 120}]
}]
};

expect(data).to.deep.equal(expectedQuery);
});

it('getFloor returns valid floor - ad server currency', function() {
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);

let origGetConfig = config.getConfig;
sandbox.stub(config, 'getConfig').callsFake(function (key) {
if (key === 'currency.adServerCurrency') {
return 'EUR';
}
return origGetConfig.apply(config, arguments);
});

let testbidRequest = clone(bidderRequest);
let bids = testbidRequest.bids.map(b => {
b.getFloor = function () { return { floor: 10, currency: 'EUR' }; }
return b;
});
let result = spec.buildRequests(bids, testbidRequest);
let data = JSON.parse(result.data);

expect(result.url).to.equal('https://lwadm.com/ad');

let expectedQuery = {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
userId: 'user id',
url: 'https://www.domain.com',
seats: {'dsp': ['seat 1']},
version: '1.4',
width: 100,
height: 100,
cookieSupport: true,
flrCur: 'EUR',
adRequests: [{
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
flr: 10
}]
};

expect(data).to.deep.equal(expectedQuery);
});

it('getFloor returns valid floor - default currency', function() {
sandbox.stub(utils, 'isSafariBrowser').callsFake(() => false);
sandbox.stub(storage, 'cookiesAreEnabled').callsFake(() => true);

let testbidRequest = clone(bidderRequest);
let bids = testbidRequest.bids.map(b => {
b.getFloor = function () { return { floor: 10, currency: 'USD' }; }
return b;
});
let result = spec.buildRequests(bids, testbidRequest);
let data = JSON.parse(result.data);

expect(result.url).to.equal('https://lwadm.com/ad');

let expectedQuery = {
auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C',
publisherId: '26947112-2289-405D-88C1-A7340C57E63E',
userId: 'user id',
url: 'https://www.domain.com',
seats: {'dsp': ['seat 1']},
version: '1.4',
width: 100,
height: 100,
cookieSupport: true,
flrCur: 'USD',
adRequests: [{
adUnitId: '9E153CED-61BC-479E-98DF-24DC0D01BA37',
callerAdUnitId: 'panorama_d_1',
bidId: '2ffb201a808da7',
transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D',
formats: [{width: 980, height: 240}, {width: 980, height: 120}],
flr: 10
}]
};

expect(data).to.deep.equal(expectedQuery);
});
});

it('should make use of user ids if available', function() {
Expand Down

0 comments on commit 22529c2

Please sign in to comment.