Skip to content

Commit

Permalink
Dailymotion bid adapter: add ortb converter and floor price support
Browse files Browse the repository at this point in the history
  • Loading branch information
stephane-ein authored and Kevin Siow committed Feb 19, 2025
1 parent 17c3b41 commit 94465ad
Show file tree
Hide file tree
Showing 3 changed files with 620 additions and 44 deletions.
64 changes: 45 additions & 19 deletions modules/dailymotionBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,43 @@
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
import { VIDEO } from '../src/mediaTypes.js';
import { deepAccess } from '../src/utils.js';
import { config } from '../src/config.js';
import { userSync } from '../src/userSync.js';

const DAILYMOTION_VENDOR_ID = 573;

const dailymotionOrtbConverter = ortbConverter({
context: {
netRevenue: true,
ttl: 600,
},
imp(buildImp, bidRequest, context) {
const imp = buildImp(bidRequest, context);

if (typeof bidRequest.getFloor === 'function') {
const size = imp.w > 0 && imp.h > 0 ? [imp.w, imp.h] : '*';

const floorInfo = bidRequest.getFloor({
currency: 'USD',
mediaType: 'video', // or '*' for all the mediaType
size
}) || {};

if (floorInfo.floor && floorInfo.currency) {
imp.bidfloor = floorInfo.floor;
imp.bidfloorcur = floorInfo.currency;
}
}

return imp;
},
});

function isArrayFilled (_array) {
return _array && Array.isArray(_array) && _array.length > 0;
}

