Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions modules/adoceanBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { _each, isStr, isArray, parseSizesInput } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';

const BIDDER_CODE = 'adocean';
const URL_SAFE_FIELDS = {
slaves: true
};

function buildEndpointUrl(emitter, payloadMap) {
const payload = [];
_each(payloadMap, function(v, k) {
payload.push(k + '=' + (URL_SAFE_FIELDS[k] ? v : encodeURIComponent(v)));
});

const randomizedPart = Math.random().toString().slice(2);
return 'https://' + emitter + '/_' + randomizedPart + '/ad.json?' + payload.join('&');
}

function buildRequest(bid, gdprConsent) {
const emitter = bid.params.emitter;
const masterId = bid.params.masterId;
const slaveId = bid.params.slaveId;
const payload = {
id: masterId,
slaves: ""
};
if (gdprConsent) {
payload.gdpr_consent = gdprConsent.consentString || undefined;
payload.gdpr = gdprConsent.gdprApplies ? 1 : 0;
}

if (bid.userId && bid.userId.gemiusId) {
payload.aouserid = bid.userId.gemiusId;
}

const bidIdMap = {};
const uniquePartLength = 10;

const rawSlaveId = bid.params.slaveId.replace('adocean', '');
payload.slaves = rawSlaveId.slice(-uniquePartLength);

bidIdMap[slaveId] = bid.bidId;

if (bid.mediaTypes.video) {
if (bid.mediaTypes.video.context === 'instream') {
if (bid.mediaTypes.video.maxduration) {
payload.dur = bid.mediaTypes.video.maxduration;
payload.maxdur = bid.mediaTypes.video.maxduration;
}
if (bid.mediaTypes.video.minduration) {
payload.mindur = bid.mediaTypes.video.minduration;
}
payload.spots = 1;
}
if (bid.mediaTypes.video.context === 'adpod') {
const durationRangeSec = bid.mediaTypes.video.durationRangeSec;
if (!bid.mediaTypes.video.adPodDurationSec || !isArray(durationRangeSec) || durationRangeSec.length === 0) {
return;
}
const spots = calculateAdPodSpotsNumber(bid.mediaTypes.video.adPodDurationSec, bid.mediaTypes.video.durationRangeSec);
const maxDuration = Math.max(...durationRangeSec);
payload.dur = bid.mediaTypes.video.adPodDurationSec;
payload.maxdur = maxDuration;
payload.spots = spots;
}
} else if (bid.mediaTypes.banner) {
payload.aosize = parseSizesInput(bid.mediaTypes.banner.sizes).join(',');
}

return {
method: 'GET',
url: buildEndpointUrl(emitter, payload),
data: '',
bidIdMap: bidIdMap
};
}

function calculateAdPodSpotsNumber(adPodDurationSec, durationRangeSec) {
const minAllowedDuration = Math.min(...durationRangeSec);
const numberOfSpots = Math.floor(adPodDurationSec / minAllowedDuration);
return numberOfSpots;
}

function interpretResponse(placementResponse, bidRequest, bids) {
const requestId = bidRequest.bidIdMap[placementResponse.id];
if (!placementResponse.error && requestId) {
if (!placementResponse.code || !placementResponse.height || !placementResponse.width || !placementResponse.price) {
return;
}
let adCode = decodeURIComponent(placementResponse.code);

const bid = {
cpm: parseFloat(placementResponse.price),
currency: placementResponse.currency,
height: parseInt(placementResponse.height, 10),
requestId: requestId,
width: parseInt(placementResponse.width, 10),
netRevenue: false,
ttl: parseInt(placementResponse.ttl),
creativeId: placementResponse.crid,
meta: {
advertiserDomains: placementResponse.adomain || []
}
};
if (placementResponse.isVideo) {
bid.meta.mediaType = VIDEO;
bid.vastXml = adCode;
} else {
bid.meta.mediaType = BANNER;
bid.ad = adCode;
}

bids.push(bid);
}
}

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER, VIDEO],

isBidRequestValid: function(bid) {
const requiredParams = ['slaveId', 'masterId', 'emitter'];
if (requiredParams.some(name => !isStr(bid.params[name]) || !bid.params[name].length)) {
return false;
}

if (bid.mediaTypes.banner) {
return true;
}
if (bid.mediaTypes.video) {
if (bid.mediaTypes.video.context === 'instream') {
return true;
}
if (bid.mediaTypes.video.context === 'adpod') {
return !bid.mediaTypes.video.requireExactDuration;
}
}
return false;
},

buildRequests: function(validBidRequests, bidderRequest) {
let requests = [];

_each(validBidRequests, function(bidRequest) {
requests.push(buildRequest(bidRequest, bidderRequest.gdprConsent));
});

return requests;
},

interpretResponse: function(serverResponse, bidRequest) {
let bids = [];

if (isArray(serverResponse.body)) {
_each(serverResponse.body, function(placementResponse) {
interpretResponse(placementResponse, bidRequest, bids);
});
}

return bids;
}
};
registerBidder(spec);
58 changes: 58 additions & 0 deletions modules/adoceanBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Overview

Module Name: AdOcean Bidder Adapter
Module Type: Bidder Adapter
Maintainer: prebid@gemius.com

# Description

AdOcean Bidder Adapter for Prebid.js.
Banner and video formats are supported.

# Test Parameters Banner
```js
var adUnits = [
{
code: 'test-div',
mediaTypes: {
banner: {
sizes: [[300, 200]]
}
},
bids: [
{
bidder: "adocean",
params: {
slaveId: 'adoceanmyaotcpiltmmnj',
masterId: 'ek1AWtSWh3BOa_x2P1vlMQ_uXXJpJcbhsHAY5PFQjWD.D7',
emitter: 'myao.adocean.pl'
}
}
]
}
];
```
# Test Parameters Video
```js
var adUnits = [
{
code: 'test-div',
mediaTypes: {
video: {
context: 'instream',
playerSize: [300, 200]
}
},
bids: [
{
bidder: "adocean",
params: {
slaveId: 'adoceanmyaonenfcoqfnd',
masterId: '2k6gA7RWl08Zn0bi42RV8LNCANpKb6LqhvKzbmK3pzP.U7',
emitter: 'myao.adocean.pl'
}
}
]
}
];
```
Loading
Loading