Skip to content

Commit 899fb32

Browse files
spotxslagleJacobKlein26
authored andcommitted
Prebid Core: Allow Cpm Custom Rounding (prebid#9018)
* Allow custom rounding functions * Add custom rounding unit tests * Default to Math.floor when passed an invalid rounding function * Add error logging * Fix import statement
1 parent d2c9022 commit 899fb32

File tree

2 files changed

+261
-180
lines changed

2 files changed

+261
-180
lines changed

src/cpmBucketManager.js

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {find} from './polyfill.js';
2-
import { isEmpty } from './utils.js';
2+
import { isEmpty, logWarn } from './utils.js';
3+
import { config } from './config.js';
34

45
const _defaultPrecision = 2;
56
const _lgPriceConfig = {
@@ -118,17 +119,35 @@ function getCpmTarget(cpm, bucket, granularityMultiplier) {
118119
const precision = typeof bucket.precision !== 'undefined' ? bucket.precision : _defaultPrecision;
119120
const increment = bucket.increment * granularityMultiplier;
120121
const bucketMin = bucket.min * granularityMultiplier;
122+
let roundingFunction = Math.floor;
123+
let customRoundingFunction = config.getConfig('cpmRoundingFunction');
124+
if (typeof customRoundingFunction === 'function') {
125+
roundingFunction = customRoundingFunction;
126+
}
121127

122128
// start increments at the bucket min and then add bucket min back to arrive at the correct rounding
123129
// note - we're padding the values to avoid using decimals in the math prior to flooring
124130
// this is done as JS can return values slightly below the expected mark which would skew the price bucket target
125131
// (eg 4.01 / 0.01 = 400.99999999999994)
126132
// min precison should be 2 to move decimal place over.
127133
let pow = Math.pow(10, precision + 2);
128-
let cpmToFloor = ((cpm * pow) - (bucketMin * pow)) / (increment * pow);
129-
let cpmTarget = ((Math.floor(cpmToFloor)) * increment) + bucketMin;
134+
let cpmToRound = ((cpm * pow) - (bucketMin * pow)) / (increment * pow);
135+
let cpmTarget;
136+
let invalidRounding;
137+
// It is likely that we will be passed {cpmRoundingFunction: roundingFunction()}
138+
// rather than the expected {cpmRoundingFunction: roundingFunction}. Default back to floor in that case
139+
try {
140+
cpmTarget = (roundingFunction(cpmToRound) * increment) + bucketMin;
141+
} catch (err) {
142+
invalidRounding = true;
143+
}
144+
if (invalidRounding || typeof cpmTarget !== 'number') {
145+
logWarn('Invalid rounding function passed in config');
146+
cpmTarget = (Math.floor(cpmToRound) * increment) + bucketMin;
147+
}
130148
// force to 10 decimal places to deal with imprecise decimal/binary conversions
131149
// (for example 0.1 * 3 = 0.30000000000000004)
150+
132151
cpmTarget = Number(cpmTarget.toFixed(10));
133152
return cpmTarget.toFixed(precision);
134153
}

0 commit comments

Comments
 (0)