Skip to content

Commit

Permalink
add a configurable "bidCacheFilterFunction" (#7993)
Browse files Browse the repository at this point in the history
* add a configurable "bidCacheFilterFunction" to determine whether to use a cached bid

* tiny != changed to !==

Co-authored-by: Eric Harper <eharper@rubiconproject.com>
  • Loading branch information
harpere and Eric Harper committed Feb 2, 2022
1 parent 2fb3a83 commit ace3efc
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
8 changes: 8 additions & 0 deletions src/targeting.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,15 @@ export function newTargeting(auctionManager) {
let bidsReceived = auctionManager.getBidsReceived();

if (!config.getConfig('useBidCache')) {
// don't use bid cache (i.e. filter out bids not in the latest auction)
bidsReceived = bidsReceived.filter(bid => latestAuctionForAdUnit[bid.adUnitCode] === bid.auctionId)
} else {
// if custom bid cache filter function exists, run for each bid from
// previous auctions. If it returns true, include bid in bid pool
const filterFunction = config.getConfig('bidCacheFilterFunction');
if (typeof filterFunction === 'function') {
bidsReceived = bidsReceived.filter(bid => latestAuctionForAdUnit[bid.adUnitCode] === bid.auctionId || !!filterFunction(bid))
}
}

bidsReceived = bidsReceived
Expand Down
3 changes: 2 additions & 1 deletion test/fixtures/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ export function getCurrencyRates() {
};
}

export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, adUnitCode, adId, status, ttl, requestId}) {
export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, adUnitCode, adId, status, ttl, requestId, mediaType}) {
let bid = {
'bidderCode': bidder,
'width': '300',
Expand Down Expand Up @@ -1259,6 +1259,7 @@ export function createBidReceived({bidder, cpm, auctionId, responseTimestamp, ad
'hb_pb': cpm,
'foobar': '300x250'
}),
'mediaType': mediaType,
'netRevenue': true,
'currency': 'USD',
'ttl': (!ttl) ? 300 : ttl
Expand Down
93 changes: 93 additions & 0 deletions test/spec/unit/core/targeting_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@ describe('targeting tests', function () {
let sandbox;
let enableSendAllBids = false;
let useBidCache;
let bidCacheFilterFunction;
let undef;

beforeEach(function() {
sandbox = sinon.sandbox.create();
Expand All @@ -241,12 +243,16 @@ describe('targeting tests', function () {
if (key === 'useBidCache') {
return useBidCache;
}
if (key === 'bidCacheFilterFunction') {
return bidCacheFilterFunction;
}
return origGetConfig.apply(config, arguments);
});
});

afterEach(function () {
sandbox.restore();
bidCacheFilterFunction = undef;
});

describe('getAllTargeting', function () {
Expand Down Expand Up @@ -785,6 +791,93 @@ describe('targeting tests', function () {
expect(bids[0].adId).to.equal('adid-2');
});

it('should use bidCacheFilterFunction', function() {
auctionManagerStub.returns([
createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', mediaType: 'banner'}),
createBidReceived({bidder: 'appnexus', cpm: 5, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-0', adId: 'adid-2', mediaType: 'banner'}),
createBidReceived({bidder: 'appnexus', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-3', mediaType: 'banner'}),
createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-1', adId: 'adid-4', mediaType: 'banner'}),
createBidReceived({bidder: 'appnexus', cpm: 27, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-2', adId: 'adid-5', mediaType: 'video'}),
createBidReceived({bidder: 'appnexus', cpm: 25, auctionId: 2, responseTimestamp: 102, adUnitCode: 'code-2', adId: 'adid-6', mediaType: 'video'}),
createBidReceived({bidder: 'appnexus', cpm: 26, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-3', adId: 'adid-7', mediaType: 'video'}),
createBidReceived({bidder: 'appnexus', cpm: 28, auctionId: 2, responseTimestamp: 103, adUnitCode: 'code-3', adId: 'adid-8', mediaType: 'video'}),
]);

let adUnitCodes = ['code-0', 'code-1', 'code-2', 'code-3'];
targetingInstance.setLatestAuctionForAdUnit('code-0', 2);
targetingInstance.setLatestAuctionForAdUnit('code-1', 2);
targetingInstance.setLatestAuctionForAdUnit('code-2', 2);
targetingInstance.setLatestAuctionForAdUnit('code-3', 2);

// Bid Caching On, No Filter Function
useBidCache = true;
bidCacheFilterFunction = undef;
let bids = targetingInstance.getWinningBids(adUnitCodes);

expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-1');
expect(bids[1].adId).to.equal('adid-4');
expect(bids[2].adId).to.equal('adid-5');
expect(bids[3].adId).to.equal('adid-8');

// Bid Caching Off, No Filter Function
useBidCache = false;
bidCacheFilterFunction = undef;
bids = targetingInstance.getWinningBids(adUnitCodes);

expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-2');
expect(bids[1].adId).to.equal('adid-4');
expect(bids[2].adId).to.equal('adid-6');
expect(bids[3].adId).to.equal('adid-8');

// Bid Caching On AGAIN, No Filter Function (should be same as first time)
useBidCache = true;
bidCacheFilterFunction = undef;
bids = targetingInstance.getWinningBids(adUnitCodes);

expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-1');
expect(bids[1].adId).to.equal('adid-4');
expect(bids[2].adId).to.equal('adid-5');
expect(bids[3].adId).to.equal('adid-8');

// Bid Caching On, with Filter Function to Exclude video
useBidCache = true;
let bcffCalled = 0;
bidCacheFilterFunction = bid => {
bcffCalled++;
return bid.mediaType !== 'video';
}
bids = targetingInstance.getWinningBids(adUnitCodes);

expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-1');
expect(bids[1].adId).to.equal('adid-4');
expect(bids[2].adId).to.equal('adid-6');
expect(bids[3].adId).to.equal('adid-8');
// filter function should have been called for each cached bid (4 times)
expect(bcffCalled).to.equal(4);

// Bid Caching Off, with Filter Function to Exclude video
// - should not use cached bids or call the filter function
useBidCache = false;
bcffCalled = 0;
bidCacheFilterFunction = bid => {
bcffCalled++;
return bid.mediaType !== 'video';
}
bids = targetingInstance.getWinningBids(adUnitCodes);

expect(bids.length).to.equal(4);
expect(bids[0].adId).to.equal('adid-2');
expect(bids[1].adId).to.equal('adid-4');
expect(bids[2].adId).to.equal('adid-6');
expect(bids[3].adId).to.equal('adid-8');
// filter function should not have been called
expect(bcffCalled).to.equal(0);
});

it('should not use rendered bid to get winning bid', function () {
let bidsReceived = [
createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'rendered'}),
Expand Down

0 comments on commit ace3efc

Please sign in to comment.