Skip to content

Commit

Permalink
PubMatic bid adapter: support for FPD & Preauction module (#6623)
Browse files Browse the repository at this point in the history
  • Loading branch information
pm-harshad-mane authored and idettman committed May 21, 2021
1 parent a0aca93 commit 690a4b3
Show file tree
Hide file tree
Showing 2 changed files with 249 additions and 0 deletions.
41 changes: 41 additions & 0 deletions modules/pubmaticBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,13 +645,45 @@ function _createImpressionObject(bid, conf) {
impObj.banner = bannerObj;
}

_addImpressionFPD(impObj, bid);

_addFloorFromFloorModule(impObj, bid);

return impObj.hasOwnProperty(BANNER) ||
impObj.hasOwnProperty(NATIVE) ||
impObj.hasOwnProperty(VIDEO) ? impObj : UNDEFINED;
}

function _addImpressionFPD(imp, bid) {
const ortb2 = {...utils.deepAccess(bid, 'ortb2Imp.ext.data')};
Object.keys(ortb2).forEach(prop => {
/**
* Prebid AdSlot
* @type {(string|undefined)}
*/
if (prop === 'pbadslot') {
if (typeof ortb2[prop] === 'string' && ortb2[prop]) utils.deepSetValue(imp, 'ext.data.pbadslot', ortb2[prop]);
} else if (prop === 'adserver') {
/**
* Copy GAM AdUnit and Name to imp
*/
['name', 'adslot'].forEach(name => {
/** @type {(string|undefined)} */
const value = utils.deepAccess(ortb2, `adserver.${name}`);
if (typeof value === 'string' && value) {
utils.deepSetValue(imp, `ext.data.adserver.${name.toLowerCase()}`, value);
// copy GAM ad unit id as imp[].ext.dfp_ad_unit_code
if (name === 'adslot') {
utils.deepSetValue(imp, `ext.dfp_ad_unit_code`, value);
}
}
});
} else {
utils.deepSetValue(imp, `ext.data.${prop}`, ortb2[prop]);
}
});
}

