Skip to content

Commit 67a1cb1

Browse files
authored
Add new bid adapter for ConnectAd (#4806)
* Add new bid adapter for ConnectAd * Add new bid adapter for ConnectAd * Conditional fix * js.fix * js-fix * EOF-fix * EOF-Fix
1 parent 8f8f6f8 commit 67a1cb1

File tree

3 files changed

+798
-0
lines changed

3 files changed

+798
-0
lines changed

modules/connectadBidAdapter.js

+299
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
import * as utils from '../src/utils.js';
2+
import { registerBidder } from '../src/adapters/bidderFactory.js';
3+
import { BANNER } from '../src/mediaTypes.js'
4+
import {config} from '../src/config.js';
5+
6+
const BIDDER_CODE = 'connectad';
7+
const BIDDER_CODE_ALIAS = 'connectadrealtime';
8+
const ENDPOINT_URL = 'https://i.connectad.io/api/v2';
9+
const SUPPORTED_MEDIA_TYPES = [BANNER];
10+
11+
export const spec = {
12+
code: BIDDER_CODE,
13+
aliases: [ BIDDER_CODE_ALIAS ],
14+
supportedMediaTypes: SUPPORTED_MEDIA_TYPES,
15+
16+
isBidRequestValid: function(bid) {
17+
return !!(bid.params.networkId && bid.params.siteId);
18+
},
19+
20+
buildRequests: function(validBidRequests, bidderRequest) {
21+
let digitrust;
22+
23+
let ret = {
24+
method: 'POST',
25+
url: '',
26+
data: '',
27+
bidRequest: []
28+
};
29+
30+
if (validBidRequests.length < 1) {
31+
return ret;
32+
}
33+
34+
const data = Object.assign({
35+
placements: [],
36+
time: Date.now(),
37+
user: {},
38+
url: (bidderRequest.refererInfo && bidderRequest.refererInfo.referer) ? bidderRequest.refererInfo.referer : window.location.href,
39+
referrer: window.document.referrer,
40+
referrer_info: bidderRequest.refererInfo,
41+
screensize: getScreenSize(),
42+
dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0,
43+
language: navigator.language,
44+
ua: navigator.userAgent
45+
});
46+
47+
// coppa compliance
48+
if (config.getConfig('coppa') === true) {
49+
utils.deepSetValue(data, 'user.coppa', 1);
50+
}
51+
52+
// adding schain object
53+
if (validBidRequests[0].schain) {
54+
utils.deepSetValue(data, 'source.ext.schain', validBidRequests[0].schain);
55+
}
56+
57+
// Attaching GDPR Consent Params
58+
if (bidderRequest.gdprConsent) {
59+
let gdprApplies;
60+
if (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') {
61+
gdprApplies = bidderRequest.gdprConsent.gdprApplies ? 1 : 0;
62+
}
63+
utils.deepSetValue(data, 'user.ext.gdpr', gdprApplies);
64+
utils.deepSetValue(data, 'user.ext.consent', bidderRequest.gdprConsent.consentString);
65+
}
66+
67+
// CCPA
68+
if (bidderRequest.uspConsent) {
69+
utils.deepSetValue(data, 'user.ext.us_privacy', bidderRequest.uspConsent);
70+
}
71+
72+
// Digitrust Support
73+
const bidRequestDigitrust = utils.deepAccess(validBidRequests[0], 'userId.digitrustid.data');
74+
if (bidRequestDigitrust && (!bidRequestDigitrust.privacy || !bidRequestDigitrust.privacy.optout)) {
75+
digitrust = {
76+
id: bidRequestDigitrust.id,
77+
keyv: bidRequestDigitrust.keyv
78+
}
79+
}
80+
81+
if (digitrust) {
82+
utils.deepSetValue(data, 'user.ext.digitrust', {
83+
id: digitrust.id,
84+
keyv: digitrust.keyv
85+
})
86+
}
87+
88+
if (validBidRequests[0].userId && typeof validBidRequests[0].userId === 'object' && (validBidRequests[0].userId.tdid || validBidRequests[0].userId.pubcid || validBidRequests[0].userId.lipb || validBidRequests[0].userId.id5id || validBidRequests[0].userId.parrableid)) {
89+
utils.deepSetValue(data, 'user.ext.eids', []);
90+
91+
if (validBidRequests[0].userId.tdid) {
92+
data.user.ext.eids.push({
93+
source: 'adserver.org',
94+
uids: [{
95+
id: validBidRequests[0].userId.tdid,
96+
ext: {
97+
rtiPartner: 'TDID'
98+
}
99+
}]
100+
});
101+
}
102+
103+
if (validBidRequests[0].userId.pubcid) {
104+
data.user.ext.eids.push({
105+
source: 'pubcommon',
106+
uids: [{
107+
id: validBidRequests[0].userId.pubcid,
108+
}]
109+
});
110+
}
111+
112+
if (validBidRequests[0].userId.id5id) {
113+
data.user.ext.eids.push({
114+
source: 'id5-sync.com',
115+
uids: [{
116+
id: validBidRequests[0].userId.id5id,
117+
}]
118+
});
119+
}
120+
121+
if (validBidRequests[0].userId.parrableid) {
122+
data.user.ext.eids.push({
123+
source: 'parrable.com',
124+
uids: [{
125+
id: validBidRequests[0].userId.parrableid,
126+
}]
127+
});
128+
}
129+
130+
if (validBidRequests[0].userId.lipb && validBidRequests[0].userId.lipb.lipbid) {
131+
data.user.ext.eids.push({
132+
source: 'liveintent.com',
133+
uids: [{
134+
id: validBidRequests[0].userId.lipb.lipbid
135+
}]
136+
});
137+
}
138+
}
139+
140+
validBidRequests.map(bid => {
141+
const placement = Object.assign({
142+
id: bid.transactionId,
143+
divName: bid.bidId,
144+
sizes: bid.mediaTypes.banner.sizes,
145+
adTypes: getSize(bid.mediaTypes.banner.sizes || bid.sizes)
146+
}, bid.params);
147+
148+
if (placement.networkId && placement.siteId) {
149+
data.placements.push(placement);
150+
}
151+
});
152+
153+
ret.data = JSON.stringify(data);
154+
ret.bidRequest = validBidRequests;
155+
ret.url = ENDPOINT_URL;
156+
157+
return ret;
158+
},
159+
160+
interpretResponse: function(serverResponse, bidRequest, bidderRequest) {
161+
let bid;
162+
let bids;
163+
let bidId;
164+
let bidObj;
165+
let bidResponses = [];
166+
167+
bids = bidRequest.bidRequest;
168+
169+
serverResponse = (serverResponse || {}).body;
170+
for (let i = 0; i < bids.length; i++) {
171+
bid = {};
172+
bidObj = bids[i];
173+
bidId = bidObj.bidId;
174+
175+
if (serverResponse) {
176+
const decision = serverResponse.decisions && serverResponse.decisions[bidId];
177+
const price = decision && decision.pricing && decision.pricing.clearPrice;
178+
179+
if (decision && price) {
180+
bid.requestId = bidId;
181+
bid.cpm = price;
182+
bid.width = decision.width;
183+
bid.height = decision.height;
184+
bid.dealid = decision.dealid || null;
185+
bid.ad = retrieveAd(decision);
186+
bid.currency = 'USD';
187+
bid.creativeId = decision.adId;
188+
bid.ttl = 360;
189+
bid.netRevenue = true;
190+
bidResponses.push(bid);
191+
}
192+
}
193+
}
194+
195+
return bidResponses;
196+
},
197+
198+
getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) {
199+
let syncEndpoint = 'https://cdn.connectad.io/connectmyusers.php?';
200+
201+
if (gdprConsent) {
202+
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'gdpr', (gdprConsent.gdprApplies ? 1 : 0));
203+
}
204+
205+
if (gdprConsent && typeof gdprConsent.consentString === 'string') {
206+
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'gdpr_consent', gdprConsent.consentString);
207+
}
208+
209+
if (uspConsent) {
210+
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'us_privacy', uspConsent);
211+
}
212+
213+
if (config.getConfig('coppa') === true) {
214+
syncEndpoint = utils.tryAppendQueryString(syncEndpoint, 'coppa', 1);
215+
}
216+
217+
if (syncOptions.iframeEnabled) {
218+
return [{
219+
type: 'iframe',
220+
url: syncEndpoint
221+
}];
222+
} else {
223+
utils.logWarn('Bidder ConnectAd: Please activate iFrame Sync');
224+
}
225+
}
226+
};
227+
228+
const sizeMap = [
229+
null,
230+
'120x90',
231+
'200x200',
232+
'468x60',
233+
'728x90',
234+
'300x250',
235+
'160x600',
236+
'120x600',
237+
'300x100',
238+
'180x150',
239+
'336x280',
240+
'240x400',
241+
'234x60',
242+
'88x31',
243+
'120x60',
244+
'120x240',
245+
'125x125',
246+
'220x250',
247+
'250x250',
248+
'250x90',
249+
'0x0',
250+
'200x90',
251+
'300x50',
252+
'320x50',
253+
'320x480',
254+
'185x185',
255+
'620x45',
256+
'300x125',
257+
'800x250',
258+
'980x120',
259+
'980x150',
260+
'320x150',
261+
'300x300',
262+
'200x600',
263+
'320x500',
264+
'320x320'
265+
];
266+
267+
sizeMap[77] = '970x90';
268+
sizeMap[123] = '970x250';
269+
sizeMap[43] = '300x600';
270+
sizeMap[286] = '970x66';
271+
sizeMap[3230] = '970x280';
272+
sizeMap[429] = '486x60';
273+
sizeMap[374] = '700x500';
274+
sizeMap[934] = '300x1050';
275+
sizeMap[1578] = '320x100';
276+
sizeMap[331] = '320x250';
277+
sizeMap[3301] = '320x267';
278+
sizeMap[2730] = '728x250';
279+
280+
function getSize(sizes) {
281+
const result = [];
282+
sizes.forEach(function(size) {
283+
const index = sizeMap.indexOf(size[0] + 'x' + size[1]);
284+
if (index >= 0) {
285+
result.push(index);
286+
}
287+
});
288+
return result;
289+
}
290+
291+
function retrieveAd(decision) {
292+
return decision.contents && decision.contents[0] && decision.contents[0].body;
293+
}
294+
295+
function getScreenSize() {
296+
return [window.screen.width, window.screen.height].join('x');
297+
}
298+
299+
registerBidder(spec);

