Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Freedom Ad Network Bid Adapter: initial release #12153

Merged
merged 15 commits into from
Aug 21, 2024
Merged
176 changes: 176 additions & 0 deletions modules/fanAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import * as utils from '../src/utils.js';
import { ajax } from '../src/ajax.js';
import { BANNER, NATIVE } from '../src/mediaTypes.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';

/**
* @typedef {import('../src/adapters/bidderFactory.js').BidderRequest} BidderRequest
* @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest
* @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid
* @typedef {import('../src/adapters/bidderFactory.js').ServerResponse} ServerResponse
*/

const BIDDER_CODE = 'freedomadnetwork';
const BASE_URL = 'https://srv.freedomadnetwork.com';

/**
* Build OpenRTB request from bidRequest and bidderRequest
*
* @param {BidRequest} bid
* @param {BidderRequest} bidderRequest
* @returns {Request}
*/
function buildBidRequest(bid, bidderRequest) {
const payload = {
id: bid.bidId,
tmax: bidderRequest.timeout,
placements: [bid.params.placementId],
at: 1,
user: {}
}

const gdprConsent = utils.deepAccess(bidderRequest, 'gdprConsent');
if (!!gdprConsent && gdprConsent.gdprApplies) {
payload.user.gdpr = 1;
payload.user.consent = gdprConsent.consentString;
}

const uspConsent = utils.deepAccess(bidderRequest, 'uspConsent');
if (uspConsent) {
payload.user.usp = uspConsent;
}

return {
method: 'POST',
url: BASE_URL + '/pb/req',
data: JSON.stringify(payload),
options: {
contentType: 'application/json',
withCredentials: false,
customHeaders: {
'Accept-Language': 'en;q=10',
},
},
originalBidRequest: bid
}
}

export const spec = {
code: BIDDER_CODE,
isBidRequestValid: function(bid) {
if (!bid) {
utils.logWarn(BIDDER_CODE, 'Invalid bid', bid);

return false;
}

if (!bid.params) {
utils.logWarn(BIDDER_CODE, 'bid.params is required');

return false;
}

if (!bid.params.placementId) {
utils.logWarn(BIDDER_CODE, 'bid.params.placementId is required');

return false;
}

var banner = utils.deepAccess(bid, 'mediaTypes.banner');
if (banner === undefined) {
return false;
}

return true;
},

buildRequests: function(validBidRequests, bidderRequest) {
return validBidRequests.map(bid => buildBidRequest(bid, bidderRequest));
},

/**
* 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: function (serverResponse, bidRequest) {
const serverBody = serverResponse.body;
let bidResponses = [];

if (!serverBody) {
return bidResponses;
}

serverBody.forEach((response) => {
const bidResponse = {
requestId: response.id,
bidid: response.bidid,
impid: response.impid,
userId: response.userId,
cpm: response.cpm,
currency: response.currency,
width: response.width,
height: response.height,
ad: response.payload,
ttl: response.ttl,
creativeId: response.crid,
netRevenue: response.netRevenue,
trackers: response.trackers,
meta: {
mediaType: response.mediaType,
advertiserDomains: response.domains,
}
};

bidResponses.push(bidResponse);
});

return bidResponses;
},

/**
* Register bidder specific code, which will execute if a bid from this bidder won the auction
*
* @param {Bid} bid The bid that won the auction
*/
onBidWon: function (bid) {
if (!bid) {
return;
}

const payload = {
id: bid.bidid,
impid: bid.impid,
t: bid.cpm,
u: bid.userId,
}

ajax(BASE_URL + '/pb/imp', null, JSON.stringify(payload), {
method: 'POST',
customHeaders: {
'Accept-Language': 'en;q=10',
},
});

if (bid.trackers && bid.trackers.length > 0) {
for (var i = 0; i < bid.trackers.length; i++) {
if (bid.trackers[i].type == 0) {
utils.triggerPixel(bid.trackers[i].url);
}
}
}
},
onSetTargeting: function(bid) {},
onBidderError: function(error) {
utils.logError(`${BIDDER_CODE} bidder error`, error);
},
getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) {
const syncs = [];
return syncs;
},
onTimeout: function(timeoutData) {},
supportedMediaTypes: [BANNER, NATIVE]
}

registerBidder(spec);
40 changes: 40 additions & 0 deletions modules/fanAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Freedom Ad Network Bidder Adapter

# Overview

```
Module Name: Freedom Ad Network Bidder Adapter
Module Type: Bidder Adapter
Maintainer: info@freedomadnetwork.com
```

## Description

Module that connects to FAN's demand sources.

## Bid Parameters

| Name | Scope | Type | Description | Example |
|---------------|----------|--------------------|-----------------------------------------|-------------------------------------------------|
| `placementId` | required | String | The Placement Id provided by FAN. | `e6203f1e-bd6d-4f42-9895-d1a19cdb83c8` |

## Example

### Banner Ads

```javascript
var adUnits = [{
code: 'banner-ad-div',
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
},
bids: [{
bidder: 'freedomadnetwork',
params: {
placementId: 'e6203f1e-bd6d-4f42-9895-d1a19cdb83c8'
}
}]
}];
```
Loading
Loading