function _addFloorFromFloorModule(impObj, bid) {
let bidFloor = -1;
// get lowest floor from floorModule
Expand Down Expand Up @@ -998,6 +1030,15 @@ export const spec = {
_handleEids(payload, validBidRequests);
_blockedIabCategoriesValidation(payload, blockedIabCategories);

// First Party Data
const commonFpd = config.getConfig('ortb2') || {};
if (commonFpd.site) {
utils.mergeDeep(payload, {site: commonFpd.site});
}
if (commonFpd.user) {
utils.mergeDeep(payload, {user: commonFpd.user});
}

// Note: Do not move this block up
// if site object is set in Prebid config then we need to copy required fields from site into app and unset the site object
if (typeof config.getConfig('app') === 'object') {
Expand Down
208 changes: 208 additions & 0 deletions test/spec/modules/pubmaticBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,214 @@ describe('PubMatic adapter', function () {
expect(data2.regs).to.equal(undefined);// USP/CCPAs
});

describe('FPD', function() {
let newRequest;

it('ortb2.site should be merged in the request', function() {
let sandbox = sinon.sandbox.create();
sandbox.stub(config, 'getConfig').callsFake(key => {
const config = {
'ortb2': {
site: {
domain: 'page.example.com',
cat: ['IAB2'],
sectioncat: ['IAB2-2']
}
}
};
return config[key];
});
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.site.domain).to.equal('page.example.com');
expect(data.site.cat).to.deep.equal(['IAB2']);
expect(data.site.sectioncat).to.deep.equal(['IAB2-2']);
sandbox.restore();
});

it('ortb2.user should be merged in the request', function() {
let sandbox = sinon.sandbox.create();
sandbox.stub(config, 'getConfig').callsFake(key => {
const config = {
'ortb2': {
user: {
yob: 1985
}
}
};
return config[key];
});
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.user.yob).to.equal(1985);
sandbox.restore();
});

describe('ortb2Imp', function() {
describe('ortb2Imp.ext.data.pbadslot', function() {
beforeEach(function () {
if (bidRequests[0].hasOwnProperty('ortb2Imp')) {
delete bidRequests[0].ortb2Imp;
}
});

it('should not send if imp[].ext.data object is invalid', function() {
bidRequests[0].ortb2Imp = {
ext: {}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.imp[0].ext).to.not.have.property('data');
});

it('should not send if imp[].ext.data.pbadslot is undefined', function() {
bidRequests[0].ortb2Imp = {
ext: {
data: {
}
}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
if (data.imp[0].ext.data) {
expect(data.imp[0].ext.data).to.not.have.property('pbadslot');
} else {
expect(data.imp[0].ext).to.not.have.property('data');
}
});

it('should not send if imp[].ext.data.pbadslot is empty string', function() {
bidRequests[0].ortb2Imp = {
ext: {
data: {
pbadslot: ''
}
}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
if (data.imp[0].ext.data) {
expect(data.imp[0].ext.data).to.not.have.property('pbadslot');
} else {
expect(data.imp[0].ext).to.not.have.property('data');
}
});

it('should send if imp[].ext.data.pbadslot is string', function() {
bidRequests[0].ortb2Imp = {
ext: {
data: {
pbadslot: 'abcd'
}
}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.imp[0].ext.data).to.have.property('pbadslot');
expect(data.imp[0].ext.data.pbadslot).to.equal('abcd');
});
});

describe('ortb2Imp.ext.data.adserver', function() {
beforeEach(function () {
if (bidRequests[0].hasOwnProperty('ortb2Imp')) {
delete bidRequests[0].ortb2Imp;
}
});

it('should not send if imp[].ext.data object is invalid', function() {
bidRequests[0].ortb2Imp = {
ext: {}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.imp[0].ext).to.not.have.property('data');
});

it('should not send if imp[].ext.data.adserver is undefined', function() {
bidRequests[0].ortb2Imp = {
ext: {
data: {
}
}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
if (data.imp[0].ext.data) {
expect(data.imp[0].ext.data).to.not.have.property('adserver');
} else {
expect(data.imp[0].ext).to.not.have.property('data');
}
});

it('should send', function() {
let adSlotValue = 'abc';
bidRequests[0].ortb2Imp = {
ext: {
data: {
adserver: {
name: 'GAM',
adslot: adSlotValue
}
}
}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.imp[0].ext.data.adserver.name).to.equal('GAM');
expect(data.imp[0].ext.data.adserver.adslot).to.equal(adSlotValue);
expect(data.imp[0].ext.dfp_ad_unit_code).to.equal(adSlotValue);
});
});

describe('ortb2Imp.ext.data.other', function() {
beforeEach(function () {
if (bidRequests[0].hasOwnProperty('ortb2Imp')) {
delete bidRequests[0].ortb2Imp;
}
});

it('should not send if imp[].ext.data object is invalid', function() {
bidRequests[0].ortb2Imp = {
ext: {}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.imp[0].ext).to.not.have.property('data');
});

it('should not send if imp[].ext.data.other is undefined', function() {
bidRequests[0].ortb2Imp = {
ext: {
data: {
}
}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
if (data.imp[0].ext.data) {
expect(data.imp[0].ext.data).to.not.have.property('other');
} else {
expect(data.imp[0].ext).to.not.have.property('data');
}
});

it('ortb2Imp.ext.data.other', function() {
bidRequests[0].ortb2Imp = {
ext: {
data: {
other: 1234
}
}
};
const request = spec.buildRequests(bidRequests, {});
let data = JSON.parse(request.data);
expect(data.imp[0].ext.data.other).to.equal(1234);
});
});
});
});

describe('setting imp.floor using floorModule', function() {
/*
Use the minimum value among floor from floorModule per mediaType
Expand Down

0 comments on commit 690a4b3

Please sign in to comment.