Skip to content

Commit

Permalink
Orbidder Bid Adapter: add native support (#7047)
Browse files Browse the repository at this point in the history
* [ORBIDDER] add native support

* [ORBIDDER] fix orbidder tests

* ORBIDDER: fix test parameter documentation
  • Loading branch information
arneschulz1984 authored Jul 6, 2021
1 parent ed0a2f9 commit 089e43a
Show file tree
Hide file tree
Showing 3 changed files with 410 additions and 70 deletions.
89 changes: 71 additions & 18 deletions modules/orbidderBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,52 @@
import {registerBidder} from '../src/adapters/bidderFactory.js';
import { getStorageManager } from '../src/storageManager.js';
import { BANNER, NATIVE } from '../src/mediaTypes.js';
import * as utils from '../src/utils.js';

const storageManager = getStorageManager();

/**
* Determines whether or not the given bid response is valid.
*
* @param {object} bidResponse The bid response to validate.
* @return boolean True if this is a valid bid response, and false if it is not valid.
*/
function isBidResponseValid(bidResponse) {
let requiredKeys = ['requestId', 'cpm', 'ttl', 'creativeId', 'netRevenue', 'currency'];

switch (bidResponse.mediaType) {
case BANNER:
requiredKeys = requiredKeys.concat(['width', 'height', 'ad']);
break;
case NATIVE:
if (!bidResponse.native.hasOwnProperty('impressionTrackers')) {
return false
}
break;
default:
return false
}

for (const key of requiredKeys) {
if (!bidResponse.hasOwnProperty(key)) {
return false
}
}

return true
}

export const spec = {
code: 'orbidder',
hostname: 'https://orbidder.otto.de',
supportedMediaTypes: [BANNER, NATIVE],

/**
* Returns a customzied hostname if 'ov_orbidder_host' is set in the browser's local storage.
* This is only used for integration testing.
*
* @return The hostname bid requests should be sent to.
*/
getHostname() {
let ret = this.hostname;
try {
Expand All @@ -17,13 +56,26 @@ export const spec = {
return ret;
},

/**
* Determines whether or not the given bid request is valid.
*
* @param {object} bid The bid to validate.
* @return boolean True if this is a valid bid, and false if it is not valid.
*/
isBidRequestValid(bid) {
return !!(bid.sizes && bid.bidId && bid.params &&
(bid.params.accountId && (typeof bid.params.accountId === 'string')) &&
(bid.params.placementId && (typeof bid.params.placementId === 'string')) &&
((typeof bid.params.profile === 'undefined') || (typeof bid.params.profile === 'object')));
},

/**
* Build a request from the list of valid BidRequests that will be sent by prebid to the orbidder /bid endpoint, i.e. the server.
*
* @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the orbidder /bid endpoint,
* i.e. the server.
* @return The requests for the orbidder /bid endpoint, i.e. the server.
*/
buildRequests(validBidRequests, bidderRequest) {
const hostname = this.getHostname();
return validBidRequests.map((bidRequest) => {
Expand All @@ -34,7 +86,7 @@ export const spec = {

bidRequest.params.bidfloor = getBidFloor(bidRequest);

const ret = {
let httpReq = {
url: `${hostname}/bid`,
method: 'POST',
options: { withCredentials: true },
Expand All @@ -46,40 +98,41 @@ export const spec = {
transactionId: bidRequest.transactionId,
adUnitCode: bidRequest.adUnitCode,
bidRequestCount: bidRequest.bidRequestCount,
params: bidRequest.params,
sizes: bidRequest.sizes,
params: bidRequest.params
mediaTypes: bidRequest.mediaTypes
}
};

if (bidderRequest && bidderRequest.gdprConsent) {
ret.data.gdprConsent = {
httpReq.data.gdprConsent = {
consentString: bidderRequest.gdprConsent.consentString,
consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') && bidderRequest.gdprConsent.gdprApplies
};
}
return ret;
return httpReq;
});
},

/**
* Unpack the response from the orbidder /bid endpoint into a list of bids.
*
* @param {*} serverResponse A successful response from the orbidder /bid endpoint, i.e. the server.
* @return {Bid[]} An array of bids from orbidder.
*/
interpretResponse(serverResponse) {
const bidResponses = [];
serverResponse = serverResponse.body;
if (serverResponse && (serverResponse.length > 0)) {
serverResponse.forEach((bid) => {
const bidResponse = {};
for (const requiredKey of ['requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', 'netRevenue', 'currency']) {
if (!bid.hasOwnProperty(requiredKey)) {
return [];
serverResponse.forEach((bidResponse) => {
if (isBidResponseValid(bidResponse)) {
if (Array.isArray(bidResponse.advertiserDomains)) {
bidResponse.meta = {
advertiserDomains: bidResponse.advertiserDomains
}
}
bidResponse[requiredKey] = bid[requiredKey];
bidResponses.push(bidResponse);
}

if (Array.isArray(bid.advertiserDomains)) {
bidResponse.meta = {
advertiserDomains: bid.advertiserDomains
}
}

bidResponses.push(bidResponse);
});
}
return bidResponses;
Expand Down
55 changes: 41 additions & 14 deletions modules/orbidderBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,46 @@ Module that connects to orbidder demand sources

# Test Parameters
```
var adUnits = [{
code: '/105091519/bidder_test',
mediaTypes: {
banner: {
sizes: [728, 90]
}
var adUnits = [
{
code: 'test_banner',
mediaTypes: {
banner: {
sizes: [728, 90]
}
},
bids: [{
bidder: 'orbidder',
params: {
accountId: "someAccount",
placementId: "somePlace"
}
}],
},
bids: [{
bidder: 'orbidder'
params: {
accountId: "someAccount",
placementId: "somePlace"
}
}]
}];
{
code: 'test_native',
mediaTypes: {
native: {
title: {
required: true,
len: 80
},
image: {
required: true,
sizes: [150, 50]
},
sponsoredBy: {
required: true
}
},
},
bids: [{
bidder: 'orbidder',
params: {
accountId: "someAccount",
placementId: "somePlace"
}
}],
}
];
```
Loading

0 comments on commit 089e43a

Please sign in to comment.