Skip to content

Commit 48113b1

Browse files
pashaGhubpaveleldzis
authored
setupad Bid Adapter: initial commit (prebid#11008)
* create setupadBidAdapter * add setupadBidAdapter * update setupadBidAdapter * update metrics collection * update analytics collection * update getUserSyncs * add setupadAnalyticsAdapter.js * test setupadAnalyticsAdapter * remove test: 1 * add GVLID && bug fixes && test updates * remove setupadAnalyticsAdapter * add userID module handling * add GVLID && bug fixes && test updates * remove setupadAnalyticsAdapter * add userID module handling * clean up && seat bugfix * clean up logs * add userID module handling * update md && clean up * Send setupad only on bidRequested * Fix bidResponse and bidWon responses * Improve bidResponse and bidWon logic * Revert changes to specific files * Remove test parameter * Fix multiple bidResponse and bidTimeout calls to getPixelUrl * eslint errors fixes(brackets added) * Add extra checks for events * Fix BIDDER_CODE const * update reporting endpoint * update setupadBidAdapter_spec.js REPORT_ENDPOINT * update readme * Revert "Merge branch 'prebid:master' into setupad-adapter" This reverts commit 1c14dbe, reversing changes made to 7fe9ea5. * Revert "Revert "Merge branch 'prebid:master' into setupad-adapter"" This reverts commit a34e3e4. * # This is a combination of 20 commits. # This is the 1st commit message: add setupadBidAdapter # This is the commit message #2: update setupadBidAdapter # This is the commit message #3: update metrics collection # This is the commit message #4: update analytics collection # This is the commit message #5: update getUserSyncs # This is the commit message #6: add setupadAnalyticsAdapter.js # This is the commit message #7: test setupadAnalyticsAdapter # This is the commit message #8: remove test: 1 # This is the commit message #9: add GVLID && bug fixes && test updates # This is the commit message #10: remove setupadAnalyticsAdapter # This is the commit message #11: add userID module handling # This is the commit message #12: clean up && seat bugfix # This is the commit message #13: add userID module handling # This is the commit message #14: add GVLID && bug fixes && test updates # This is the commit message #15: remove setupadAnalyticsAdapter # This is the commit message #16: add userID module handling # This is the commit message #17: clean up logs # This is the commit message #18: update md && clean up # This is the commit message #19: Send setupad only on bidRequested # This is the commit message #20: Fix bidResponse and bidWon responses * # This is a combination of 22 commits.tree 8abae7e parent cecfce3 author pavel <[email protected]> 1706627437 +0200 committer pavel <[email protected]> 1706627437 +0200 gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEqGYI3KX/FkbObQG8FABtd4pCs/AFAmW5EW0ACgkQFABtd4pC s/CK3w//WWJSFUlycnnNKTV2XfdcBjooOeZZvjpXVthwr09CCC4uO//kw4bPluhn f5fcVFdXzrY1AZ6ch8Wo3msX/Pkso014jIGd5aIWcHpNYFtffACwH/40Y8AcJNZd bsOZxVK0awPTz/RihC5eY+0J3cP+iFWP/FlYJoHEQIBXq/Eg6mWoAhxwpL/JvxbY QbLFWsRn2ckQ6ftOZgm3/jh8VLaG1zWbWImlWEs5Zel+CorJBTniTj58VbApelYD TFMgbSR2I4NGVaqNIrHePnSMsDATxalQ2nZPwY6raKCHWIbvoUPIn/OpDMMbKgC7 nCwounNmObxFVoj3xusAZppzHpKPasY8xKWb2Kr7zfhZArsOMC6B7fYqQNK0cWG3 8RR/10oheJD9M2kRlfLiqnRv7ExY08SQ/ZMo9LA8BeRUGBXhh6++8FKhKIHvX1gL k1R5W6c+NNWP+PDFsmrFpMn+LpYdl84I7yfYK5dHuw80od7f1wuAVYpswi6Cziy9 /KY6/rfENvUrGTmWSh5GdDBel89ACCfFkasIKB92xhzKTfjzF/DXkc8XQZOMbt1j CsILgWMNfLPMo4Dlgdx/tYCSLLBNEtZ1/hhUcFQ3+0TzLf0GtMkvMnlBnDinqe1n 1P30fQ2I5W5NJKDPrCOnRymI6QOAPFXtMF11R81mbB9H8asft/E= =oJtZ -----END PGP SIGNATURE----- bugfixes # This is the commit message #22: Remove test parameter * # This is a combination of 26 commits. parent cecfce3 author pavel <[email protected]> 1706627437 +0200 committer pavel <[email protected]> 1706627437 +0200 gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEqGYI3KX/FkbObQG8FABtd4pCs/AFAmW5EW0ACgkQFABtd4pC s/CK3w//WWJSFUlycnnNKTV2XfdcBjooOeZZvjpXVthwr09CCC4uO//kw4bPluhn f5fcVFdXzrY1AZ6ch8Wo3msX/Pkso014jIGd5aIWcHpNYFtffACwH/40Y8AcJNZd bsOZxVK0awPTz/RihC5eY+0J3cP+iFWP/FlYJoHEQIBXq/Eg6mWoAhxwpL/JvxbY QbLFWsRn2ckQ6ftOZgm3/jh8VLaG1zWbWImlWEs5Zel+CorJBTniTj58VbApelYD TFMgbSR2I4NGVaqNIrHePnSMsDATxalQ2nZPwY6raKCHWIbvoUPIn/OpDMMbKgC7 nCwounNmObxFVoj3xusAZppzHpKPasY8xKWb2Kr7zfhZArsOMC6B7fYqQNK0cWG3 8RR/10oheJD9M2kRlfLiqnRv7ExY08SQ/ZMo9LA8BeRUGBXhh6++8FKhKIHvX1gL k1R5W6c+NNWP+PDFsmrFpMn+LpYdl84I7yfYK5dHuw80od7f1wuAVYpswi6Cziy9 /KY6/rfENvUrGTmWSh5GdDBel89ACCfFkasIKB92xhzKTfjzF/DXkc8XQZOMbt1j CsILgWMNfLPMo4Dlgdx/tYCSLLBNEtZ1/hhUcFQ3+0TzLf0GtMkvMnlBnDinqe1n 1P30fQ2I5W5NJKDPrCOnRymI6QOAPFXtMF11R81mbB9H8asft/E= =oJtZ -----END PGP SIGNATURE----- bugfixes # This is the commit message #22: Remove test parameter # This is the commit message #23: Fix multiple bidResponse and bidTimeout calls to getPixelUrl # This is the commit message #25: eslint errors fixes(brackets added) # This is the commit message #26: Add extra checks for events * parent 75178b9 author pavel <[email protected]> 1706627694 +0200 committer pavel <[email protected]> 1706627694 +0200 gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEqGYI3KX/FkbObQG8FABtd4pCs/AFAmW5Em4ACgkQFABtd4pC s/BBUQ/+NXyHoxPM185YJLG9M1ySC/5vTT9W5mfwQ93cVDLCeuGnpsnmi4S21NuQ b7gSeokFjwztvVOUmh/xqMp4lTsvL53TUd00b1k4KGVSqgcF00Foit5g8fOGLYsI DAoqphYV6MWjpAun+II+ELY8QUkHR1cjTc7PEGtmf+8RnptGVdyJ6C9Ab8u9TQTY Apj5Srhfo3Tl8S+WScOxwwB/uqEJR4fhIrJyzFzdLDEb2olSPyrQUs87vQXlhEnK buPEg2F5JsRH6sw11Xp3TFNSZGxNnBSlTh9dixou5md4yRCv5a2TMef667N0BVDp lGgc7mCrRKXyqzphmmeHudiscEGFjtUPObXoHutSVw22wdARFCTpNFKBLLFn4v8o Zv1OvFdNprvHsoeW0HVlZdU7OKnDTRrko6DHk2AahxojjvAFEWuDsGYZNjhdQwRR lK1zm+SFQnKI0Eojd+f84fvKod9geGs640jyH/x5R4eYm4yjZb8SkRtd3cca88wS OuGq9LIkbU428b46l7VnDwudldTXPUU8eKfUtFRjdGtIWH9I3tK6TsRoCfTcXkv0 smxYiiU1XHjAkkPFWQWEeFdfZ071snFKVWouU0AoKiq+PdRoS8+3AJqIQUjlA2sH AybnSkv9KxY/Rs1bnvMubsQm1GF66qVrbxBU6FILBv1JZYwj4yA= =Gbog -----END PGP SIGNATURE----- bugfixes update setupadBidAdapter_spec.js REPORT_ENDPOINT update readme Revert "Merge branch 'prebid:master' into setupad-adapter" This reverts commit 1c14dbe, reversing changes made to 7fe9ea5. Revert "Revert "Merge branch 'prebid:master' into setupad-adapter"" This reverts commit a34e3e4. * change double quote to single quote --------- Co-authored-by: pavel <[email protected]> Co-authored-by: Elgars Grodnis <[email protected]> * bugfix setupadBidAdapter remove getAdEl, spelling correction * add onBidWon event onBidWon event handling moved from custom to native onBidWon method * minor bugfixes && remove funk getSiteObj && getDeviceObj --------- Co-authored-by: pavel <[email protected]> Co-authored-by: Elgars Grodnis <[email protected]>
1 parent 90822c6 commit 48113b1

File tree

3 files changed

+654
-0
lines changed

3 files changed

+654
-0
lines changed

modules/setupadBidAdapter.js

+271
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
import {
2+
_each,
3+
createTrackPixelHtml,
4+
deepAccess,
5+
isStr,
6+
getBidIdParameter,
7+
triggerPixel,
8+
logWarn,
9+
} from '../src/utils.js';
10+
import { registerBidder } from '../src/adapters/bidderFactory.js';
11+
import { BANNER } from '../src/mediaTypes.js';
12+
13+
const BIDDER_CODE = 'setupad';
14+
const ENDPOINT = 'https://prebid.setupad.io/openrtb2/auction';
15+
const SYNC_ENDPOINT = 'https://cookie.stpd.cloud/sync?';
16+
const REPORT_ENDPOINT = 'https://adapter-analytics.setupad.io/api/adapter-analytics';
17+
const GVLID = 1241;
18+
const TIME_TO_LIVE = 360;
19+
const biddersCreativeIds = {};
20+
21+
function getEids(bidRequest) {
22+
if (deepAccess(bidRequest, 'userIdAsEids')) return bidRequest.userIdAsEids;
23+
}
24+
25+
export const spec = {
26+
code: BIDDER_CODE,
27+
supportedMediaTypes: [BANNER],
28+
gvlid: GVLID,
29+
30+
isBidRequestValid: function (bid) {
31+
return !!(bid.params.placement_id && isStr(bid.params.placement_id));
32+
},
33+
34+
buildRequests: function (validBidRequests, bidderRequest) {
35+
const requests = [];
36+
37+
_each(validBidRequests, function (bid) {
38+
const id = getBidIdParameter('placement_id', bid.params);
39+
const accountId = getBidIdParameter('account_id', bid.params);
40+
const auctionId = bid.auctionId;
41+
const bidId = bid.bidId;
42+
const eids = getEids(bid) || undefined;
43+
let sizes = bid.sizes;
44+
if (sizes && !Array.isArray(sizes[0])) sizes = [sizes];
45+
46+
const site = {
47+
page: bidderRequest?.refererInfo?.page,
48+
ref: bidderRequest?.refererInfo?.ref,
49+
domain: bidderRequest?.refererInfo?.domain,
50+
};
51+
const device = {
52+
w: bidderRequest?.ortb2?.device?.w,
53+
h: bidderRequest?.ortb2?.device?.h,
54+
};
55+
56+
const payload = {
57+
id: bid?.bidderRequestId,
58+
ext: {
59+
prebid: {
60+
storedrequest: {
61+
id: accountId || 'default',
62+
},
63+
},
64+
},
65+
user: { ext: { eids } },
66+
device,
67+
site,
68+
imp: [],
69+
};
70+
71+
const imp = {
72+
id: bid.adUnitCode,
73+
ext: {
74+
prebid: {
75+
storedrequest: { id },
76+
},
77+
},
78+
};
79+
80+
if (deepAccess(bid, 'mediaTypes.banner')) {
81+
imp.banner = {
82+
format: (sizes || []).map((s) => {
83+
return { w: s[0], h: s[1] };
84+
}),
85+
};
86+
}
87+
88+
payload.imp.push(imp);
89+
90+
const gdprConsent = bidderRequest && bidderRequest.gdprConsent;
91+
const uspConsent = bidderRequest && bidderRequest.uspConsent;
92+
93+
if (gdprConsent || uspConsent) {
94+
payload.regs = { ext: {} };
95+
96+
if (uspConsent) payload.regs.ext.us_privacy = uspConsent;
97+
98+
if (gdprConsent) {
99+
if (typeof gdprConsent.gdprApplies !== 'undefined') {
100+
payload.regs.ext.gdpr = gdprConsent.gdprApplies ? 1 : 0;
101+
}
102+
103+
if (typeof gdprConsent.consentString !== 'undefined') {
104+
payload.user.ext.consent = gdprConsent.consentString;
105+
}
106+
}
107+
}
108+
const params = bid.params;
109+
110+
requests.push({
111+
method: 'POST',
112+
url: ENDPOINT,
113+
data: JSON.stringify(payload),
114+
options: {
115+
contentType: 'text/plain',
116+
withCredentials: true,
117+
},
118+
119+
bidId,
120+
params,
121+
auctionId,
122+
});
123+
});
124+
125+
return requests;
126+
},
127+
128+
interpretResponse: function (serverResponse, bidRequest) {
129+
if (
130+
!serverResponse ||
131+
!serverResponse.body ||
132+
typeof serverResponse.body != 'object' ||
133+
Object.keys(serverResponse.body).length === 0
134+
) {
135+
logWarn('no response or body is malformed');
136+
return [];
137+
}
138+
139+
const serverBody = serverResponse.body;
140+
const bidResponses = [];
141+
142+
_each(serverBody.seatbid, (res) => {
143+
_each(res.bid, (bid) => {
144+
const requestId = bidRequest.bidId;
145+
const params = bidRequest.params;
146+
const { ad, adUrl } = getAd(bid);
147+
148+
const bidResponse = {
149+
requestId,
150+
params,
151+
cpm: bid.price,
152+
width: bid.w,
153+
height: bid.h,
154+
creativeId: bid.id,
155+
currency: serverBody.cur,
156+
netRevenue: true,
157+
ttl: TIME_TO_LIVE,
158+
meta: {
159+
advertiserDomains: bid.adomain || [],
160+
},
161+
};
162+
163+
// set a seat for creativeId for triggerPixel url
164+
biddersCreativeIds[bidResponse.creativeId] = res.seat;
165+
166+
bidResponse.ad = ad;
167+
bidResponse.adUrl = adUrl;
168+
bidResponses.push(bidResponse);
169+
});
170+
});
171+
172+
return bidResponses;
173+
},
174+
175+
getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) {
176+
if (!responses?.length) return [];
177+
178+
const syncs = [];
179+
const bidders = getBidders(responses);
180+
181+
if (syncOptions.iframeEnabled && bidders) {
182+
const queryParams = [];
183+
184+
queryParams.push(`bidders=${bidders}`);
185+
queryParams.push('gdpr=' + +gdprConsent.gdprApplies);
186+
queryParams.push('gdpr_consent=' + gdprConsent.consentString);
187+
queryParams.push('usp_consent=' + (uspConsent || ''));
188+
189+
const strQueryParams = queryParams.join('&');
190+
191+
syncs.push({
192+
type: 'iframe',
193+
url: SYNC_ENDPOINT + strQueryParams + '&type=iframe',
194+
});
195+
196+
return syncs;
197+
}
198+
199+
return [];
200+
},
201+
202+
onBidWon: function (bid) {
203+
let bidder = bid.bidder || bid.bidderCode;
204+
const auctionId = bid.auctionId;
205+
if (bidder !== BIDDER_CODE) return;
206+
207+
let params;
208+
if (bid.params) {
209+
params = Array.isArray(bid.params) ? bid.params : [bid.params];
210+
} else {
211+
if (Array.isArray(bid.bids)) {
212+
params = bid.bids.map((singleBid) => singleBid.params);
213+
}
214+
}
215+
216+
if (!params?.length) return;
217+
218+
const placementIdsArray = [];
219+
params.forEach((param) => {
220+
if (!param.placement_id) return;
221+
placementIdsArray.push(param.placement_id);
222+
});
223+
224+
const placementIds = (placementIdsArray.length && placementIdsArray.join(';')) || '';
225+
226+
if (!placementIds) return;
227+
228+
let extraBidParams = '';
229+
230+
// find the winning bidder by using creativeId as identification
231+
if (biddersCreativeIds.hasOwnProperty(bid.creativeId) && biddersCreativeIds[bid.creativeId]) {
232+
bidder = biddersCreativeIds[bid.creativeId];
233+
}
234+
235+
// Add extra parameters
236+
extraBidParams = `&cpm=${bid.originalCpm}&currency=${bid.originalCurrency}`;
237+
238+
const url = `${REPORT_ENDPOINT}?event=bidWon&bidder=${bidder}&placementIds=${placementIds}&auctionId=${auctionId}${extraBidParams}&timestamp=${Date.now()}`;
239+
triggerPixel(url);
240+
},
241+
};
242+
243+
function getBidders(serverResponse) {
244+
const bidders = serverResponse
245+
.map((res) => Object.keys(res.body.ext.responsetimemillis || []))
246+
.flat(1);
247+
248+
if (bidders.length) {
249+
return encodeURIComponent(JSON.stringify([...new Set(bidders)]));
250+
}
251+
}
252+
253+
function getAd(bid) {
254+
let ad, adUrl;
255+
256+
switch (deepAccess(bid, 'ext.prebid.type')) {
257+
default:
258+
if (bid.adm && bid.nurl) {
259+
ad = bid.adm;
260+
ad += createTrackPixelHtml(decodeURIComponent(bid.nurl));
261+
} else if (bid.adm) {
262+
ad = bid.adm;
263+
} else if (bid.nurl) {
264+
adUrl = bid.nurl;
265+
}
266+
}
267+
268+
return { ad, adUrl };
269+
}
270+
271+
registerBidder(spec);

modules/setupadBidAdapter.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Overview
2+
3+
```text
4+
Module Name: Setupad Bid Adapter
5+
Module Type: Bidder Adapter
6+
Maintainer: [email protected]
7+
```
8+
9+
# Description
10+
11+
Module that connects to Setupad's demand sources.
12+
13+
# Test Parameters
14+
15+
```js
16+
const adUnits = [
17+
{
18+
code: 'test-div',
19+
mediaTypes: {
20+
banner: {
21+
sizes: [[300, 250]],
22+
},
23+
},
24+
bids: [
25+
{
26+
bidder: 'setupad',
27+
params: {
28+
placement_id: '123', //required
29+
account_id: '123', //optional
30+
},
31+
},
32+
],
33+
},
34+
];
35+
```

0 commit comments

Comments
 (0)