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

Fidelity Media Bid Adapter. Prebid.js v3 support, CCPA support. #4630

Merged
merged 10 commits into from
Dec 18, 2019
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
120 changes: 120 additions & 0 deletions modules/fidelityBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import * as utils from '../src/utils';
import {registerBidder} from '../src/adapters/bidderFactory';

const BIDDER_CODE = 'fidelity';
const BIDDER_SERVER = 'x.fidelity-media.com';
const FIDELITY_VENDOR_ID = 408;
export const spec = {
code: BIDDER_CODE,
isBidRequestValid: function isBidRequestValid(bid) {
return !!(bid && bid.params && bid.params.zoneid);
},
buildRequests: function buildRequests(validBidRequests, bidderRequest) {
return validBidRequests.map(bidRequest => {
var server = bidRequest.params.server || BIDDER_SERVER;

const payload = {
from: 'hb',
v: '1.0',
requestid: bidRequest.bidderRequestId,
impid: bidRequest.bidId,
zoneid: bidRequest.params.zoneid,
floor: parseFloat(bidRequest.params.floor) > 0 ? bidRequest.params.floor : 0,
charset: document.charSet || document.characterSet,
subid: 'hb',
flashver: getFlashVersion(),
tmax: bidderRequest.timeout,
defloc: bidderRequest.refererInfo.referer,
referrer: getTopWindowReferrer(),
};
setConsentParams(bidderRequest.gdprConsent, bidderRequest.uspConsent, payload);

return {
method: 'GET',
url: 'https://' + server + '/delivery/hb.php',
data: payload
};
});
},
interpretResponse: function interpretResponse(serverResponse) {
serverResponse = serverResponse.body;
const bidResponses = [];
if (serverResponse && serverResponse.seatbid) {
serverResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => {
const bidResponse = {
requestId: bid.impid,
creativeId: bid.impid,
cpm: bid.price,
width: bid.width,
height: bid.height,
ad: bid.adm,
netRevenue: bid.netRevenue,
currency: bid.cur,
ttl: bid.ttl,
};

bidResponses.push(bidResponse);
}));
}
return bidResponses;
},
getUserSyncs: function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
if (syncOptions.iframeEnabled) {
var url = 'https://' + BIDDER_SERVER + '/delivery/matches.php';
var payload = {
type: 'iframe'
};
setConsentParams(gdprConsent, uspConsent, payload);

return [{
type: 'iframe',
url: url + '?' + utils.parseQueryStringParameters(payload).replace(/\&$/, '')
}];
}
}
}

function getFlashVersion() {
var plugins, plugin, result;

if (navigator.plugins && navigator.plugins.length > 0) {
plugins = navigator.plugins;
for (var i = 0; i < plugins.length && !result; i++) {
plugin = plugins[i];
if (plugin.name.indexOf('Shockwave Flash') > -1) {
result = plugin.description.split('Shockwave Flash ')[1];
}
}
}
return result || '';
}

function getTopWindowReferrer() {
try {
return window.top.document.referrer;
} catch (e) {
return '';
}
}

function setConsentParams(gdprConsent, uspConsent, payload) {
if (gdprConsent) {
payload.gdpr = 0;
payload.consent_str = '';
payload.consent_given = 0;
if (typeof gdprConsent.gdprApplies !== 'undefined') {
payload.gdpr = gdprConsent.gdprApplies ? 1 : 0;
}
if (typeof gdprConsent.consentString !== 'undefined') {
payload.consent_str = gdprConsent.consentString;
}
if (gdprConsent.vendorData && gdprConsent.vendorData.vendorConsents && typeof gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] !== 'undefined') {
payload.consent_given = gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] ? 1 : 0;
}
}
if (typeof uspConsent !== 'undefined') {
payload.us_privacy = uspConsent;
}
}

registerBidder(spec);
18 changes: 11 additions & 7 deletions modules/fidelityBidAdapter.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
# Overview

**Module Name**: Fidelity Media fmxSSP Bidder Adapter
**Module Type**: Bidder Adapter
**Maintainer**: [email protected]

# Description

Connects to Fidelity Media fmxSSP demand source to fetch bids.

