Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DeepIntent Bid Adapter: add bid floor support #12266

Merged
merged 7 commits into from
Sep 25, 2024
42 changes: 42 additions & 0 deletions libraries/deepintentUtils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { isInteger } from '../../src/utils.js';

export const COMMON_ORTB_VIDEO_PARAMS = {
'mimes': (value) => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'),
'minduration': (value) => isInteger(value),
'maxduration': (value) => isInteger(value),
'protocols': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 10),
'w': (value) => isInteger(value),
'h': (value) => isInteger(value),
'startdelay': (value) => isInteger(value),
'linearity': (value) => [1, 2].indexOf(value) !== -1,
'skip': (value) => [0, 1].indexOf(value) !== -1,
'skipmin': (value) => isInteger(value),
'skipafter': (value) => isInteger(value),
'sequence': (value) => isInteger(value),
'battr': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 17),
'maxextended': (value) => isInteger(value),
'minbitrate': (value) => isInteger(value),
'maxbitrate': (value) => isInteger(value),
'boxingallowed': (value) => [0, 1].indexOf(value) !== -1,
'playbackmethod': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6),
'playbackend': (value) => [1, 2, 3].indexOf(value) !== -1,
'api': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6)
};

export function formatResponse(bid) {
return {
requestId: bid && bid.impid ? bid.impid : undefined,
cpm: bid && bid.price ? bid.price : 0.0,
width: bid && bid.w ? bid.w : 0,
height: bid && bid.h ? bid.h : 0,
ad: bid && bid.adm ? bid.adm : '',
meta: {
advertiserDomains: bid && bid.adomain ? bid.adomain : []
},
creativeId: bid && bid.crid ? bid.crid : undefined,
netRevenue: false,
currency: bid && bid.cur ? bid.cur : 'USD',
ttl: 300,
dealId: bid && bid.dealId ? bid.dealId : undefined
}
}
65 changes: 24 additions & 41 deletions modules/deepintentBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
import { generateUUID, deepSetValue, deepAccess, isArray, isInteger, logError, logWarn } from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {BANNER, VIDEO} from '../src/mediaTypes.js';
import { generateUUID, deepSetValue, deepAccess, isArray, isFn, isPlainObject, logError, logWarn } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { COMMON_ORTB_VIDEO_PARAMS, formatResponse } from '../libraries/deepintentUtils/index.js';
const BIDDER_CODE = 'deepintent';
const GVL_ID = 541;
const BIDDER_ENDPOINT = 'https://prebid.deepintent.com/prebid';
const USER_SYNC_URL = 'https://cdn.deepintent.com/syncpixel.html';
const DI_M_V = '1.0.0';
export const ORTB_VIDEO_PARAMS = {
'mimes': (value) => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'),
'minduration': (value) => isInteger(value),
'maxduration': (value) => isInteger(value),
'protocols': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 10),
'w': (value) => isInteger(value),
'h': (value) => isInteger(value),
'startdelay': (value) => isInteger(value),
...COMMON_ORTB_VIDEO_PARAMS,
'plcmt': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 5),
'linearity': (value) => [1, 2].indexOf(value) !== -1,
'skip': (value) => [0, 1].indexOf(value) !== -1,
'skipmin': (value) => isInteger(value),
'skipafter': (value) => isInteger(value),
'sequence': (value) => isInteger(value),
'battr': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 17),
'maxextended': (value) => isInteger(value),
'minbitrate': (value) => isInteger(value),
'maxbitrate': (value) => isInteger(value),
'boxingallowed': (value) => [0, 1].indexOf(value) !== -1,
'playbackmethod': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6),
'playbackend': (value) => [1, 2, 3].indexOf(value) !== -1,
'delivery': (value) => [1, 2, 3].indexOf(value) !== -1,
'pos': (value) => [0, 1, 2, 3, 4, 5, 6, 7].indexOf(value) !== -1,
'api': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6)
};
export const spec = {
code: BIDDER_CODE,
Expand Down Expand Up @@ -155,29 +137,13 @@ function clean(obj) {
}
}

