1
- import { isArray , logError , logWarn , isFn , isPlainObject } from '../src/utils.js' ;
2
- import { Renderer } from '../src/Renderer.js' ;
3
- import { config } from '../src/config.js' ;
4
- import { registerBidder } from '../src/adapters/bidderFactory.js' ;
5
- import { BANNER , VIDEO } from '../src/mediaTypes.js' ;
1
+ import { deepAccess , deepClone , isArray , isFn , isPlainObject , logError , logWarn } from '../src/utils.js' ;
2
+ import { Renderer } from '../src/Renderer.js' ;
3
+ import { config } from '../src/config.js' ;
4
+ import { registerBidder } from '../src/adapters/bidderFactory.js' ;
5
+ import { BANNER , NATIVE , VIDEO } from '../src/mediaTypes.js' ;
6
+ import { INSTREAM , OUTSTREAM } from '../src/video.js' ;
7
+ import { convertOrtbRequestToProprietaryNative , toOrtbNativeRequest , toLegacyResponse } from '../src/native.js' ;
8
+
9
+ const BIDDER_CODE = 'smilewanted' ;
6
10
7
11
/**
8
12
* @typedef {import('../src/adapters/bidderFactory.js').BidRequest } BidRequest
@@ -12,29 +16,50 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js';
12
16
const GVL_ID = 639 ;
13
17
14
18
export const spec = {
15
- code : 'smilewanted' ,
16
- aliases : [ 'smile' , 'sw' ] ,
19
+ code : BIDDER_CODE ,
17
20
gvlid : GVL_ID ,
18
- supportedMediaTypes : [ BANNER , VIDEO ] ,
21
+ aliases : [ 'smile' , 'sw' ] ,
22
+ supportedMediaTypes : [ BANNER , VIDEO , NATIVE ] ,
19
23
/**
20
24
* Determines whether or not the given bid request is valid.
21
25
*
22
- * @param {object } bid The bid to validate.
26
+ * @param {BidRequest } bid The bid to validate.
23
27
* @return boolean True if this is a valid bid, and false otherwise.
24
28
*/
25
29
isBidRequestValid : function ( bid ) {
26
- return ! ! ( bid . params && bid . params . zoneId ) ;
30
+ if ( ! bid . params || ! bid . params . zoneId ) {
31
+ return false ;
32
+ }
33
+
34
+ if ( deepAccess ( bid , 'mediaTypes.video' ) ) {
35
+ const videoMediaTypesParams = deepAccess ( bid , 'mediaTypes.video' , { } ) ;
36
+ const videoBidderParams = deepAccess ( bid , 'params.video' , { } ) ;
37
+
38
+ const videoParams = {
39
+ ...videoMediaTypesParams ,
40
+ ...videoBidderParams
41
+ } ;
42
+
43
+ if ( ! videoParams . context || ! [ INSTREAM , OUTSTREAM ] . includes ( videoParams . context ) ) {
44
+ return false ;
45
+ }
46
+ }
47
+
48
+ return true ;
27
49
} ,
28
50
29
51
/**
30
52
* Make a server request from the list of BidRequests.
31
53
*
32
54
* @param {BidRequest[] } validBidRequests A non-empty list of valid bid requests that should be sent to the Server.
55
+ * @param {BidderRequest } bidderRequest bidder request object.
33
56
* @return ServerRequest Info describing the request to the server.
34
57
*/
35
58
buildRequests : function ( validBidRequests , bidderRequest ) {
59
+ validBidRequests = convertOrtbRequestToProprietaryNative ( validBidRequests ) ;
60
+
36
61
return validBidRequests . map ( bid => {
37
- var payload = {
62
+ const payload = {
38
63
zoneId : bid . params . zoneId ,
39
64
currencyCode : config . getConfig ( 'currency.adServerCurrency' ) || 'EUR' ,
40
65
tagId : bid . adUnitCode ,
@@ -65,20 +90,41 @@ export const spec = {
65
90
payload . bidfloor = bid . params . bidfloor ;
66
91
}
67
92
68
- if ( bidderRequest && bidderRequest . refererInfo ) {
93
+ if ( bidderRequest ? .refererInfo ) {
69
94
payload . pageDomain = bidderRequest . refererInfo . page || '' ;
70
95
}
71
96
72
- if ( bidderRequest && bidderRequest . gdprConsent ) {
97
+ if ( bidderRequest ? .gdprConsent ) {
73
98
payload . gdpr_consent = bidderRequest . gdprConsent . consentString ;
74
99
payload . gdpr = bidderRequest . gdprConsent . gdprApplies ; // we're handling the undefined case server side
75
100
}
76
101
77
- if ( bid && bid . userIdAsEids ) {
78
- payload . eids = bid . userIdAsEids ;
102
+ payload . eids = bid ?. userIdAsEids ;
103
+
104
+ const videoMediaType = deepAccess ( bid , 'mediaTypes.video' ) ;
105
+ const context = deepAccess ( bid , 'mediaTypes.video.context' ) ;
106
+
107
+ if ( bid . mediaType === 'video' || ( videoMediaType && context === INSTREAM ) || ( videoMediaType && context === OUTSTREAM ) ) {
108
+ payload . context = context ;
109
+ payload . videoParams = deepClone ( videoMediaType ) ;
79
110
}
80
111
81
- var payloadString = JSON . stringify ( payload ) ;
112
+ const nativeMediaType = deepAccess ( bid , 'mediaTypes.native' ) ;
113
+
114
+ if ( nativeMediaType ) {
115
+ payload . context = 'native' ;
116
+ payload . nativeParams = nativeMediaType ;
117
+ let sizes = deepAccess ( bid , 'mediaTypes.native.image.sizes' , [ ] ) ;
118
+
119
+ if ( sizes . length > 0 ) {
120
+ const size = Array . isArray ( sizes [ 0 ] ) ? sizes [ 0 ] : sizes ;
121
+
122
+ payload . width = size [ 0 ] || payload . width ;
123
+ payload . height = size [ 1 ] || payload . height ;
124
+ }
125
+ }
126
+
127
+ const payloadString = JSON . stringify ( payload ) ;
82
128
return {
83
129
method : 'POST' ,
84
130
url : 'https://prebid.smilewanted.com' ,
@@ -90,18 +136,21 @@ export const spec = {
90
136
/**
91
137
* Unpack the response from the server into a list of bids.
92
138
*
93
- * @param {* } serverResponse A successful response from the server.
139
+ * @param {ServerResponse } serverResponse A successful response from the server.
140
+ * @param {BidRequest } bidRequest
94
141
* @return {Bid[] } An array of bids which were nested inside the server.
95
142
*/
96
143
interpretResponse : function ( serverResponse , bidRequest ) {
144
+ if ( ! serverResponse . body ) return [ ] ;
97
145
const bidResponses = [ ] ;
98
- var response = serverResponse . body ;
99
146
100
147
try {
148
+ const response = serverResponse . body ;
149
+ const bidRequestData = JSON . parse ( bidRequest . data ) ;
101
150
if ( response ) {
102
151
const dealId = response . dealId || '' ;
103
152
const bidResponse = {
104
- requestId : JSON . parse ( bidRequest . data ) . bidId ,
153
+ requestId : bidRequestData . bidId ,
105
154
cpm : response . cpm ,
106
155
width : response . width ,
107
156
height : response . height ,
@@ -113,38 +162,48 @@ export const spec = {
113
162
ad : response . ad ,
114
163
} ;
115
164
116
- if ( response . formatTypeSw == 'video_instream' || response . formatTypeSw == 'video_outstream' ) {
165
+ if ( response . formatTypeSw === 'video_instream' || response . formatTypeSw = == 'video_outstream' ) {
117
166
bidResponse [ 'mediaType' ] = 'video' ;
118
167
bidResponse [ 'vastUrl' ] = response . ad ;
119
168
bidResponse [ 'ad' ] = null ;
169
+
170
+ if ( response . formatTypeSw === 'video_outstream' ) {
171
+ bidResponse [ 'renderer' ] = newRenderer ( bidRequestData , response ) ;
172
+ }
120
173
}
121
174
122
- if ( response . formatTypeSw == 'video_outstream' ) {
123
- bidResponse [ 'renderer' ] = newRenderer ( JSON . parse ( bidRequest . data ) , response ) ;
175
+ if ( response . formatTypeSw === 'native' ) {
176
+ const nativeAdResponse = JSON . parse ( response . ad ) ;
177
+ const ortbNativeRequest = toOrtbNativeRequest ( bidRequestData . nativeParams ) ;
178
+ bidResponse [ 'mediaType' ] = 'native' ;
179
+ bidResponse [ 'native' ] = toLegacyResponse ( nativeAdResponse , ortbNativeRequest ) ;
124
180
}
125
181
126
182
if ( dealId . length > 0 ) {
127
183
bidResponse . dealId = dealId ;
128
184
}
129
185
130
186
bidResponse . meta = { } ;
131
- if ( response . meta && response . meta . advertiserDomains && isArray ( response . meta . advertiserDomains ) ) {
187
+ if ( response . meta ? .advertiserDomains && isArray ( response . meta . advertiserDomains ) ) {
132
188
bidResponse . meta . advertiserDomains = response . meta . advertiserDomains ;
133
189
}
134
190
bidResponses . push ( bidResponse ) ;
135
191
}
136
192
} catch ( error ) {
137
193
logError ( 'Error while parsing smilewanted response' , error ) ;
138
194
}
195
+
139
196
return bidResponses ;
140
197
} ,
141
198
142
199
/**
143
- * User syncs .
200
+ * Register the user sync pixels which should be dropped after the auction .
144
201
*
145
- * @param {* } syncOptions Publisher prebid configuration.
146
- * @param {* } serverResponses A successful response from the server.
147
- * @return {Syncs[] } An array of syncs that should be executed.
202
+ * @param {SyncOptions } syncOptions Which user syncs are allowed?
203
+ * @param {ServerResponse[] } responses List of server's responses.
204
+ * @param {Object } gdprConsent The GDPR consent parameters
205
+ * @param {Object } uspConsent The USP consent parameters
206
+ * @return {UserSync[] } The user syncs which should be dropped.
148
207
*/
149
208
getUserSyncs : function ( syncOptions , responses , gdprConsent , uspConsent ) {
150
209
let params = '' ;
@@ -177,7 +236,8 @@ export const spec = {
177
236
178
237
/**
179
238
* Create SmileWanted renderer
180
- * @param requestId
239
+ * @param bidRequest
240
+ * @param bidResponse
181
241
* @returns {* }
182
242
*/
183
243
function newRenderer ( bidRequest , bidResponse ) {
0 commit comments