Skip to content

Commit 758f081

Browse files
stephane-einKevin Siow
authored andcommitted
Dailymotion bid adapter: add ortb converter and floor price support
1 parent 13b18fa commit 758f081

3 files changed

Lines changed: 630 additions & 44 deletions

File tree

modules/dailymotionBidAdapter.js

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,43 @@
11
import { registerBidder } from '../src/adapters/bidderFactory.js';
2+
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
23
import { VIDEO } from '../src/mediaTypes.js';
34
import { deepAccess } from '../src/utils.js';
45
import { config } from '../src/config.js';
56
import { userSync } from '../src/userSync.js';
67

78
const DAILYMOTION_VENDOR_ID = 573;
89

10+
const dailymotionOrtbConverter = ortbConverter({
11+
context: {
12+
netRevenue: true,
13+
ttl: 600,
14+
},
15+
imp(buildImp, bidRequest, context) {
16+
const imp = buildImp(bidRequest, context);
17+
18+
if (typeof bidRequest.getFloor === 'function') {
19+
const size = imp.w > 0 && imp.h > 0 ? [imp.w, imp.h] : '*';
20+
21+
const floorInfo = bidRequest.getFloor({
22+
currency: 'USD',
23+
mediaType: 'video', // or '*' for all the mediaType
24+
size
25+
}) || {};
26+
27+
if (floorInfo.floor && floorInfo.currency) {
28+
imp.bidfloor = floorInfo.floor;
29+
imp.bidfloorcur = floorInfo.currency;
30+
}
31+
}
32+
33+
return imp;
34+
},
35+
});
36+
37+
function isArrayFilled (_array) {
38+
return _array && Array.isArray(_array) && _array.length > 0;
39+
}
40+
941
/**
1042
* Get video metadata from bid request
1143
*
@@ -23,6 +55,10 @@ function getVideoMetadata(bidRequest, bidderRequest) {
2355
// Content object is either from Object: Site or Object: App
2456
const contentObj = deepAccess(siteOrAppObj, 'content')
2557

58+
const contentCattax = deepAccess(contentObj, 'cattax', 0);
59+
const isContentCattaxV1 = contentCattax === 1;
60+
const isContentCattaxV2 = [2, 5, 6].includes(contentCattax);
61+
2662
const parsedContentData = {
2763
// Store as object keys to ensure uniqueness
2864
iabcat1: {},
@@ -49,14 +85,16 @@ function getVideoMetadata(bidRequest, bidderRequest) {
4985
const videoMetadata = {
5086
description: videoParams.description || '',
5187
duration: videoParams.duration || deepAccess(contentObj, 'len', 0),
52-
iabcat1: Array.isArray(videoParams.iabcat1)
88+
iabcat1: isArrayFilled(videoParams.iabcat1)
5389
? videoParams.iabcat1
54-
: Array.isArray(deepAccess(contentObj, 'cat'))
90+
: (isArrayFilled(deepAccess(contentObj, 'cat')) && isContentCattaxV1)
5591
? contentObj.cat
5692
: Object.keys(parsedContentData.iabcat1),
57-
iabcat2: Array.isArray(videoParams.iabcat2)
93+
iabcat2: isArrayFilled(videoParams.iabcat2)
5894
? videoParams.iabcat2
59-
: Object.keys(parsedContentData.iabcat2),
95+
: (isArrayFilled(deepAccess(contentObj, 'cat')) && isContentCattaxV2)
96+
? contentObj.cat
97+
: Object.keys(parsedContentData.iabcat2),
6098
id: videoParams.id || deepAccess(contentObj, 'id', ''),
6199
lang: videoParams.lang || deepAccess(contentObj, 'language', ''),
62100
livestream: typeof videoParams.livestream === 'number'
@@ -153,6 +191,7 @@ export const spec = {
153191
* @return ServerRequest Info describing the request to the server.
154192
*/
155193
buildRequests: function(validBidRequests = [], bidderRequest) {
194+
const ortbData = dailymotionOrtbConverter.toORTB({ bidRequests: validBidRequests, bidderRequest });
156195
// check consent to be able to read user cookie
157196
const allowCookieReading =
158197
// No GDPR applies
@@ -184,6 +223,7 @@ export const spec = {
184223
url: 'https://pb.dmxleo.com',
185224
data: {
186225
pbv: '$prebid.version$',
226+
ortb: ortbData,
187227
bidder_request: {
188228
gdprConsent: {
189229
apiVersion: deepAccess(bidderRequest, 'gdprConsent.apiVersion', 1),
@@ -206,20 +246,6 @@ export const spec = {
206246
api_key: bid.params.apiKey,
207247
ts: bid.params.dmTs,
208248
},
209-
// Cast boolean in any case (value should be 0 or 1) to ensure type
210-
coppa: !!deepAccess(bidderRequest, 'ortb2.regs.coppa'),
211-
// In app context, we need to retrieve additional informations
212-
...(!deepAccess(bidderRequest, 'ortb2.site') && !!deepAccess(bidderRequest, 'ortb2.app') ? {
213-
appBundle: deepAccess(bidderRequest, 'ortb2.app.bundle', ''),
214-
appStoreUrl: deepAccess(bidderRequest, 'ortb2.app.storeurl', ''),
215-
} : {}),
216-
...(deepAccess(bidderRequest, 'ortb2.device') ? {
217-
device: {
218-
lmt: deepAccess(bidderRequest, 'ortb2.device.lmt', null),
219-
ifa: deepAccess(bidderRequest, 'ortb2.device.ifa', ''),
220-
atts: deepAccess(bidderRequest, 'ortb2.device.ext.atts', 0),
221-
},
222-
} : {}),
223249
userSyncEnabled: isUserSyncEnabled(),
224250
request: {
225251
adUnitCode: deepAccess(bid, 'adUnitCode', ''),
@@ -261,7 +287,7 @@ export const spec = {
261287
* @param {*} serverResponse A successful response from the server.
262288
* @return {Bid[]} An array of bids which were nested inside the server.
263289
*/
264-
interpretResponse: serverResponse => serverResponse?.body ? [serverResponse.body] : [],
290+
interpretResponse: serverResponse => serverResponse?.body?.cpm ? [serverResponse.body] : [],
265291

266292
/**
267293
* Retrieves user synchronization URLs based on provided options and consents.

modules/dailymotionBidAdapter.md

Lines changed: 123 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ Maintainer: ad-leo-engineering@dailymotion.com
1111
Dailymotion prebid adapter.
1212
Supports video ad units in instream context.
1313

14+
### Usage
15+
16+
Make sure to have the following modules listed while building prebid : `priceFloors,dailymotionBidAdapter`
17+
18+
`priceFloors` module is needed to retrieve the price floor: https://docs.prebid.org/dev-docs/modules/floors.html
19+
20+
```shell
21+
gulp build --modules=priceFloors,dailymotionBidAdapter
22+
```
23+
1424
### Configuration options
1525

1626
Before calling this adapter, you need to at least set a video adUnit in an instream context and the API key in the bid parameters:
@@ -58,6 +68,116 @@ pbjs.setConfig({
5868
});
5969
```
6070

71+
#### Price floor
72+
73+
The price floor can be set at the ad unit level, for example :
74+
75+
```javascript
76+
const adUnits = [{
77+
floors: {
78+
currency: 'USD',
79+
schema: {
80+
fields: [ 'mediaType', 'size' ]
81+
},
82+
values: {
83+
'video|300x250': 2.22,
84+
'video|*': 1
85+
}
86+
},
87+
bids: [{
88+
bidder: 'dailymotion',
89+
params: {
90+
apiKey: 'dailymotion-testing',
91+
}
92+
}],
93+
code: 'test-ad-unit',
94+
mediaTypes: {
95+
video: {
96+
playerSize: [300, 250],
97+
context: 'instream',
98+
},
99+
}
100+
}];
101+
102+
// Do not forget to set an empty object for "floors" to active the price floor module
103+
pbjs.setConfig({floors: {}});
104+
```
105+
106+
The following request will be sent to Dailymotion Prebid Service :
107+
108+
```javascript
109+
{
110+
"pbv": "9.23.0-pre",
111+
"ortb": {
112+
"imp": [
113+
{
114+
...
115+
"bidfloor": 2.22,
116+
"bidfloorcur": "USD"
117+
}
118+
],
119+
}
120+
...
121+
}
122+
```
123+
124+
Or the price floor can be set at the package level, for example :
125+
126+
```javascript
127+
const adUnits = [
128+
{
129+
bids: [{
130+
bidder: 'dailymotion',
131+
params: {
132+
apiKey: 'dailymotion-testing',
133+
}
134+
}],
135+
code: 'test-ad-unit',
136+
mediaTypes: {
137+
video: {
138+
playerSize: [1280,720],
139+
context: 'instream',
140+
},
141+
}
142+
}
143+
];
144+
145+
pbjs.setConfig({
146+
floors: {
147+
data: {
148+
currency: 'USD',
149+
schema: {
150+
fields: [ 'mediaType', 'size' ]
151+
},
152+
values: {
153+
'video|300x250': 2.22,
154+
'video|*': 1
155+
}
156+
}
157+
}
158+
})
159+
```
160+
161+
This will send the following bid floor in the request to Daiymotion Prebid Service :
162+
163+
```javascript
164+
{
165+
"pbv": "9.23.0-pre",
166+
"ortb": {
167+
"imp": [
168+
{
169+
...
170+
"bidfloor": 1,
171+
"bidfloorcur": "USD"
172+
}
173+
],
174+
...
175+
}
176+
}
177+
```
178+
179+
You can also [set dynamic floors](https://docs.prebid.org/dev-docs/modules/floors.html#bid-adapter-interface).
180+
61181
### Test Parameters
62182

63183
By setting the following bid parameters, you'll get a constant response to any request, to validate your adapter integration:
@@ -142,6 +262,7 @@ const adUnits = [
142262
private: false,
143263
tags: 'tag_1,tag_2,tag_3',
144264
title: 'test video',
265+
url: 'https://test.com/testvideo'
145266
topics: 'topic_1, topic_2',
146267
isCreatedForKids: false,
147268
videoViewsInSession: 1,
@@ -161,7 +282,7 @@ const adUnits = [
161282
maxduration: 30,
162283
playbackmethod: [3],
163284
plcmt: 1,
164-
protocols: [7, 8, 11, 12, 13, 14]
285+
protocols: [7, 8, 11, 12, 13, 14],
165286
startdelay: 0,
166287
w: 1280,
167288
h: 720,
@@ -206,16 +327,4 @@ If you already specify [First-Party data](https://docs.prebid.org/features/first
206327
| `ortb2.site.content.keywords` | `tags` |
207328
| `ortb2.site.content.title` | `title` |
208329
| `ortb2.site.content.url` | `url` |
209-
| `ortb2.app.bundle` | N/A |
210-
| `ortb2.app.storeurl` | N/A |
211-
| `ortb2.device.lmt` | N/A |
212-
| `ortb2.device.ifa` | N/A |
213-
| `ortb2.device.ext.atts` | N/A |
214-
215-
### Integrating the adapter
216-
217-
To use the adapter with any non-test request, you first need to ask an API key from Dailymotion. Please contact us through **DailymotionPrebid.js@dailymotion.com**.
218-
219-
You will then be able to use it within the bid parameters before making a bid request.
220-
221-
This API key will ensure proper identification of your inventory and allow you to get real bids.
330+
| `ortb2.*` | N/A |

0 commit comments

Comments
 (0)