/**
* Get video metadata from bid request
*
Expand All @@ -23,6 +55,10 @@ function getVideoMetadata(bidRequest, bidderRequest) {
// Content object is either from Object: Site or Object: App
const contentObj = deepAccess(siteOrAppObj, 'content')

const contentCattax = deepAccess(contentObj, 'cattax', 0);
const isContentCattaxV1 = contentCattax === 1;
const isContentCattaxV2 = [2, 5, 6].includes(contentCattax);

const parsedContentData = {
// Store as object keys to ensure uniqueness
iabcat1: {},
Expand All @@ -49,14 +85,16 @@ function getVideoMetadata(bidRequest, bidderRequest) {
const videoMetadata = {
description: videoParams.description || '',
duration: videoParams.duration || deepAccess(contentObj, 'len', 0),
iabcat1: Array.isArray(videoParams.iabcat1)
iabcat1: isArrayFilled(videoParams.iabcat1)
? videoParams.iabcat1
: Array.isArray(deepAccess(contentObj, 'cat'))
: (isArrayFilled(deepAccess(contentObj, 'cat')) && isContentCattaxV1)
? contentObj.cat
: Object.keys(parsedContentData.iabcat1),
iabcat2: Array.isArray(videoParams.iabcat2)
iabcat2: isArrayFilled(videoParams.iabcat2)
? videoParams.iabcat2
: Object.keys(parsedContentData.iabcat2),
: (isArrayFilled(deepAccess(contentObj, 'cat')) && isContentCattaxV2)
? contentObj.cat
: Object.keys(parsedContentData.iabcat2),
id: videoParams.id || deepAccess(contentObj, 'id', ''),
lang: videoParams.lang || deepAccess(contentObj, 'language', ''),
livestream: typeof videoParams.livestream === 'number'
Expand Down Expand Up @@ -153,6 +191,7 @@ export const spec = {
* @return ServerRequest Info describing the request to the server.
*/
buildRequests: function(validBidRequests = [], bidderRequest) {
const ortbData = dailymotionOrtbConverter.toORTB({ bidRequests: validBidRequests, bidderRequest });
// check consent to be able to read user cookie
const allowCookieReading =
// No GDPR applies
Expand Down Expand Up @@ -184,6 +223,7 @@ export const spec = {
url: 'https://pb.dmxleo.com',
data: {
pbv: '$prebid.version$',
ortb: ortbData,
bidder_request: {
gdprConsent: {
apiVersion: deepAccess(bidderRequest, 'gdprConsent.apiVersion', 1),
Expand All @@ -206,20 +246,6 @@ export const spec = {
api_key: bid.params.apiKey,
ts: bid.params.dmTs,
},
// Cast boolean in any case (value should be 0 or 1) to ensure type
coppa: !!deepAccess(bidderRequest, 'ortb2.regs.coppa'),
// In app context, we need to retrieve additional informations
...(!deepAccess(bidderRequest, 'ortb2.site') && !!deepAccess(bidderRequest, 'ortb2.app') ? {
appBundle: deepAccess(bidderRequest, 'ortb2.app.bundle', ''),
appStoreUrl: deepAccess(bidderRequest, 'ortb2.app.storeurl', ''),
} : {}),
...(deepAccess(bidderRequest, 'ortb2.device') ? {
device: {
lmt: deepAccess(bidderRequest, 'ortb2.device.lmt', null),
ifa: deepAccess(bidderRequest, 'ortb2.device.ifa', ''),
atts: deepAccess(bidderRequest, 'ortb2.device.ext.atts', 0),
},
} : {}),
userSyncEnabled: isUserSyncEnabled(),
request: {
adUnitCode: deepAccess(bid, 'adUnitCode', ''),
Expand Down Expand Up @@ -261,7 +287,7 @@ export const spec = {
* @param {*} serverResponse A successful response from the server.
* @return {Bid[]} An array of bids which were nested inside the server.
*/
interpretResponse: serverResponse => serverResponse?.body ? [serverResponse.body] : [],
interpretResponse: serverResponse => serverResponse?.body?.cpm ? [serverResponse.body] : [],

/**
* Retrieves user synchronization URLs based on provided options and consents.
Expand Down
137 changes: 123 additions & 14 deletions modules/dailymotionBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ Maintainer: [email protected]
Dailymotion prebid adapter.
Supports video ad units in instream context.

### Usage

Make sure to have the following modules listed while building prebid : `priceFloors,dailymotionBidAdapter`

`priceFloors` module is needed to retrieve the price floor: https://docs.prebid.org/dev-docs/modules/floors.html

```shell
gulp build --modules=priceFloors,dailymotionBidAdapter
```

### Configuration options

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:
Expand Down Expand Up @@ -58,6 +68,116 @@ pbjs.setConfig({
});
```

#### Price floor

The price floor can be set at the ad unit level, for example :

```javascript
const adUnits = [{
floors: {
currency: 'USD',
schema: {
fields: [ 'mediaType', 'size' ]
},
values: {
'video|300x250': 2.22,
'video|*': 1
}
},
bids: [{
bidder: 'dailymotion',
params: {
apiKey: 'dailymotion-testing',
}
}],
code: 'test-ad-unit',
mediaTypes: {
video: {
playerSize: [300, 250],
context: 'instream',
},
}
}];

// Do not forget to set an empty object for "floors" to active the price floor module
pbjs.setConfig({floors: {}});
```

The following request will be sent to Dailymotion Prebid Service :

```javascript
{
"pbv": "9.23.0-pre",
"ortb": {
"imp": [
{
...
"bidfloor": 2.22,
"bidfloorcur": "USD"
}
],
}
...
}
```

Or the price floor can be set at the package level, for example :

```javascript
const adUnits = [
{
bids: [{
bidder: 'dailymotion',
params: {
apiKey: 'dailymotion-testing',
}
}],
code: 'test-ad-unit',
mediaTypes: {
video: {
playerSize: [1280,720],
context: 'instream',
},
}
}
];

pbjs.setConfig({
floors: {
data: {
currency: 'USD',
schema: {
fields: [ 'mediaType', 'size' ]
},
values: {
'video|300x250': 2.22,
'video|*': 1
}
}
}
})
```

This will send the following bid floor in the request to Daiymotion Prebid Service :

```javascript
{
"pbv": "9.23.0-pre",
"ortb": {
"imp": [
{
...
"bidfloor": 1,
"bidfloorcur": "USD"
}
],
...
}
}
```

You can also [set dynamic floors](https://docs.prebid.org/dev-docs/modules/floors.html#bid-adapter-interface).

### Test Parameters

By setting the following bid parameters, you'll get a constant response to any request, to validate your adapter integration:
Expand Down Expand Up @@ -142,6 +262,7 @@ const adUnits = [
private: false,
tags: 'tag_1,tag_2,tag_3',
title: 'test video',
url: 'https://test.com/testvideo'
topics: 'topic_1, topic_2',
isCreatedForKids: false,
videoViewsInSession: 1,
Expand All @@ -161,7 +282,7 @@ const adUnits = [
maxduration: 30,
playbackmethod: [3],
plcmt: 1,
protocols: [7, 8, 11, 12, 13, 14]
protocols: [7, 8, 11, 12, 13, 14],
startdelay: 0,
w: 1280,
h: 720,
Expand Down Expand Up @@ -206,16 +327,4 @@ If you already specify [First-Party data](https://docs.prebid.org/features/first
| `ortb2.site.content.keywords` | `tags` |
| `ortb2.site.content.title` | `title` |
| `ortb2.site.content.url` | `url` |
| `ortb2.app.bundle` | N/A |
| `ortb2.app.storeurl` | N/A |
| `ortb2.device.lmt` | N/A |
| `ortb2.device.ifa` | N/A |
| `ortb2.device.ext.atts` | N/A |

### Integrating the adapter

To use the adapter with any non-test request, you first need to ask an API key from Dailymotion. Please contact us through **[email protected]**.

You will then be able to use it within the bid parameters before making a bid request.

This API key will ensure proper identification of your inventory and allow you to get real bids.
| `ortb2.*` | N/A |
Loading

0 comments on commit 94465ad

Please sign in to comment.