function formatResponse(bid) {
return {
requestId: bid && bid.impid ? bid.impid : undefined,
cpm: bid && bid.price ? bid.price : 0.0,
width: bid && bid.w ? bid.w : 0,
height: bid && bid.h ? bid.h : 0,
ad: bid && bid.adm ? bid.adm : '',
meta: {
advertiserDomains: bid && bid.adomain ? bid.adomain : []
},
creativeId: bid && bid.crid ? bid.crid : undefined,
netRevenue: false,
currency: bid && bid.cur ? bid.cur : 'USD',
ttl: 300,
dealId: bid && bid.dealId ? bid.dealId : undefined
}
}

function buildImpression(bid) {
let impression = {};
const floor = getFloor(bid);
impression = {
id: bid.bidId,
tagid: bid.params.tagId || '',
...(!isNaN(floor) && { bidfloor: floor }),
secure: window.location.protocol === 'https:' ? 1 : 0,
displaymanager: 'di_prebid',
displaymanagerver: DI_M_V,
Expand All @@ -192,6 +158,23 @@ function buildImpression(bid) {
return impression;
}

function getFloor(bidRequest) {
if (!isFn(bidRequest.getFloor)) {
return bidRequest.params?.bidfloor;
}

let floor = bidRequest.getFloor({
currency: 'USD',
mediaType: '*',
size: '*'
});

if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'USD') {
return floor.floor;
}
return null;
}

function _buildVideo(bid) {
const videoObj = {};
const videoAdUnitParams = deepAccess(bid, 'mediaTypes.video', {});
Expand Down
116 changes: 60 additions & 56 deletions modules/deepintentBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,64 +15,70 @@ Module that connects to Deepintent's demand sources.
# Banner Test Request
```
var adUnits = [
{
code: 'di_adUnit1',
mediaTypes: {
banner: {
sizes: [[300, 250]], // a display size, only first one will be picked up since multiple ad sizes are not supported yet
}
}
bids: [
{
bidder: 'deepintent',
params: {
tagId: '1300', // Required parameter
w: 300, // Width and Height here will override sizes in mediatype
h: 250,
pos: 1,
custom: { // Custom parameters in form of key value pairs
user_min_age: 18
}
}
}
]
}
];
{
code: 'di_adUnit1',
mediaTypes: {
banner: {
sizes: [[300, 250]], // a display size, only first one will be picked up since multiple ad sizes are not supported yet
},
},
bids: [
{
bidder: 'deepintent',
params: {
tagId: '1300', // Required parameter
bidfloor: 1.5, // optional
w: 300, // Width and Height here will override sizes in mediatype
h: 250,
pos: 1,
custom: {
// Custom parameters in form of key value pairs
user_min_age: 18,
},
},
},
],
},
];
```

# Sample Video Ad Unit
```
var adVideoAdUnits = [
{
code: 'test-div-video',
mediaTypes: {
video: {
playerSize: [640, 480], // required
context: 'instream' //required
}
},
bids: [{
bidder: 'deepintent',
params: {
tagId: '1300', // Required parameter // required
video: {
mimes: ['video/mp4','video/x-flv'], // required
skippable: true, // optional
minduration: 5, // optional
maxduration: 30, // optional
startdelay: 5, // optional
playbackmethod: [1,3], // optional
api: [ 1, 2 ], // optional
protocols: [ 2, 3 ], // optional
battr: [ 13, 14 ], // optional
linearity: 1, // optional
plcmt: 2, // optional
minbitrate: 10, // optional
maxbitrate: 10 // optional
}
}
}]
}]
var adVideoAdUnits = [
{
code: 'test-div-video',
mediaTypes: {
video: {
playerSize: [640, 480], // required
context: 'instream', //required
},
},
bids: [
{
bidder: 'deepintent',
params: {
tagId: '1300', // Required parameter // required
bidfloor: 1.5, // optional
video: {
mimes: ['video/mp4', 'video/x-flv'], // required
skippable: true, // optional
minduration: 5, // optional
maxduration: 30, // optional
startdelay: 5, // optional
playbackmethod: [1, 3], // optional
api: [1, 2], // optional
protocols: [2, 3], // optional
battr: [13, 14], // optional
linearity: 1, // optional
plcmt: 2, // optional
minbitrate: 10, // optional
maxbitrate: 10, // optional
},
},
},
],
},
];
```

###Recommended User Sync Configuration
Expand All @@ -84,6 +90,4 @@ pbjs.setConfig({
enabledBidders: ['deepintent'],
syncDelay: 3000
}});


```
19 changes: 1 addition & 18 deletions modules/relevatehealthBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { formatResponse } from '../libraries/deepintentUtils/index.js';
import {
registerBidder
} from '../src/adapters/bidderFactory.js';
Expand Down Expand Up @@ -119,24 +120,6 @@ function getSite(bidderRequest) {
}
return site;
}
// Function to format response
function formatResponse(bid) {
return {
requestId: bid && bid.impid ? bid.impid : undefined,
cpm: bid && bid.price ? bid.price : 0.0,
width: bid && bid.w ? bid.w : 0,
height: bid && bid.h ? bid.h : 0,
ad: bid && bid.adm ? bid.adm : '',
meta: {
advertiserDomains: bid && bid.adomain ? bid.adomain : []
},
creativeId: bid && bid.crid ? bid.crid : undefined,
netRevenue: false,
currency: bid && bid.cur ? bid.cur : 'USD',
ttl: 300,
dealId: bid && bid.dealId ? bid.dealId : undefined
};
}
// Function to build the user object
function buildUser(bid) {
if (bid && bid.params) {
Expand Down
22 changes: 2 additions & 20 deletions modules/sovrnBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,18 @@ import {
BANNER,
VIDEO
} from '../src/mediaTypes.js'
import { COMMON_ORTB_VIDEO_PARAMS } from '../libraries/deepintentUtils/index.js';

/**
* @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid
*/

const ORTB_VIDEO_PARAMS = {
'mimes': (value) => Array.isArray(value) && value.length > 0 && value.every(v => typeof v === 'string'),
'minduration': (value) => isInteger(value),
'maxduration': (value) => isInteger(value),
'protocols': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 10),
'w': (value) => isInteger(value),
'h': (value) => isInteger(value),
'startdelay': (value) => isInteger(value),
...COMMON_ORTB_VIDEO_PARAMS,
'placement': (value) => isInteger(value) && value >= 1 && value <= 5,
'plcmt': (value) => isInteger(value) && value >= 1 && value <= 4,
'linearity': (value) => [1, 2].indexOf(value) !== -1,
'skip': (value) => [0, 1].indexOf(value) !== -1,
'skipmin': (value) => isInteger(value),
'skipafter': (value) => isInteger(value),
'sequence': (value) => isInteger(value),
'battr': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 17),
'maxextended': (value) => isInteger(value),
'minbitrate': (value) => isInteger(value),
'maxbitrate': (value) => isInteger(value),
'boxingallowed': (value) => [0, 1].indexOf(value) !== -1,
'playbackmethod': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6),
'playbackend': (value) => [1, 2, 3].indexOf(value) !== -1,
'delivery': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 3),
'pos': (value) => isInteger(value) && value >= 1 && value <= 7,
'api': (value) => Array.isArray(value) && value.every(v => v >= 1 && v <= 6)
}

const REQUIRED_VIDEO_PARAMS = {
Expand Down
16 changes: 16 additions & 0 deletions test/spec/modules/deepintentBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,22 @@ describe('Deepintent adapter', function () {
expect(data.imp[0].displaymanager).to.equal('di_prebid');
expect(data.imp[0].displaymanagerver).to.equal('1.0.0');
});
it('bid request check: bidfloor check', function() {
const requestClone = utils.deepClone(request);
let bRequest = spec.buildRequests(requestClone);
let data = JSON.parse(bRequest.data);
expect(data.imp[0].bidfloor).to.not.exist;

requestClone[0].params.bidfloor = 0;
bRequest = spec.buildRequests(requestClone);
data = JSON.parse(bRequest.data);
expect(data.imp[0].bidfloor).to.equal(0);

requestClone[0].params.bidfloor = 1.2;
bRequest = spec.buildRequests(requestClone);
data = JSON.parse(bRequest.data);
expect(data.imp[0].bidfloor).to.equal(1.2);
});
it('bid request check: user object check', function () {
let bRequest = spec.buildRequests(request);
let data = JSON.parse(bRequest.data);
Expand Down