modules/connectadBidAdapter.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Overview
2+
3+
```
4+
Module Name: ConnectAd PreBid Adapter
5+
Module Type: Bidder Adapter
6+
Maintainer: [email protected]
7+
```
8+
9+
# Description
10+
11+
ConnectAd bid adapter supports only Banner at present. Video and Mobile will follow Q2/2020
12+
13+
# Sample Ad Unit: For Publishers
14+
```
15+
var adUnits = [
16+
{
17+
code: 'test-div',
18+
mediaTypes: {
19+
banner: {
20+
sizes: [[300, 250], [300,600]]
21+
}
22+
},
23+
bids: [{
24+
bidder: 'connectad',
25+
params: {
26+
siteId: 123456,
27+
networkId: 123456,
28+
bidfloor: 0.20 // Optional: Requested Bidfloor
29+
}
30+
}]
31+
}
32+
33+
# ## Configuration
34+
ConnectAd recommends the UserSync configuration below otherwise we will not be able to performe user syncs.
35+
36+
```javascript
37+
pbjs.setConfig({
38+
userSync: {
39+
filterSettings: {
40+
iframe: {
41+
bidders: ['connectad'],
42+
filter: 'include'
43+
}
44+
}
45+
}
46+
});

0 commit comments

Comments
 (0)