Skip to content

Commit

Permalink
Prebid core: allow configurable TTL buffer (prebid#9136)
Browse files Browse the repository at this point in the history
  • Loading branch information
dgirardi authored Oct 27, 2022
1 parent cc3f01d commit 297bb48
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 6 deletions.
5 changes: 5 additions & 0 deletions src/auction.js
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ export const callPrebidCache = hook('async', function(auctionInstance, bidRespon
*/
function addCommonResponseProperties(bidResponse, adUnitCode, {index = auctionManager.index} = {}) {
const bidderRequest = index.getBidderRequest(bidResponse);
const adUnit = index.getAdUnit(bidResponse);
const start = (bidderRequest && bidderRequest.start) || bidResponse.requestTimestamp;

Object.assign(bidResponse, {
Expand All @@ -676,6 +677,10 @@ function addCommonResponseProperties(bidResponse, adUnitCode, {index = auctionMa
adUnitCode
});

if (adUnit?.ttlBuffer != null) {
bidResponse.ttlBuffer = adUnit.ttlBuffer;
}

bidResponse.timeToRespond = bidResponse.responseTimestamp - bidResponse.requestTimestamp;
}

Expand Down
9 changes: 6 additions & 3 deletions src/prebid.js
Original file line number Diff line number Diff line change
Expand Up @@ -622,15 +622,15 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) {
* @alias module:pbjs.requestBids
*/
$$PREBID_GLOBAL$$.requestBids = (function() {
const delegate = hook('sync', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels, auctionId, ortb2, metrics } = {}) {
const delegate = hook('sync', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2, metrics } = {}) {
events.emit(REQUEST_BIDS);
const cbTimeout = timeout || config.getConfig('bidderTimeout');
logInfo('Invoking $$PREBID_GLOBAL$$.requestBids', arguments);
const ortb2Fragments = {
global: mergeDeep({}, config.getAnyConfig('ortb2') || {}, ortb2 || {}),
bidder: Object.fromEntries(Object.entries(config.getBidderConfig()).map(([bidder, cfg]) => [bidder, cfg.ortb2]).filter(([_, ortb2]) => ortb2 != null))
}
return startAuction({bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ortb2Fragments, metrics});
return startAuction({bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2Fragments, metrics});
}, 'requestBids');

return wrapHook(delegate, function requestBids(req = {}) {
Expand All @@ -646,7 +646,7 @@ $$PREBID_GLOBAL$$.requestBids = (function() {
});
})();

export const startAuction = hook('sync', function ({ bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ortb2Fragments, metrics } = {}) {
export const startAuction = hook('sync', function ({ bidsBackHandler, timeout: cbTimeout, adUnits, ttlBuffer, adUnitCodes, labels, auctionId, ortb2Fragments, metrics } = {}) {
const s2sBidders = getS2SBidderSet(config.getConfig('s2sConfig') || []);
adUnits = useMetrics(metrics).measureTime('requestBids.validate', () => checkAdUnitSetup(adUnits));

Expand Down Expand Up @@ -688,6 +688,9 @@ export const startAuction = hook('sync', function ({ bidsBackHandler, timeout: c

const tid = adUnit.ortb2Imp?.ext?.tid || generateUUID();
adUnit.transactionId = tid;
if (ttlBuffer != null && !adUnit.hasOwnProperty('ttlBuffer')) {
adUnit.ttlBuffer = ttlBuffer;
}
// Populate ortb2Imp.ext.tid with transactionId. Specifying a transaction ID per item in the ortb impression array, lets multiple transaction IDs be transmitted in a single bid request.
deepSetValue(adUnit, 'ortb2Imp.ext.tid', tid);

Expand Down
12 changes: 10 additions & 2 deletions src/targeting.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@ import CONSTANTS from './constants.json';
var pbTargetingKeys = [];

const MAX_DFP_KEYLENGTH = 20;
const TTL_BUFFER = 1000;
let DEFAULT_TTL_BUFFER = 1;

config.getConfig('ttlBuffer', (cfg) => {
if (typeof cfg.ttlBuffer === 'number') {
DEFAULT_TTL_BUFFER = cfg.ttlBuffer;
} else {
logError('Invalid value for ttlBuffer', cfg.ttlBuffer);
}
})

const CFG_ALLOW_TARGETING_KEYS = `targetingControls.allowTargetingKeys`;
const CFG_ADD_TARGETING_KEYS = `targetingControls.addTargetingKeys`;
Expand All @@ -39,7 +47,7 @@ export const TARGETING_KEYS = Object.keys(CONSTANTS.TARGETING_KEYS).map(
);

// return unexpired bids
const isBidNotExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 - TTL_BUFFER) > timestamp();
const isBidNotExpired = (bid) => (bid.responseTimestamp + (bid.ttl - (bid.hasOwnProperty('ttlBuffer') ? bid.ttlBuffer : DEFAULT_TTL_BUFFER)) * 1000) > timestamp();

// return bids whose status is not set. Winning bids can only have a status of `rendered`.
const isUnusedBid = (bid) => bid && ((bid.status && !includes([CONSTANTS.BID_STATUS.RENDERED], bid.status)) || !bid.status);
Expand Down
6 changes: 6 additions & 0 deletions test/spec/auctionmanager_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,12 @@ describe('auctionmanager.js', function () {
const addedBid = find(auction.getBidsReceived(), bid => bid.adUnitCode == ADUNIT_CODE);
assert.equal(addedBid.renderer.url, 'renderer.js');
});

it('sets bidResponse.ttlBuffer from adUnit.ttlBuffer', () => {
adUnits[0].ttlBuffer = 0;
auction.callBids();
expect(auction.getBidsReceived()[0].ttlBuffer).to.eql(0);
});
});

describe('when auction timeout is 20', function () {
Expand Down
34 changes: 34 additions & 0 deletions test/spec/unit/core/targeting_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,40 @@ describe('targeting tests', function () {
bidCacheFilterFunction = undef;
});

describe('isBidNotExpired', () => {
let clock;
beforeEach(() => {
clock = sandbox.useFakeTimers(0);
});

Object.entries({
'bid.ttlBuffer': (bid, ttlBuffer) => {
bid.ttlBuffer = ttlBuffer
},
'setConfig({ttlBuffer})': (_, ttlBuffer) => {
config.setConfig({ttlBuffer})
},
}).forEach(([t, setup]) => {
describe(`respects ${t}`, () => {
[0, 2].forEach(ttlBuffer => {
it(`when ttlBuffer is ${ttlBuffer}`, () => {
const bid = {
responseTimestamp: 0,
ttl: 10,
}
setup(bid, ttlBuffer);

expect(filters.isBidNotExpired(bid)).to.be.true;
clock.tick((bid.ttl - ttlBuffer) * 1000 - 100);
expect(filters.isBidNotExpired(bid)).to.be.true;
clock.tick(101);
expect(filters.isBidNotExpired(bid)).to.be.false;
});
});
});
});
});

describe('getAllTargeting', function () {
let amBidsReceivedStub;
let amGetAdUnitsStub;
Expand Down
12 changes: 11 additions & 1 deletion test/spec/unit/pbjs_api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,7 @@ describe('Unit: Prebid Module', function () {

describe('requestBids', function () {
let logMessageSpy;
let makeRequestsStub;
let makeRequestsStub, createAuctionStub;
let adUnits;
let clock;
before(function () {
Expand Down Expand Up @@ -1670,6 +1670,16 @@ describe('Unit: Prebid Module', function () {
})
})
})

it('should transfer ttlBuffer to adUnit.ttlBuffer', () => {
$$PREBID_GLOBAL$$.requestBids({
ttlBuffer: 123,
adUnits: [adUnits[0], {...adUnits[0], ttlBuffer: 0}]
});
sinon.assert.calledWithMatch(auctionModule.newAuction, {
adUnits: sinon.match((units) => units[0].ttlBuffer === 123 && units[1].ttlBuffer === 0)
})
});
})

describe('requestBids', function () {
Expand Down

0 comments on commit 297bb48

Please sign in to comment.