Skip to content

Commit

Permalink
Codefuel Bid Adapter: add new bid adapter (#7489)
Browse files Browse the repository at this point in the history
* * Update undertone adapter - change parameters - placementId parameter is now optional and not mandatory - undertoneBidAdapter.js

* Updated undertone bid adapter tests accordingly - undertoneBidAdapter_spec.js

* * Update undertone adapter - change parameters - placementId parameter is now optional and not mandatory - undertoneBidAdapter.js

 * Updated undertone bid adapter tests accordingly - undertoneBidAdapter_spec.js

* fix lint issue in undertone adapter spec

* added user sync function to undertone adapter

* * Update undertone adapter - change parameters - placementId parameter is now optional and not mandatory - undertoneBidAdapter.js

* Updated undertone bid adapter tests accordingly - undertoneBidAdapter_spec.js

* added user sync function to undertone adapter

* added user sync function to undertone adapter

* revert package-lock.json

* added user sync function to undertone adapter

* Update undertoneBidAdapter.js

* Update browsers.json

* sanity

* indentation

* cf adapter, md and spec

* spec.js fix

* spec.js fix (2)

* final fixes:
- browsers.json -> remove newline
- adapter -> import only used functions

* adomain -> meta.advertiserDomains

* re-check

* re-check-2

Co-authored-by: omerko <omer.koren@perion.com>
Co-authored-by: Omer Koren <omerko@users.noreply.github.com>
Co-authored-by: AnnaPerion <annat@perion.com>
Co-authored-by: Oran Hollaender <oran@perion.com>
  • Loading branch information
5 people authored Oct 14, 2021
1 parent 0bbea5e commit ff18876
Show file tree
Hide file tree
Showing 3 changed files with 610 additions and 0 deletions.
183 changes: 183 additions & 0 deletions modules/codefuelBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { deepAccess, isArray } from '../src/utils.js';
import { config } from '../src/config.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import { BANNER } from '../src/mediaTypes.js';
const BIDDER_CODE = 'codefuel';
const CURRENCY = 'USD';

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [ BANNER ],
aliases: ['ex'], // short code
/**
* Determines whether or not the given bid request is valid.
*
* @param {BidRequest} bid The bid params to validate.
* @return boolean True if this is a valid bid, and false otherwise.
*/
isBidRequestValid: function(bid) {
if (bid.nativeParams) {
return false;
}
return !!(bid.params.placementId || (bid.params.member && bid.params.invCode));
},
/**
* Make a server request from the list of BidRequests.
*
* @param {validBidRequests[]} - an array of bids
* @return ServerRequest Info describing the request to the server.
*/
buildRequests: function(validBidRequests, bidderRequest) {
const page = bidderRequest.refererInfo.referer;
const domain = getDomainFromURL(page)
const ua = navigator.userAgent;
const devicetype = getDeviceType()
const publisher = setOnAny(validBidRequests, 'params.publisher');
const cur = CURRENCY;
// const endpointUrl = 'http://localhost:5000/prebid'
const endpointUrl = config.getConfig('codefuel.bidderUrl');
const timeout = bidderRequest.timeout;

validBidRequests.forEach(bid => bid.netRevenue = 'net');

const imps = validBidRequests.map((bid, idx) => {
const imp = {
id: idx + 1 + ''
}

if (bid.params.tagid) {
imp.tagid = bid.params.tagid
}

if (bid.sizes) {
imp.banner = {
format: transformSizes(bid.sizes)
}
}

return imp;
});

const request = {
id: bidderRequest.auctionId,
site: { page, domain, publisher },
device: { ua, devicetype },
source: { fd: 1 },
cur: [cur],
tmax: timeout,
imp: imps,
};

return {
method: 'POST',
url: endpointUrl,
data: request,
bids: validBidRequests,
options: {
withCredentials: false
}
};
},
/**
* Unpack the response from the server into a list of bids.
*
* @param {ServerResponse} serverResponse A successful response from the server.
* @return {Bid[]} An array of bids which were nested inside the server.
*/
interpretResponse: (serverResponse, { bids }) => {
if (!serverResponse.body) {
return [];
}
const { seatbid, cur } = serverResponse.body;

const bidResponses = flatten(seatbid.map(seat => seat.bid)).reduce((result, bid) => {
result[bid.impid - 1] = bid;
return result;
}, []);

return bids.map((bid, id) => {
const bidResponse = bidResponses[id];
if (bidResponse) {
const bidObject = {
requestId: bid.bidId,
cpm: bidResponse.price,
creativeId: bidResponse.crid,
ttl: 360,
netRevenue: true,
currency: cur,
mediaType: BANNER,
ad: bidResponse.adm,
width: bidResponse.w,
height: bidResponse.h,
meta: { advertiserDomains: bid.adomain ? bid.adomain : [] }
};
return bidObject;
}
}).filter(Boolean);
},

/**
* Register the user sync pixels which should be dropped after the auction.
*
* @param {SyncOptions} syncOptions Which user syncs are allowed?
* @param {ServerResponse[]} serverResponses List of server's responses.
* @return {UserSync[]} The user syncs which should be dropped.
*/
getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) {
return [];
}

}
registerBidder(spec);

