Skip to content

Commit d2a25fc

Browse files
onaydenovsa1omon
authored and
sa1omon
committed
Fidelity Media Bid Adapter. Prebid.js v3 support, CCPA support. (prebid#4630)
* Fidelity Media bid adapter update. Add Prebid.js v.3 support. Add CCPA support. * Fidelity Media bid adapter update. Add Prebid.js v.3 support. Add CCPA support. * PR Error fix * error fix * PR Error fix * PR Error fix * PR Error fix * pr error fix * Auction timeout removed * Fix. Timeout is back
1 parent acfec39 commit d2a25fc

File tree

3 files changed

+319
-7
lines changed

3 files changed

+319
-7
lines changed

modules/fidelityBidAdapter.js

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import * as utils from '../src/utils';
2+
import {registerBidder} from '../src/adapters/bidderFactory';
3+
4+
const BIDDER_CODE = 'fidelity';
5+
const BIDDER_SERVER = 'x.fidelity-media.com';
6+
const FIDELITY_VENDOR_ID = 408;
7+
export const spec = {
8+
code: BIDDER_CODE,
9+
isBidRequestValid: function isBidRequestValid(bid) {
10+
return !!(bid && bid.params && bid.params.zoneid);
11+
},
12+
buildRequests: function buildRequests(validBidRequests, bidderRequest) {
13+
return validBidRequests.map(bidRequest => {
14+
var server = bidRequest.params.server || BIDDER_SERVER;
15+
16+
const payload = {
17+
from: 'hb',
18+
v: '1.0',
19+
requestid: bidRequest.bidderRequestId,
20+
impid: bidRequest.bidId,
21+
zoneid: bidRequest.params.zoneid,
22+
floor: parseFloat(bidRequest.params.floor) > 0 ? bidRequest.params.floor : 0,
23+
charset: document.charSet || document.characterSet,
24+
subid: 'hb',
25+
flashver: getFlashVersion(),
26+
tmax: bidderRequest.timeout,
27+
defloc: bidderRequest.refererInfo.referer,
28+
referrer: getTopWindowReferrer(),
29+
};
30+
setConsentParams(bidderRequest.gdprConsent, bidderRequest.uspConsent, payload);
31+
32+
return {
33+
method: 'GET',
34+
url: 'https://' + server + '/delivery/hb.php',
35+
data: payload
36+
};
37+
});
38+
},
39+
interpretResponse: function interpretResponse(serverResponse) {
40+
serverResponse = serverResponse.body;
41+
const bidResponses = [];
42+
if (serverResponse && serverResponse.seatbid) {
43+
serverResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => {
44+
const bidResponse = {
45+
requestId: bid.impid,
46+
creativeId: bid.impid,
47+
cpm: bid.price,
48+
width: bid.width,
49+
height: bid.height,
50+
ad: bid.adm,
51+
netRevenue: bid.netRevenue,
52+
currency: bid.cur,
53+
ttl: bid.ttl,
54+
};
55+
56+
bidResponses.push(bidResponse);
57+
}));
58+
}
59+
return bidResponses;
60+
},
61+
getUserSyncs: function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
62+
if (syncOptions.iframeEnabled) {
63+
var url = 'https://' + BIDDER_SERVER + '/delivery/matches.php';
64+
var payload = {
65+
type: 'iframe'
66+
};
67+
setConsentParams(gdprConsent, uspConsent, payload);
68+
69+
return [{
70+
type: 'iframe',
71+
url: url + '?' + utils.parseQueryStringParameters(payload).replace(/\&$/, '')
72+
}];
73+
}
74+
}
75+
}
76+
77+
function getFlashVersion() {
78+
var plugins, plugin, result;
79+
80+
if (navigator.plugins && navigator.plugins.length > 0) {
81+
plugins = navigator.plugins;
82+
for (var i = 0; i < plugins.length && !result; i++) {
83+
plugin = plugins[i];
84+
if (plugin.name.indexOf('Shockwave Flash') > -1) {
85+
result = plugin.description.split('Shockwave Flash ')[1];
86+
}
87+
}
88+
}
89+
return result || '';
90+
}
91+
92+
function getTopWindowReferrer() {
93+
try {
94+
return window.top.document.referrer;
95+
} catch (e) {
96+
return '';
97+
}
98+
}
99+
100+
function setConsentParams(gdprConsent, uspConsent, payload) {
101+
if (gdprConsent) {
102+
payload.gdpr = 0;
103+
payload.consent_str = '';
104+
payload.consent_given = 0;
105+
if (typeof gdprConsent.gdprApplies !== 'undefined') {
106+
payload.gdpr = gdprConsent.gdprApplies ? 1 : 0;
107+
}
108+
if (typeof gdprConsent.consentString !== 'undefined') {
109+
payload.consent_str = gdprConsent.consentString;
110+
}
111+
if (gdprConsent.vendorData && gdprConsent.vendorData.vendorConsents && typeof gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] !== 'undefined') {
112+
payload.consent_given = gdprConsent.vendorData.vendorConsents[FIDELITY_VENDOR_ID.toString(10)] ? 1 : 0;
113+
}
114+
}
115+
if (typeof uspConsent !== 'undefined') {
116+
payload.us_privacy = uspConsent;
117+
}
118+
}
119+
120+
registerBidder(spec);

