|
1 | 1 | import * as utils from 'src/utils';
|
2 | 2 | import { registerBidder } from 'src/adapters/bidderFactory';
|
| 3 | +import { VIDEO, BANNER } from 'src/mediaTypes'; |
| 4 | +import find from 'core-js/library/fn/array/find'; |
3 | 5 |
|
4 |
| -export const ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; |
| 6 | +const ADAPTER_VERSION = '1.0'; |
| 7 | +const ADAPTER_NAME = 'BFIO_PREBID'; |
| 8 | + |
| 9 | +export const VIDEO_ENDPOINT = '//reachms.bfmio.com/bid.json?exchange_id='; |
| 10 | +export const BANNER_ENDPOINT = '//display.bfmio.com/prebid_display'; |
5 | 11 |
|
6 | 12 | export const spec = {
|
7 | 13 | code: 'beachfront',
|
8 |
| - supportedMediaTypes: ['video'], |
| 14 | + supportedMediaTypes: [ VIDEO, BANNER ], |
9 | 15 |
|
10 | 16 | isBidRequestValid(bid) {
|
11 | 17 | return !!(bid && bid.params && bid.params.appId && bid.params.bidfloor);
|
12 | 18 | },
|
13 | 19 |
|
14 | 20 | buildRequests(bids) {
|
15 |
| - return bids.map(bid => { |
16 |
| - return { |
| 21 | + let requests = []; |
| 22 | + let videoBids = bids.filter(bid => isVideoBid(bid)); |
| 23 | + let bannerBids = bids.filter(bid => !isVideoBid(bid)); |
| 24 | + videoBids.forEach(bid => { |
| 25 | + requests.push({ |
17 | 26 | method: 'POST',
|
18 |
| - url: ENDPOINT + bid.params.appId, |
19 |
| - data: createRequestParams(bid), |
| 27 | + url: VIDEO_ENDPOINT + bid.params.appId, |
| 28 | + data: createVideoRequestData(bid), |
20 | 29 | bidRequest: bid
|
21 |
| - }; |
| 30 | + }); |
22 | 31 | });
|
| 32 | + if (bannerBids.length) { |
| 33 | + requests.push({ |
| 34 | + method: 'POST', |
| 35 | + url: BANNER_ENDPOINT, |
| 36 | + data: createBannerRequestData(bannerBids), |
| 37 | + bidRequest: bannerBids |
| 38 | + }); |
| 39 | + } |
| 40 | + return requests; |
23 | 41 | },
|
24 | 42 |
|
25 | 43 | interpretResponse(response, { bidRequest }) {
|
26 | 44 | response = response.body;
|
27 |
| - if (!response || !response.url || !response.bidPrice) { |
28 |
| - utils.logWarn(`No valid bids from ${spec.code} bidder`); |
29 |
| - return []; |
| 45 | + |
| 46 | + if (isVideoBid(bidRequest)) { |
| 47 | + if (!response || !response.url || !response.bidPrice) { |
| 48 | + utils.logWarn(`No valid video bids from ${spec.code} bidder`); |
| 49 | + return []; |
| 50 | + } |
| 51 | + let size = getFirstSize(bidRequest); |
| 52 | + return { |
| 53 | + requestId: bidRequest.bidId, |
| 54 | + bidderCode: spec.code, |
| 55 | + vastUrl: response.url, |
| 56 | + cpm: response.bidPrice, |
| 57 | + width: size.w, |
| 58 | + height: size.h, |
| 59 | + creativeId: response.cmpId, |
| 60 | + mediaType: VIDEO, |
| 61 | + currency: 'USD', |
| 62 | + netRevenue: true, |
| 63 | + ttl: 300 |
| 64 | + }; |
| 65 | + } else { |
| 66 | + if (!response || !response.length) { |
| 67 | + utils.logWarn(`No valid banner bids from ${spec.code} bidder`); |
| 68 | + return []; |
| 69 | + } |
| 70 | + return response.map((bid) => { |
| 71 | + let request = find(bidRequest, req => req.adUnitCode === bid.slot); |
| 72 | + return { |
| 73 | + requestId: request.bidId, |
| 74 | + bidderCode: spec.code, |
| 75 | + ad: bid.adm, |
| 76 | + creativeId: bid.crid, |
| 77 | + cpm: bid.price, |
| 78 | + width: bid.w, |
| 79 | + height: bid.h, |
| 80 | + mediaType: BANNER, |
| 81 | + currency: 'USD', |
| 82 | + netRevenue: true, |
| 83 | + ttl: 300 |
| 84 | + }; |
| 85 | + }); |
30 | 86 | }
|
31 |
| - let size = getSize(bidRequest.sizes); |
32 |
| - return { |
33 |
| - requestId: bidRequest.bidId, |
34 |
| - bidderCode: spec.code, |
35 |
| - cpm: response.bidPrice, |
36 |
| - creativeId: response.cmpId, |
37 |
| - vastUrl: response.url, |
38 |
| - width: size.width, |
39 |
| - height: size.height, |
40 |
| - mediaType: 'video', |
41 |
| - currency: 'USD', |
42 |
| - ttl: 300, |
43 |
| - netRevenue: true |
44 |
| - }; |
45 | 87 | }
|
46 | 88 | };
|
47 | 89 |
|
48 |
| -function getSize(sizes) { |
49 |
| - let parsedSizes = utils.parseSizesInput(sizes); |
50 |
| - let [ width, height ] = parsedSizes.length ? parsedSizes[0].split('x') : []; |
51 |
| - return { |
52 |
| - width: parseInt(width, 10) || undefined, |
53 |
| - height: parseInt(height, 10) || undefined |
54 |
| - }; |
| 90 | +function getSizes(bid) { |
| 91 | + return utils.parseSizesInput(bid.sizes).map(size => { |
| 92 | + let [ width, height ] = size.split('x'); |
| 93 | + return { |
| 94 | + w: parseInt(width, 10) || undefined, |
| 95 | + h: parseInt(height, 10) || undefined |
| 96 | + }; |
| 97 | + }); |
| 98 | +} |
| 99 | + |
| 100 | +function getFirstSize(bid) { |
| 101 | + let sizes = getSizes(bid); |
| 102 | + return sizes.length ? sizes[0] : { w: undefined, h: undefined }; |
| 103 | +} |
| 104 | + |
| 105 | +function getOsVersion() { |
| 106 | + let clientStrings = [ |
| 107 | + { s: 'Android', r: /Android/ }, |
| 108 | + { s: 'iOS', r: /(iPhone|iPad|iPod)/ }, |
| 109 | + { s: 'Mac OS X', r: /Mac OS X/ }, |
| 110 | + { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ }, |
| 111 | + { s: 'Linux', r: /(Linux|X11)/ }, |
| 112 | + { s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ }, |
| 113 | + { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ }, |
| 114 | + { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ }, |
| 115 | + { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ }, |
| 116 | + { s: 'Windows Vista', r: /Windows NT 6.0/ }, |
| 117 | + { s: 'Windows Server 2003', r: /Windows NT 5.2/ }, |
| 118 | + { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ }, |
| 119 | + { s: 'UNIX', r: /UNIX/ }, |
| 120 | + { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ } |
| 121 | + ]; |
| 122 | + let cs = find(clientStrings, cs => cs.r.test(navigator.userAgent)); |
| 123 | + return cs ? cs.s : 'unknown'; |
55 | 124 | }
|
56 | 125 |
|
57 | 126 | function isMobile() {
|
58 |
| - return (/(ios|ipod|ipad|iphone|android)/i).test(global.navigator.userAgent); |
| 127 | + return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent); |
59 | 128 | }
|
60 | 129 |
|
61 | 130 | function isConnectedTV() {
|
62 |
| - return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(global.navigator.userAgent); |
| 131 | + return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent); |
| 132 | +} |
| 133 | + |
| 134 | +function getDoNotTrack() { |
| 135 | + return navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNoTrack === '1' || navigator.doNotTrack === 'yes'; |
| 136 | +} |
| 137 | + |
| 138 | +function isVideoBid(bid) { |
| 139 | + return bid.mediaTypes && bid.mediaTypes.video; |
63 | 140 | }
|
64 | 141 |
|
65 |
| -function createRequestParams(bid) { |
66 |
| - let size = getSize(bid.sizes); |
| 142 | +function createVideoRequestData(bid) { |
| 143 | + let size = getFirstSize(bid); |
| 144 | + let topLocation = utils.getTopWindowLocation(); |
67 | 145 | return {
|
68 | 146 | isPrebid: true,
|
69 | 147 | appId: bid.params.appId,
|
70 | 148 | domain: document.location.hostname,
|
| 149 | + id: utils.getUniqueIdentifierStr(), |
71 | 150 | imp: [{
|
72 | 151 | video: {
|
73 |
| - w: size.width, |
74 |
| - h: size.height |
| 152 | + w: size.w, |
| 153 | + h: size.h |
75 | 154 | },
|
76 | 155 | bidfloor: bid.params.bidfloor
|
77 | 156 | }],
|
78 | 157 | site: {
|
79 |
| - page: utils.getTopWindowLocation().host |
| 158 | + page: topLocation.host |
80 | 159 | },
|
81 | 160 | device: {
|
82 |
| - ua: global.navigator.userAgent, |
83 |
| - devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2 |
| 161 | + ua: navigator.userAgent, |
| 162 | + devicetype: isMobile() ? 1 : isConnectedTV() ? 3 : 2, |
| 163 | + geo: {} |
84 | 164 | },
|
85 | 165 | cur: ['USD']
|
86 | 166 | };
|
87 | 167 | }
|
88 | 168 |
|
| 169 | +function createBannerRequestData(bids) { |
| 170 | + let topLocation = utils.getTopWindowLocation(); |
| 171 | + let referrer = utils.getTopWindowReferrer(); |
| 172 | + let slots = bids.map(bid => { |
| 173 | + return { |
| 174 | + slot: bid.adUnitCode, |
| 175 | + id: bid.params.appId, |
| 176 | + bidfloor: bid.params.bidfloor, |
| 177 | + sizes: getSizes(bid) |
| 178 | + }; |
| 179 | + }); |
| 180 | + return { |
| 181 | + slots: slots, |
| 182 | + page: topLocation.href, |
| 183 | + domain: topLocation.hostname, |
| 184 | + search: topLocation.search, |
| 185 | + secure: topLocation.protocol === 'https:' ? 1 : 0, |
| 186 | + referrer: referrer, |
| 187 | + ua: navigator.userAgent, |
| 188 | + deviceOs: getOsVersion(), |
| 189 | + isMobile: isMobile() ? 1 : 0, |
| 190 | + dnt: getDoNotTrack() ? 1 : 0, |
| 191 | + adapterVersion: ADAPTER_VERSION, |
| 192 | + adapterName: ADAPTER_NAME |
| 193 | + }; |
| 194 | +} |
| 195 | + |
89 | 196 | registerBidder(spec);
|
0 commit comments