# Test Parameters
```
```
var adUnits = [{
code: 'banner-ad-div',
sizes: [[300, 250]],
mediaTypes: {
banner: {
sizes: [[300, 250]],
}
},
bids: [{
bidder: 'fidelity',
params: {
Expand All @@ -23,4 +27,4 @@ Connects to Fidelity Media fmxSSP demand source to fetch bids.
}]
}];

```
```
188 changes: 188 additions & 0 deletions test/spec/modules/fidelityBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import { expect } from 'chai';
import { spec } from 'modules/fidelityBidAdapter';
import { newBidder } from 'src/adapters/bidderFactory';

describe('FidelityAdapter', function () {
const adapter = newBidder(spec);

describe('inherited functions', function () {
it('exists and is a function', function () {
expect(adapter.callBids).to.exist.and.to.be.a('function');
});
});

describe('isBidRequestValid', function () {
let bid = {
'bidder': 'fidelity',
'params': {
'zoneid': '27248',
'floor': '0.05',
'server': 'x.fidelity-media.com',
},
'adUnitCode': 'adunit-code',
'sizes': [[300, 250], [300, 600]],
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
};

it('should return true when required params found', function () {
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

it('should return true when required params found', function () {
let bid = Object.assign({}, bid);
delete bid.params;
bid.params = {
'zoneid': '27248',
};
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

it('should return false when required params are not passed', function () {
let bid = Object.assign({}, bid);
delete bid.params;
bid.params = {
'zoneid': 0,
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
});

describe('buildRequests', function () {
let bidderRequest = {
bidderCode: 'fidelity',
requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a',
bidderRequestId: '178e34bad3658f',
bids: [
{
bidder: 'fidelity',
params: {
zoneid: '27248',
floor: '0.05',
server: 'x.fidelity-media.com',
},
placementCode: '/19968336/header-bid-tag-0',
sizes: [[300, 250], [320, 50]],
bidId: '2ffb201a808da7',
bidderRequestId: '178e34bad3658f',
requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a',
transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b'
}
],
start: 1472239426002,
auctionStart: 1472239426000,
timeout: 5000,
refererInfo: {
referer: 'http://test.com/index.html'
}
};

it('should add source and verison to the tag', function () {
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
const payload = request.data;
expect(payload.from).to.exist;
expect(payload.v).to.exist;
expect(payload.requestid).to.exist;
expect(payload.impid).to.exist;
expect(payload.zoneid).to.exist;
expect(payload.floor).to.exist;
expect(payload.charset).to.exist;
expect(payload.subid).to.exist;
expect(payload.flashver).to.exist;
expect(payload.tmax).to.exist;
expect(payload.defloc).to.exist;
});

it('should add gdpr consent information to the request', function () {
let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==';
let uspConsentString = '1YN-';
bidderRequest.gdprConsent = {
gdprApplies: true,
allowAuctionWithoutConsent: true,
consentString: consentString,
vendorData: {
vendorConsents: {
'408': 1
},
},
};
bidderRequest.uspConsent = uspConsentString;
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
const payload = request.data;
expect(payload.gdpr).to.exist.and.to.be.a('number');
expect(payload.gdpr).to.equal(1);
expect(payload.consent_str).to.exist.and.to.be.a('string');
expect(payload.consent_str).to.equal(consentString);
expect(payload.consent_given).to.exist.and.to.be.a('number');
expect(payload.consent_given).to.equal(1);
expect(payload.us_privacy).to.exist.and.to.be.a('string');
expect(payload.us_privacy).to.equal(uspConsentString);
});

it('sends bid request to ENDPOINT via GET', function () {
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
expect(request.url).to.equal('https://x.fidelity-media.com/delivery/hb.php');
expect(request.method).to.equal('GET');
});
})

describe('interpretResponse', function () {
let response = {
'id': '543210',
'seatbid': [ {
'bid': [ {
'id': '1111111',
'impid': 'bidId-123456-1',
'price': 0.09,
'adm': '<!-- Creative -->',
'width': 728,
'height': 90,
} ]
} ]
};

it('should get correct bid response', function () {
let expectedResponse = [
{
requestId: 'bidId-123456-1',
creativeId: 'bidId-123456-1',
cpm: 0.09,
width: 728,
height: 90,
ad: '<!-- Creative -->',
netRevenue: true,
currency: 'USD',
ttl: 360,
}
];

let result = spec.interpretResponse({ body: response });
expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0]));
});

it('handles nobid responses', function () {
let response = {
'id': '543210',
'seatbid': [ ]
};

let result = spec.interpretResponse({ body: response });
expect(result.length).to.equal(0);
});
});

describe('user sync', function () {
const syncUrl = 'https://x.fidelity-media.com/delivery/matches.php?type=iframe';

it('should register the sync iframe', function () {
expect(spec.getUserSyncs({})).to.be.undefined;
expect(spec.getUserSyncs({iframeEnabled: false})).to.be.undefined;
const options = spec.getUserSyncs({iframeEnabled: true});
expect(options).to.not.be.undefined;
expect(options).to.have.lengthOf(1);
expect(options[0].type).to.equal('iframe');
expect(options[0].url).to.equal(syncUrl);
});
});
});