modules/fidelityBidAdapter.md

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
# Overview
2-
2+
33
**Module Name**: Fidelity Media fmxSSP Bidder Adapter
44
**Module Type**: Bidder Adapter
55
**Maintainer**: [email protected]
6-
6+
77
# Description
8-
8+
99
Connects to Fidelity Media fmxSSP demand source to fetch bids.
10-
10+
1111
# Test Parameters
12-
```
12+
```
1313
var adUnits = [{
1414
code: 'banner-ad-div',
15-
sizes: [[300, 250]],
15+
mediaTypes: {
16+
banner: {
17+
sizes: [[300, 250]],
18+
}
19+
},
1620
bids: [{
1721
bidder: 'fidelity',
1822
params: {
@@ -23,4 +27,4 @@ Connects to Fidelity Media fmxSSP demand source to fetch bids.
2327
}]
2428
}];
2529
26-
```
30+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
import { expect } from 'chai';
2+
import { spec } from 'modules/fidelityBidAdapter';
3+
import { newBidder } from 'src/adapters/bidderFactory';
4+
5+
describe('FidelityAdapter', function () {
6+
const adapter = newBidder(spec);
7+
8+
describe('inherited functions', function () {
9+
it('exists and is a function', function () {
10+
expect(adapter.callBids).to.exist.and.to.be.a('function');
11+
});
12+
});
13+
14+
describe('isBidRequestValid', function () {
15+
let bid = {
16+
'bidder': 'fidelity',
17+
'params': {
18+
'zoneid': '27248',
19+
'floor': '0.05',
20+
'server': 'x.fidelity-media.com',
21+
},
22+
'adUnitCode': 'adunit-code',
23+
'sizes': [[300, 250], [300, 600]],
24+
'bidId': '30b31c1838de1e',
25+
'bidderRequestId': '22edbae2733bf6',
26+
'auctionId': '1d1a030790a475',
27+
};
28+
29+
it('should return true when required params found', function () {
30+
expect(spec.isBidRequestValid(bid)).to.equal(true);
31+
});
32+
33+
it('should return true when required params found', function () {
34+
let bid = Object.assign({}, bid);
35+
delete bid.params;
36+
bid.params = {
37+
'zoneid': '27248',
38+
};
39+
expect(spec.isBidRequestValid(bid)).to.equal(true);
40+
});
41+
42+
it('should return false when required params are not passed', function () {
43+
let bid = Object.assign({}, bid);
44+
delete bid.params;
45+
bid.params = {
46+
'zoneid': 0,
47+
};
48+
expect(spec.isBidRequestValid(bid)).to.equal(false);
49+
});
50+
});
51+
52+
describe('buildRequests', function () {
53+
let bidderRequest = {
54+
bidderCode: 'fidelity',
55+
requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a',
56+
bidderRequestId: '178e34bad3658f',
57+
bids: [
58+
{
59+
bidder: 'fidelity',
60+
params: {
61+
zoneid: '27248',
62+
floor: '0.05',
63+
server: 'x.fidelity-media.com',
64+
},
65+
placementCode: '/19968336/header-bid-tag-0',
66+
sizes: [[300, 250], [320, 50]],
67+
bidId: '2ffb201a808da7',
68+
bidderRequestId: '178e34bad3658f',
69+
requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a',
70+
transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b'
71+
}
72+
],
73+
start: 1472239426002,
74+
auctionStart: 1472239426000,
75+
timeout: 5000,
76+
refererInfo: {
77+
referer: 'http://test.com/index.html'
78+
}
79+
};
80+
81+
it('should add source and verison to the tag', function () {
82+
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
83+
const payload = request.data;
84+
expect(payload.from).to.exist;
85+
expect(payload.v).to.exist;
86+
expect(payload.requestid).to.exist;
87+
expect(payload.impid).to.exist;
88+
expect(payload.zoneid).to.exist;
89+
expect(payload.floor).to.exist;
90+
expect(payload.charset).to.exist;
91+
expect(payload.subid).to.exist;
92+
expect(payload.flashver).to.exist;
93+
expect(payload.tmax).to.exist;
94+
expect(payload.defloc).to.exist;
95+
});
96+
97+
it('should add gdpr consent information to the request', function () {
98+
let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A==';
99+
let uspConsentString = '1YN-';
100+
bidderRequest.gdprConsent = {
101+
gdprApplies: true,
102+
allowAuctionWithoutConsent: true,
103+
consentString: consentString,
104+
vendorData: {
105+
vendorConsents: {
106+
'408': 1
107+
},
108+
},
109+
};
110+
bidderRequest.uspConsent = uspConsentString;
111+
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
112+
const payload = request.data;
113+
expect(payload.gdpr).to.exist.and.to.be.a('number');
114+
expect(payload.gdpr).to.equal(1);
115+
expect(payload.consent_str).to.exist.and.to.be.a('string');
116+
expect(payload.consent_str).to.equal(consentString);
117+
expect(payload.consent_given).to.exist.and.to.be.a('number');
118+
expect(payload.consent_given).to.equal(1);
119+
expect(payload.us_privacy).to.exist.and.to.be.a('string');
120+
expect(payload.us_privacy).to.equal(uspConsentString);
121+
});
122+
123+
it('sends bid request to ENDPOINT via GET', function () {
124+
const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest);
125+
expect(request.url).to.equal('https://x.fidelity-media.com/delivery/hb.php');
126+
expect(request.method).to.equal('GET');
127+
});
128+
})
129+
130+
describe('interpretResponse', function () {
131+
let response = {
132+
'id': '543210',
133+
'seatbid': [ {
134+
'bid': [ {
135+
'id': '1111111',
136+
'impid': 'bidId-123456-1',
137+
'price': 0.09,
138+
'adm': '<!-- Creative -->',
139+
'width': 728,
140+
'height': 90,
141+
} ]
142+
} ]
143+
};
144+
145+
it('should get correct bid response', function () {
146+
let expectedResponse = [
147+
{
148+
requestId: 'bidId-123456-1',
149+
creativeId: 'bidId-123456-1',
150+
cpm: 0.09,
151+
width: 728,
152+
height: 90,
153+
ad: '<!-- Creative -->',
154+
netRevenue: true,
155+
currency: 'USD',
156+
ttl: 360,
157+
}
158+
];
159+
160+
let result = spec.interpretResponse({ body: response });
161+
expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0]));
162+
});
163+
164+
it('handles nobid responses', function () {
165+
let response = {
166+
'id': '543210',
167+
'seatbid': [ ]
168+
};
169+
170+
let result = spec.interpretResponse({ body: response });
171+
expect(result.length).to.equal(0);
172+
});
173+
});
174+
175+
describe('user sync', function () {
176+
const syncUrl = 'https://x.fidelity-media.com/delivery/matches.php?type=iframe';
177+
178+
it('should register the sync iframe', function () {
179+
expect(spec.getUserSyncs({})).to.be.undefined;
180+
expect(spec.getUserSyncs({iframeEnabled: false})).to.be.undefined;
181+
const options = spec.getUserSyncs({iframeEnabled: true});
182+
expect(options).to.not.be.undefined;
183+
expect(options).to.have.lengthOf(1);
184+
expect(options[0].type).to.equal('iframe');
185+
expect(options[0].url).to.equal(syncUrl);
186+
});
187+
});
188+
});

0 commit comments

Comments
 (0)