From 4a4e922cb7b0e40fd1c902f1a310e92f48e47d20 Mon Sep 17 00:00:00 2001 From: Matt Kleinberg Date: Wed, 29 Jul 2020 14:40:54 -0400 Subject: [PATCH] Update floors module for #5511 (#5538) * Changed fallback value of skipRate from 0 to undefined. Removed skipRate from bidRequest[ ].floorData if undefined. If no floor data available set bidRequest[ ].floorData.location to 'noBid'. * Added top level floorProvider value. * reverted skip rate back to 0 from undifined when not set. Removed type enforcement from floorProvider. Added floorProvider into return data. * fixed description for floorProvider --- modules/priceFloors.js | 6 ++- modules/priceFloors.md | 4 +- test/spec/modules/priceFloors_spec.js | 54 +++++++++++++++++---------- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/modules/priceFloors.js b/modules/priceFloors.js index 6d35a0a74cc..817f2103ba2 100644 --- a/modules/priceFloors.js +++ b/modules/priceFloors.js @@ -286,9 +286,10 @@ export function updateAdUnitsForAuction(adUnits, floorData, auctionId) { bid.auctionId = auctionId; bid.floorData = { skipped: floorData.skipped, - modelVersion: utils.deepAccess(floorData, 'data.modelVersion'), - location: utils.deepAccess(floorData, 'data.location'), skipRate: floorData.skipRate, + modelVersion: utils.deepAccess(floorData, 'data.modelVersion'), + location: utils.deepAccess(floorData, 'data.location', 'noData'), + floorProvider: floorData.floorProvider, fetchStatus: _floorsConfig.fetchStatus } }); @@ -568,6 +569,7 @@ export function handleSetFloorsConfig(config) { _floorsConfig = utils.pick(config, [ 'enabled', enabled => enabled !== false, // defaults to true 'auctionDelay', auctionDelay => auctionDelay || 0, + 'floorProvider', 'endpoint', endpoint => endpoint || {}, 'skipRate', () => !isNaN(utils.deepAccess(config, 'data.skipRate')) ? config.data.skipRate : config.skipRate || 0, 'enforcement', enforcement => utils.pick(enforcement || {}, [ diff --git a/modules/priceFloors.md b/modules/priceFloors.md index d09be78c620..36ac07ee972 100644 --- a/modules/priceFloors.md +++ b/modules/priceFloors.md @@ -11,6 +11,7 @@ pbjs.setConfig({ enforceJS: true //defaults to true }, auctionDelay: 150, // in milliseconds defaults to 0 + floorProvider: 'awesomeFloorProviderName', // name of the floor provider (optional) endpoint: { url: 'http://localhost:1500/floor-domains', method: 'GET' // Only get supported for now @@ -40,6 +41,7 @@ pbjs.setConfig({ | enabled | Wether to turn off or on the floors module | | enforcement | object of booleans which control certain features of the module | | auctionDelay | The time to suspend and auction while waiting for a real time price floors fetch to come back | +| floorProvider | A string identifying the floor provider.| | endpoint | An object describing the endpoint to retrieve floor data from. GET only | | data | The data to be used to select appropriate floors. See schema for more detail | | additionalSchemaFields | An object of additional fields to be used in a floor data object. The schema is KEY: function to retrieve the match | @@ -59,4 +61,4 @@ This function can takes in an object with the following optional parameters: If a bid adapter passes in `*` as an attribute, then the `priceFloors` module will attempt to select the best rule based on context. -For example, if an adapter passes in a `*`, but the bidRequest only has a single size and a single mediaType, then the `getFloor` function will attempt to get a rule for that size before matching with the `*` catch-all. Similarily, if mediaType can be inferred on the bidRequest, it will use it. \ No newline at end of file +For example, if an adapter passes in a `*`, but the bidRequest only has a single size and a single mediaType, then the `getFloor` function will attempt to get a rule for that size before matching with the `*` catch-all. Similarily, if mediaType can be inferred on the bidRequest, it will use it. diff --git a/test/spec/modules/priceFloors_spec.js b/test/spec/modules/priceFloors_spec.js index 9d35554c27f..5cb31ffab4c 100644 --- a/test/spec/modules/priceFloors_spec.js +++ b/test/spec/modules/priceFloors_spec.js @@ -314,9 +314,10 @@ describe('the price floors module', function () { validateBidRequests(false, { skipped: true, modelVersion: undefined, - location: undefined, + location: 'noData', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: undefined }); }); it('should use adUnit level data if not setConfig or fetch has occured', function () { @@ -348,18 +349,20 @@ describe('the price floors module', function () { modelVersion: 'adUnit Model Version', location: 'adUnit', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: undefined }); }); it('bidRequests should have getFloor function and flooring meta data when setConfig occurs', function () { - handleSetFloorsConfig({...basicFloorConfig}); + handleSetFloorsConfig({...basicFloorConfig, floorProvider: 'floorprovider'}); runStandardAuction(); validateBidRequests(true, { skipped: false, modelVersion: 'basic model', location: 'setConfig', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: 'floorprovider' }); }); it('should take the right skipRate depending on input', function () { @@ -380,7 +383,8 @@ describe('the price floors module', function () { modelVersion: 'basic model', location: 'setConfig', skipRate: 50, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: undefined }); // if that does not exist uses topLevel skipRate setting @@ -392,7 +396,8 @@ describe('the price floors module', function () { modelVersion: 'basic model', location: 'setConfig', skipRate: 10, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: undefined }); // if that is not there defaults to zero @@ -404,12 +409,14 @@ describe('the price floors module', function () { modelVersion: 'basic model', location: 'setConfig', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: undefined }); }); it('should randomly pick a model if floorsSchemaVersion is 2', function () { let inputFloors = { ...basicFloorConfig, + floorProvider: 'floorprovider', data: { floorsSchemaVersion: 2, currency: 'USD', @@ -465,7 +472,8 @@ describe('the price floors module', function () { modelVersion: 'model-1', location: 'setConfig', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: 'floorprovider' }); // 11 - 50 should use second model @@ -476,7 +484,8 @@ describe('the price floors module', function () { modelVersion: 'model-2', location: 'setConfig', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: 'floorprovider' }); // 51 - 100 should use third model @@ -487,7 +496,8 @@ describe('the price floors module', function () { modelVersion: 'model-3', location: 'setConfig', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: 'floorprovider' }); }); it('should not overwrite previous data object if the new one is bad', function () { @@ -514,7 +524,8 @@ describe('the price floors module', function () { modelVersion: 'basic model', location: 'setConfig', skipRate: 0, - fetchStatus: undefined + fetchStatus: undefined, + floorProvider: undefined }); }); it('should dynamically add new schema fileds and functions if added via setConfig', function () { @@ -591,7 +602,8 @@ describe('the price floors module', function () { modelVersion: 'basic model', location: 'setConfig', skipRate: 0, - fetchStatus: 'timeout' + fetchStatus: 'timeout', + floorProvider: undefined }); fakeFloorProvider.respond(); }); @@ -604,7 +616,7 @@ describe('the price floors module', function () { fakeFloorProvider.respondWith(JSON.stringify(fetchFloorData)); // run setConfig indicating fetch - handleSetFloorsConfig({...basicFloorConfig, auctionDelay: 250, endpoint: {url: 'http://www.fakeFloorProvider.json'}}); + handleSetFloorsConfig({...basicFloorConfig, floorProvider: 'floorprovider', auctionDelay: 250, endpoint: {url: 'http://www.fakeFloorProvider.json'}}); // floor provider should be called expect(fakeFloorProvider.requests.length).to.equal(1); @@ -627,7 +639,8 @@ describe('the price floors module', function () { modelVersion: 'fetch model name', location: 'fetch', skipRate: 0, - fetchStatus: 'success' + fetchStatus: 'success', + floorProvider: 'floorprovider' }); }); it('it should correctly overwrite skipRate with fetch skipRate', function () { @@ -642,7 +655,7 @@ describe('the price floors module', function () { fakeFloorProvider.respondWith(JSON.stringify(fetchFloorData)); // run setConfig indicating fetch - handleSetFloorsConfig({...basicFloorConfig, auctionDelay: 250, endpoint: {url: 'http://www.fakeFloorProvider.json'}}); + handleSetFloorsConfig({...basicFloorConfig, floorProvider: 'floorprovider', auctionDelay: 250, endpoint: {url: 'http://www.fakeFloorProvider.json'}}); // floor provider should be called expect(fakeFloorProvider.requests.length).to.equal(1); @@ -665,7 +678,8 @@ describe('the price floors module', function () { modelVersion: 'fetch model name', location: 'fetch', skipRate: 95, - fetchStatus: 'success' + fetchStatus: 'success', + floorProvider: 'floorprovider' }); }); it('Should not break if floor provider returns 404', function () { @@ -685,7 +699,8 @@ describe('the price floors module', function () { modelVersion: 'basic model', location: 'setConfig', skipRate: 0, - fetchStatus: 'error' + fetchStatus: 'error', + floorProvider: undefined }); }); it('Should not break if floor provider returns non json', function () { @@ -707,7 +722,8 @@ describe('the price floors module', function () { modelVersion: 'basic model', location: 'setConfig', skipRate: 0, - fetchStatus: 'success' + fetchStatus: 'success', + floorProvider: undefined }); }); it('should handle not using fetch correctly', function () {