|
1 | | -import { isFn, isPlainObject } from '../src/utils.js'; |
2 | | -import { registerBidder } from '../src/adapters/bidderFactory.js'; |
| 1 | +import {registerBidder} from '../src/adapters/bidderFactory.js'; |
| 2 | +import {ortbConverter} from '../libraries/ortbConverter/converter.js'; |
| 3 | +import {BANNER} from '../src/mediaTypes.js'; |
| 4 | +import {deepSetValue} from '../src/utils.js'; |
3 | 5 |
|
4 | 6 | const BIDDER_CODE = 'proxistore'; |
5 | 7 | const PROXISTORE_VENDOR_ID = 418; |
6 | | -const COOKIE_BASE_URL = 'https://abs.proxistore.com/v3/rtb/prebid/multi'; |
7 | | -const COOKIE_LESS_URL = |
8 | | - 'https://abs.cookieless-proxistore.com/v3/rtb/prebid/multi'; |
9 | | - |
10 | | -function _createServerRequest(bidRequests, bidderRequest) { |
11 | | - var sizeIds = []; |
12 | | - bidRequests.forEach(function (bid) { |
13 | | - var sizeId = { |
14 | | - id: bid.bidId, |
15 | | - sizes: bid.sizes.map(function (size) { |
16 | | - return { |
17 | | - width: size[0], |
18 | | - height: size[1], |
19 | | - }; |
20 | | - }), |
21 | | - floor: _assignFloor(bid), |
22 | | - segments: _assignSegments(bid), |
23 | | - }; |
24 | | - sizeIds.push(sizeId); |
25 | | - }); |
26 | | - var payload = { |
27 | | - // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 |
28 | | - auctionId: bidRequests[0].auctionId, |
29 | | - transactionId: bidRequests[0].ortb2Imp?.ext?.tid, |
30 | | - bids: sizeIds, |
31 | | - website: bidRequests[0].params.website, |
32 | | - language: bidRequests[0].params.language, |
33 | | - gdpr: { |
34 | | - applies: false, |
35 | | - consentGiven: false, |
36 | | - }, |
37 | | - }; |
| 8 | +const COOKIE_BASE_URL = 'https://abs.proxistore.com/v3/rtb/openrtb'; |
| 9 | +const COOKIE_LESS_URL = 'https://abs.cookieless-proxistore.com/v3/rtb/openrtb'; |
| 10 | +const SYNC_BASE_URL = 'https://abs.proxistore.com/v3/rtb/sync'; |
| 11 | + |
| 12 | +const converter = ortbConverter({ |
| 13 | + context: { |
| 14 | + mediaType: BANNER, |
| 15 | + netRevenue: true, |
| 16 | + ttl: 30, |
| 17 | + currency: 'EUR', |
| 18 | + }, |
| 19 | + request(buildRequest, imps, bidderRequest, context) { |
| 20 | + const request = buildRequest(imps, bidderRequest, context); |
| 21 | + const bidRequests = context.bidRequests; |
| 22 | + if (bidRequests && bidRequests.length > 0) { |
| 23 | + const params = bidRequests[0].params; |
| 24 | + if (params.website) { |
| 25 | + deepSetValue(request, 'ext.proxistore.website', params.website); |
| 26 | + } |
| 27 | + if (params.language) { |
| 28 | + deepSetValue(request, 'ext.proxistore.language', params.language); |
| 29 | + } |
| 30 | + } |
| 31 | + return request; |
| 32 | + } |
| 33 | +}); |
38 | 34 |
|
39 | | - if (bidderRequest && bidderRequest.gdprConsent) { |
40 | | - var gdprConsent = bidderRequest.gdprConsent; |
| 35 | +/** |
| 36 | + * Determines whether or not the given bid request is valid. |
| 37 | + * |
| 38 | + * @param bid The bid params to validate. |
| 39 | + * @return boolean True if this is a valid bid, and false otherwise. |
| 40 | + */ |
| 41 | +function isBidRequestValid(bid) { |
| 42 | + return !!(bid.params.website && bid.params.language); |
| 43 | +} |
41 | 44 |
|
42 | | - if ( |
43 | | - typeof gdprConsent.gdprApplies === 'boolean' && |
44 | | - gdprConsent.gdprApplies |
45 | | - ) { |
46 | | - payload.gdpr.applies = true; |
47 | | - } |
| 45 | +/** |
| 46 | + * Make a server request from the list of BidRequests. |
| 47 | + * |
| 48 | + * @param bidRequests - an array of bids |
| 49 | + * @param bidderRequest |
| 50 | + * @return ServerRequest Info describing the request to the server. |
| 51 | + */ |
| 52 | +function buildRequests(bidRequests, bidderRequest) { |
| 53 | + let gdprApplies = false; |
| 54 | + let consentGiven = false; |
| 55 | + |
| 56 | + if (bidderRequest && bidderRequest.gdprConsent) { |
| 57 | + const gdprConsent = bidderRequest.gdprConsent; |
48 | 58 |
|
49 | | - if ( |
50 | | - typeof gdprConsent.consentString === 'string' && |
51 | | - gdprConsent.consentString |
52 | | - ) { |
53 | | - payload.gdpr.consentString = bidderRequest.gdprConsent.consentString; |
| 59 | + if (typeof gdprConsent.gdprApplies === 'boolean' && gdprConsent.gdprApplies) { |
| 60 | + gdprApplies = true; |
54 | 61 | } |
55 | 62 |
|
56 | 63 | if (gdprConsent.vendorData) { |
57 | | - var vendorData = gdprConsent.vendorData; |
58 | | - |
| 64 | + const vendorData = gdprConsent.vendorData; |
59 | 65 | if ( |
60 | 66 | vendorData.vendor && |
61 | 67 | vendorData.vendor.consents && |
62 | | - typeof vendorData.vendor.consents[PROXISTORE_VENDOR_ID.toString(10)] !== |
63 | | - 'undefined' |
| 68 | + vendorData.vendor.consents[PROXISTORE_VENDOR_ID.toString(10)] !== 'undefined' |
64 | 69 | ) { |
65 | | - payload.gdpr.consentGiven = |
66 | | - !!vendorData.vendor.consents[PROXISTORE_VENDOR_ID.toString(10)]; |
| 70 | + consentGiven = !!vendorData.vendor.consents[PROXISTORE_VENDOR_ID.toString(10)]; |
67 | 71 | } |
68 | 72 | } |
69 | 73 | } |
70 | 74 |
|
71 | | - var options = { |
| 75 | + const options = { |
72 | 76 | contentType: 'application/json', |
73 | | - withCredentials: payload.gdpr.consentGiven, |
| 77 | + withCredentials: consentGiven, |
74 | 78 | customHeaders: { |
75 | | - version: '1.0.4', |
| 79 | + version: '2.0.0', |
76 | 80 | }, |
77 | 81 | }; |
78 | | - var endPointUri = |
79 | | - payload.gdpr.consentGiven || !payload.gdpr.applies |
80 | | - ? COOKIE_BASE_URL |
81 | | - : COOKIE_LESS_URL; |
| 82 | + |
| 83 | + const endPointUri = consentGiven || !gdprApplies ? COOKIE_BASE_URL : COOKIE_LESS_URL; |
82 | 84 |
|
83 | 85 | return { |
84 | 86 | method: 'POST', |
85 | 87 | url: endPointUri, |
86 | | - data: JSON.stringify(payload), |
| 88 | + data: converter.toORTB({ bidRequests, bidderRequest }), |
87 | 89 | options: options, |
88 | 90 | }; |
89 | 91 | } |
90 | 92 |
|
91 | | -function _assignSegments(bid) { |
92 | | - var segs = (bid.ortb2 && bid.ortb2.user && bid.ortb2.user.ext && bid.ortb2.user.ext.data && bid.ortb2.user.ext.data.sd_rtd && bid.ortb2.user.ext.data.sd_rtd.segments ? bid.ortb2.user.ext.data.sd_rtd.segments : []); |
93 | | - var cats = {}; |
94 | | - if (bid.ortb2 && bid.ortb2.site && bid.ortb2.site.ext && bid.ortb2.site.ext.data && bid.ortb2.site.ext.data.sd_rtd) { |
95 | | - if (bid.ortb2.site.ext.data.sd_rtd.categories) { |
96 | | - segs = segs.concat(bid.ortb2.site.ext.data.sd_rtd.categories); |
97 | | - } |
98 | | - if (bid.ortb2.site.ext.data.sd_rtd.categories_score) { |
99 | | - cats = bid.ortb2.site.ext.data.sd_rtd.categories_score; |
100 | | - } |
101 | | - } |
102 | | - |
103 | | - return { |
104 | | - segments: segs, |
105 | | - contextual_categories: cats |
106 | | - }; |
107 | | -} |
108 | | - |
109 | | -function _createBidResponse(response) { |
110 | | - return { |
111 | | - requestId: response.requestId, |
112 | | - cpm: response.cpm, |
113 | | - width: response.width, |
114 | | - height: response.height, |
115 | | - ad: response.ad, |
116 | | - ttl: response.ttl, |
117 | | - creativeId: response.creativeId, |
118 | | - currency: response.currency, |
119 | | - netRevenue: response.netRevenue, |
120 | | - vastUrl: response.vastUrl, |
121 | | - vastXml: response.vastXml, |
122 | | - dealId: response.dealId, |
123 | | - meta: response.meta, |
124 | | - }; |
125 | | -} |
126 | 93 | /** |
127 | | - * Determines whether or not the given bid request is valid. |
| 94 | + * Unpack the response from the server into a list of bids. |
128 | 95 | * |
129 | | - * @param bid The bid params to validate. |
130 | | - * @return boolean True if this is a valid bid, and false otherwise. |
| 96 | + * @param response |
| 97 | + * @param request |
| 98 | + * @return An array of bids which were nested inside the server. |
131 | 99 | */ |
132 | | - |
133 | | -function isBidRequestValid(bid) { |
134 | | - return !!(bid.params.website && bid.params.language); |
| 100 | +function interpretResponse(response, request) { |
| 101 | + if (response.body) { |
| 102 | + return converter.fromORTB({response: response.body, request: request.data}).bids; |
| 103 | + } |
| 104 | + return []; |
135 | 105 | } |
136 | | -/** |
137 | | - * Make a server request from the list of BidRequests. |
138 | | - * |
139 | | - * @param bidRequests - an array of bids |
140 | | - * @param bidderRequest |
141 | | - * @return ServerRequest Info describing the request to the server. |
142 | | - */ |
143 | | - |
144 | | -function buildRequests(bidRequests, bidderRequest) { |
145 | | - var request = _createServerRequest(bidRequests, bidderRequest); |
146 | 106 |
|
147 | | - return request; |
148 | | -} |
149 | 107 | /** |
150 | | - * Unpack the response from the server into a list of bids. |
| 108 | + * Register user sync pixels and iframes. |
151 | 109 | * |
152 | | - * @param serverResponse A successful response from the server. |
153 | | - * @param bidRequest Request original server request |
154 | | - * @return An array of bids which were nested inside the server. |
| 110 | + * @param syncOptions - which sync types are enabled |
| 111 | + * @param responses - server responses |
| 112 | + * @param gdprConsent - GDPR consent data |
| 113 | + * @return Array of sync objects |
155 | 114 | */ |
| 115 | +function getUserSyncs(syncOptions, responses, gdprConsent) { |
| 116 | + const syncs = []; |
156 | 117 |
|
157 | | -function interpretResponse(serverResponse, bidRequest) { |
158 | | - return serverResponse.body.map(_createBidResponse); |
159 | | -} |
| 118 | + // Only sync if consent given or GDPR doesn't apply |
| 119 | + const consentGiven = gdprConsent?.vendorData?.vendor?.consents?.[PROXISTORE_VENDOR_ID]; |
| 120 | + if (gdprConsent?.gdprApplies && !consentGiven) { |
| 121 | + return syncs; |
| 122 | + } |
160 | 123 |
|
161 | | -function _assignFloor(bid) { |
162 | | - if (!isFn(bid.getFloor)) { |
163 | | - return bid.params.bidFloor ? bid.params.bidFloor : null; |
| 124 | + const params = new URLSearchParams(); |
| 125 | + if (gdprConsent) { |
| 126 | + params.set('gdpr', gdprConsent.gdprApplies ? '1' : '0'); |
| 127 | + if (gdprConsent.consentString) { |
| 128 | + params.set('gdpr_consent', gdprConsent.consentString); |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | + if (syncOptions.pixelEnabled) { |
| 133 | + syncs.push({ |
| 134 | + type: 'image', |
| 135 | + url: `${SYNC_BASE_URL}/image?${params}` |
| 136 | + }); |
164 | 137 | } |
165 | | - const floor = bid.getFloor({ |
166 | | - currency: 'EUR', |
167 | | - mediaType: 'banner', |
168 | | - size: '*', |
169 | | - }); |
170 | 138 |
|
171 | | - if (isPlainObject(floor) && !isNaN(floor.floor) && floor.currency === 'EUR') { |
172 | | - return floor.floor; |
| 139 | + if (syncOptions.iframeEnabled) { |
| 140 | + syncs.push({ |
| 141 | + type: 'iframe', |
| 142 | + url: `${SYNC_BASE_URL}/iframe?${params}` |
| 143 | + }); |
173 | 144 | } |
174 | | - return null; |
| 145 | + |
| 146 | + return syncs; |
175 | 147 | } |
176 | 148 |
|
177 | 149 | export const spec = { |
178 | 150 | code: BIDDER_CODE, |
| 151 | + gvlid: PROXISTORE_VENDOR_ID, |
179 | 152 | isBidRequestValid: isBidRequestValid, |
180 | 153 | buildRequests: buildRequests, |
181 | 154 | interpretResponse: interpretResponse, |
182 | | - gvlid: PROXISTORE_VENDOR_ID, |
| 155 | + getUserSyncs: getUserSyncs, |
| 156 | + supportedMediaTypes: [BANNER], |
| 157 | + browsingTopics: true, |
183 | 158 | }; |
184 | 159 |
|
185 | 160 | registerBidder(spec); |
0 commit comments