function getDomainFromURL(url) {
let anchor = document.createElement('a');
anchor.href = url;
return anchor.hostname;
}

function getDeviceType() {
if ((/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(navigator.userAgent.toLowerCase()))) {
return 5; // 'tablet'
}
if ((/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(navigator.userAgent.toLowerCase()))) {
return 4; // 'mobile'
}
return 2; // 'desktop'
}

function setOnAny(collection, key) {
for (let i = 0, result; i < collection.length; i++) {
result = deepAccess(collection[i], key);
if (result) {
return result;
}
}
}

function flatten(arr) {
return [].concat(...arr);
}

/* Turn bid request sizes into ut-compatible format */
function transformSizes(requestSizes) {
if (!isArray(requestSizes)) {
return [];
}

if (requestSizes.length === 2 && !isArray(requestSizes[0])) {
return [{
w: parseInt(requestSizes[0], 10),
h: parseInt(requestSizes[1], 10)
}];
} else if (isArray(requestSizes[0])) {
return requestSizes.map(item =>
({
w: parseInt(item[0], 10),
h: parseInt(item[1], 10)
})
);
}

return [];
}
111 changes: 111 additions & 0 deletions modules/codefuelBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Overview

```
Module Name: Codefuel Adapter
Module Type: Bidder Adapter
Maintainer: hayimm@codefuel.com
```

# Description

Module that connects to Codefuel bidder to fetch bids.
Display format is supported but not native format. Using OpenRTB standard.

# Configuration

## Bidder and usersync URLs

The Codefuel adapter does not work without setting the correct bidder.
You will receive the URLs when contacting us.

```
pbjs.setConfig({
codefuel: {
bidderUrl: 'https://ai-i-codefuel-ds-rtb-us-east-1-k8s-internal.seccint.com/prebid',
usersyncUrl: 'https://usersync-url.com'
}
});
```


# Test Native Parameters
```
var adUnits = [
code: '/19968336/prebid_native_example_1',
mediaTypes: {
native: {
image: {
required: false,
sizes: [100, 50]
},
title: {
required: false,
len: 140
},
sponsoredBy: {
required: false
},
clickUrl: {
required: false
},
body: {
required: false
},
icon: {
required: false,
sizes: [50, 50]
}
}
},
bids: [{
bidder: 'codefuel',
params: {
publisher: {
id: '2706', // required
name: 'Publishers Name',
domain: 'publisher.com'
},
tagid: 'tag-id',
bcat: ['IAB1-1'],
badv: ['example.com']
}
}]
];
pbjs.setConfig({
codefuel: {
bidderUrl: 'https://prebidtest.zemanta.com/api/bidder/prebidtest/bid/'
}
});
```

# Test Display Parameters
```
var adUnits = [
code: '/19968336/prebid_display_example_1',
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
},
bids: [{
bidder: 'codefuel',
params: {
publisher: {
id: '2706', // required
name: 'Publishers Name',
domain: 'publisher.com'
},
tagid: 'tag-id',
bcat: ['IAB1-1'],
badv: ['example.com']
},
}]
];
pbjs.setConfig({
codefuel: {
bidderUrl: 'https://prebidtest.zemanta.com/api/bidder/prebidtest/bid/'
}
});
```
Loading

0 comments on commit ff18876

Please sign in to comment.