|
| 1 | +import * as utils from '../src/utils'; |
| 2 | +import { registerBidder } from '../src/adapters/bidderFactory'; |
| 3 | +import includes from 'core-js/library/fn/array/includes'; |
| 4 | +import {BANNER, VIDEO} from '../src/mediaTypes'; |
| 5 | + |
| 6 | +const VIDEO_TARGETING = ['mimes', 'minduration', 'maxduration', 'protocols', |
| 7 | + 'startdelay', 'linearity', 'skip', 'delivery', |
| 8 | + 'pos', 'api', 'ext', 'battr']; |
| 9 | +const BANNER_TARGETING = ['battr', 'btype', 'pos', 'mimes', 'ext']; |
| 10 | + |
| 11 | +const SITE_TARGETING = ['name', 'domain', 'cat', 'keywords', 'content'] |
| 12 | +const APP_TARGETING = ['name', 'bundle', 'domain', 'storeUrl', 'cat', 'ver', 'keywords', 'content'] |
| 13 | + |
| 14 | +export const spec = { |
| 15 | + |
| 16 | + code: 'somo', |
| 17 | + |
| 18 | + supportedMediaTypes: [BANNER, VIDEO], |
| 19 | + aliases: ['somoaudience'], |
| 20 | + |
| 21 | + isBidRequestValid: bid => ( |
| 22 | + !!(bid && bid.params && bid.params.placementId) |
| 23 | + ), |
| 24 | + |
| 25 | + buildRequests: function(bidRequests, bidderRequest) { |
| 26 | + return bidRequests.map(bidRequest => { |
| 27 | + let da = openRtbRequest(bidRequest, bidderRequest); |
| 28 | + |
| 29 | + return { |
| 30 | + method: 'POST', |
| 31 | + url: 'https://publisher-east.mobileadtrading.com/rtb/bid?s=' + bidRequest.params.placementId.toString(), |
| 32 | + data: da, |
| 33 | + bidRequest: bidRequest |
| 34 | + }; |
| 35 | + }); |
| 36 | + }, |
| 37 | + |
| 38 | + interpretResponse(response, request) { |
| 39 | + return bidResponseAvailable(request, response); |
| 40 | + }, |
| 41 | + |
| 42 | + getUserSyncs: (syncOptions, serverResponses, gdprConsent) => { |
| 43 | + const syncs = []; |
| 44 | + var url = 'https://publisher-east.mobileadtrading.com/usersync'; |
| 45 | + |
| 46 | + if (syncOptions.pixelEnabled) { |
| 47 | + if (gdprConsent && typeof gdprConsent.consentString === 'string') { |
| 48 | + // add 'gdpr' only if 'gdprApplies' is defined |
| 49 | + if (typeof gdprConsent.gdprApplies === 'boolean') { |
| 50 | + url += `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; |
| 51 | + } |
| 52 | + } |
| 53 | + syncs.push({ |
| 54 | + type: 'image', |
| 55 | + url: url |
| 56 | + }); |
| 57 | + } |
| 58 | + return syncs; |
| 59 | + } |
| 60 | +}; |
| 61 | + |
| 62 | +function bidResponseAvailable(bidRequest, bidResponse) { |
| 63 | + let bidResponses = []; |
| 64 | + |
| 65 | + if (bidResponse.body) { |
| 66 | + let bidData = bidResponse.body.seatbid[0].bid[0]; |
| 67 | + const bid = { |
| 68 | + requestId: bidResponse.body.id, |
| 69 | + cpm: bidData.price, |
| 70 | + width: bidData.w, |
| 71 | + height: bidData.h, |
| 72 | + ad: bidData.adm, |
| 73 | + ttl: 360, |
| 74 | + creativeId: bidData.crid, |
| 75 | + adId: bidData.impid, |
| 76 | + netRevenue: false, |
| 77 | + currency: 'USD', |
| 78 | + adUnitCode: bidRequest.bidRequest.adUnitCode |
| 79 | + }; |
| 80 | + if (isVideo(bidRequest.bidRequest)) { |
| 81 | + bid.vastXml = bidData.adm; |
| 82 | + bid.mediaType = 'video'; |
| 83 | + } else { |
| 84 | + bid.ad = bidData.adm; |
| 85 | + bid.mediaType = 'banner'; |
| 86 | + } |
| 87 | + bidResponses.push(bid); |
| 88 | + } |
| 89 | + return bidResponses; |
| 90 | +} |
| 91 | + |
| 92 | +function openRtbRequest(bidRequest, bidderRequest) { |
| 93 | + var openRtbRequest = { |
| 94 | + id: bidRequest.bidId, |
| 95 | + imp: [openRtbImpression(bidRequest)], |
| 96 | + at: 1, |
| 97 | + tmax: 400, |
| 98 | + site: openRtbSite(bidRequest, bidderRequest), |
| 99 | + app: openRtbApp(bidRequest), |
| 100 | + device: openRtbDevice(), |
| 101 | + bcat: openRtbBCat(bidRequest), |
| 102 | + badv: openRtbBAdv(bidRequest), |
| 103 | + ext: { |
| 104 | + prebid: '$prebid.version$', |
| 105 | + }, |
| 106 | + }; |
| 107 | + if (typeof bidderRequest !== 'undefined') { |
| 108 | + openRtbRequest = populateOpenRtbGdpr(bidderRequest.gdprConsent, openRtbRequest); |
| 109 | + } |
| 110 | + |
| 111 | + return openRtbRequest; |
| 112 | +} |
| 113 | + |
| 114 | +function populateOpenRtbGdpr(gdpr, bidRequest) { |
| 115 | + if (gdpr && bidRequest && 'gdprApplies' in gdpr) { |
| 116 | + if (!('reqs' in bidRequest)) { |
| 117 | + bidRequest.reqs = {}; |
| 118 | + } |
| 119 | + if (!('ext' in bidRequest.reqs)) { |
| 120 | + bidRequest.reqs.ext = {}; |
| 121 | + } |
| 122 | + bidRequest.reqs.ext.gdpr = gdpr.gdprApplies; |
| 123 | + |
| 124 | + if ('consentString' in gdpr) { |
| 125 | + if (!('user' in bidRequest)) { |
| 126 | + bidRequest.user = {}; |
| 127 | + } |
| 128 | + if (!('ext' in bidRequest.user)) { |
| 129 | + bidRequest.user.ext = {}; |
| 130 | + } |
| 131 | + bidRequest.user.ext.consent = gdpr.consentString; |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + return bidRequest; |
| 136 | +} |
| 137 | + |
| 138 | +function openRtbImpression(bidRequest) { |
| 139 | + const imp = { |
| 140 | + 'id': bidRequest.bidId, |
| 141 | + bidfloor: bidRequest.params.bidfloor || 0, |
| 142 | + }; |
| 143 | + if (isVideo(bidRequest)) { |
| 144 | + imp.video = {}; |
| 145 | + if (bidRequest.mediaTypes && |
| 146 | + bidRequest.mediaTypes.video && |
| 147 | + bidRequest.mediaTypes.video.sizes) { |
| 148 | + const sizes = getSizes(bidRequest.mediaTypes.video.sizes); |
| 149 | + imp.video.w = sizes[0]; |
| 150 | + imp.video.h = sizes[1]; |
| 151 | + } |
| 152 | + if (bidRequest.params.video) { |
| 153 | + Object.keys(bidRequest.params.video) |
| 154 | + .filter(param => includes(VIDEO_TARGETING, param)) |
| 155 | + .forEach(param => imp.video[param] = bidRequest.params.video[param]); |
| 156 | + } |
| 157 | + } else { |
| 158 | + imp.banner = { |
| 159 | + topframe: 0 |
| 160 | + }; |
| 161 | + if (bidRequest.mediaTypes && |
| 162 | + bidRequest.mediaTypes.banner && |
| 163 | + bidRequest.mediaTypes.banner.sizes) { |
| 164 | + const sizes = getSizes(bidRequest.mediaTypes.banner.sizes); |
| 165 | + imp.banner.w = sizes[0]; |
| 166 | + imp.banner.h = sizes[1]; |
| 167 | + } |
| 168 | + if (bidRequest.params.banner) { |
| 169 | + Object.keys(bidRequest.params.banner) |
| 170 | + .filter(param => includes(BANNER_TARGETING, param)) |
| 171 | + .forEach(param => imp.banner[param] = bidRequest.params.banner[param]); |
| 172 | + } |
| 173 | + } |
| 174 | + return imp; |
| 175 | +} |
| 176 | + |
| 177 | +function isApp(bidRequest) { |
| 178 | + if (bidRequest.params.app) { |
| 179 | + return true; |
| 180 | + } else { |
| 181 | + return false; |
| 182 | + } |
| 183 | +} |
| 184 | + |
| 185 | +function openRtbSite(bidRequest, bidderRequest) { |
| 186 | + if (!isApp(bidRequest)) { |
| 187 | + const site = {}; |
| 188 | + |
| 189 | + if (bidderRequest && bidderRequest.refererInfo) { |
| 190 | + site.ref = bidderRequest.refererInfo.referer; |
| 191 | + site.page = bidderRequest.refererInfo.canonicalUrl; |
| 192 | + } |
| 193 | + |
| 194 | + if (bidRequest.params.site) { |
| 195 | + Object.keys(bidRequest.params.site) |
| 196 | + .filter(param => includes(SITE_TARGETING, param)) |
| 197 | + .forEach(param => site[param] = bidRequest.params.site[param]); |
| 198 | + } |
| 199 | + if (typeof site.domain === 'undefined' && |
| 200 | + typeof site.page !== 'undefined') { |
| 201 | + if (typeof window.URL === 'function') { |
| 202 | + site.domain = (new window.URL(site.page)).hostname; |
| 203 | + } else { |
| 204 | + site.domain = getDomainFromUrl(site.page); |
| 205 | + } |
| 206 | + } |
| 207 | + |
| 208 | + return site; |
| 209 | + } else { |
| 210 | + return null; |
| 211 | + } |
| 212 | +} |
| 213 | + |
| 214 | +function getDomainFromUrl(url) { |
| 215 | + var domain = url; |
| 216 | + |
| 217 | + if (url.indexOf('//') > -1) { |
| 218 | + domain = url.split('/')[2]; |
| 219 | + } else { |
| 220 | + domain = url.split('/')[0]; |
| 221 | + } |
| 222 | + |
| 223 | + domain = domain.split(':')[0]; |
| 224 | + domain = domain.split('?')[0]; |
| 225 | + |
| 226 | + return domain; |
| 227 | +} |
| 228 | + |
| 229 | +function openRtbApp(bidRequest) { |
| 230 | + if (isApp(bidRequest)) { |
| 231 | + const app = { |
| 232 | + |
| 233 | + } |
| 234 | + Object.keys(bidRequest.params.app) |
| 235 | + .filter(param => includes(APP_TARGETING, param)) |
| 236 | + .forEach(param => app[param] = bidRequest.params.app[param]); |
| 237 | + |
| 238 | + return app; |
| 239 | + } else { |
| 240 | + return null; |
| 241 | + } |
| 242 | +} |
| 243 | + |
| 244 | +function openRtbDevice() { |
| 245 | + return { |
| 246 | + ip: 'check', |
| 247 | + ua: navigator.userAgent, |
| 248 | + language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), |
| 249 | + }; |
| 250 | +} |
| 251 | + |
| 252 | +function openRtbBCat(bidRequest) { |
| 253 | + if (utils.isArray(bidRequest.params.bcat)) { |
| 254 | + return bidRequest.params.bcat; |
| 255 | + } |
| 256 | + return []; |
| 257 | +} |
| 258 | + |
| 259 | +function openRtbBAdv(bidRequest) { |
| 260 | + if (utils.isArray(bidRequest.params.badv)) { |
| 261 | + return bidRequest.params.badv; |
| 262 | + } |
| 263 | + return []; |
| 264 | +} |
| 265 | + |
| 266 | +function isVideo(format) { |
| 267 | + return utils.deepAccess(format, 'mediaTypes.video') || format.mediaType == 'video'; |
| 268 | +} |
| 269 | + |
| 270 | +/* Turn bid request sizes into compatible format */ |
| 271 | +function getSizes(requestSizes) { |
| 272 | + let width = 0; |
| 273 | + let height = 0; |
| 274 | + if (utils.isArray(requestSizes) && requestSizes.length === 2 && |
| 275 | + !utils.isArray(requestSizes[0])) { |
| 276 | + width = parseInt(requestSizes[0], 10); |
| 277 | + height = parseInt(requestSizes[1], 10); |
| 278 | + } else if (typeof requestSizes === 'object') { |
| 279 | + for (let i = 0; i < requestSizes.length; i++) { |
| 280 | + let size = requestSizes[i]; |
| 281 | + width = parseInt(size[0], 10); |
| 282 | + height = parseInt(size[1], 10); |
| 283 | + break; |
| 284 | + } |
| 285 | + } |
| 286 | + return [width, height]; |
| 287 | +} |
| 288 | + |
| 289 | +registerBidder(spec); |
0 commit comments