Skip to content

Commit 07962d6

Browse files
QuentinGallardQuentinGallard
and
QuentinGallard
authored
SmileWanted - Add Video Instream, Video Outstream and Native support (prebid#10996)
Co-authored-by: QuentinGallard <[email protected]>
1 parent 17f3468 commit 07962d6

File tree

2 files changed

+272
-30
lines changed

2 files changed

+272
-30
lines changed

modules/smilewantedBidAdapter.js

+88-28
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
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';
610

711
/**
812
* @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest
@@ -12,29 +16,50 @@ import { BANNER, VIDEO } from '../src/mediaTypes.js';
1216
const GVL_ID = 639;
1317

1418
export const spec = {
15-
code: 'smilewanted',
16-
aliases: ['smile', 'sw'],
19+
code: BIDDER_CODE,
1720
gvlid: GVL_ID,
18-
supportedMediaTypes: [BANNER, VIDEO],
21+
aliases: ['smile', 'sw'],
22+
supportedMediaTypes: [BANNER, VIDEO, NATIVE],
1923
/**
2024
* Determines whether or not the given bid request is valid.
2125
*
22-
* @param {object} bid The bid to validate.
26+
* @param {BidRequest} bid The bid to validate.
2327
* @return boolean True if this is a valid bid, and false otherwise.
2428
*/
2529
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;
2749
},
2850

2951
/**
3052
* Make a server request from the list of BidRequests.
3153
*
3254
* @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.
3356
* @return ServerRequest Info describing the request to the server.
3457
*/
3558
buildRequests: function(validBidRequests, bidderRequest) {
59+
validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests);
60+
3661
return validBidRequests.map(bid => {
37-
var payload = {
62+
const payload = {
3863
zoneId: bid.params.zoneId,
3964
currencyCode: config.getConfig('currency.adServerCurrency') || 'EUR',
4065
tagId: bid.adUnitCode,
@@ -65,20 +90,41 @@ export const spec = {
6590
payload.bidfloor = bid.params.bidfloor;
6691
}
6792

68-
if (bidderRequest && bidderRequest.refererInfo) {
93+
if (bidderRequest?.refererInfo) {
6994
payload.pageDomain = bidderRequest.refererInfo.page || '';
7095
}
7196

72-
if (bidderRequest && bidderRequest.gdprConsent) {
97+
if (bidderRequest?.gdprConsent) {
7398
payload.gdpr_consent = bidderRequest.gdprConsent.consentString;
7499
payload.gdpr = bidderRequest.gdprConsent.gdprApplies; // we're handling the undefined case server side
75100
}
76101

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);
79110
}
80111

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);
82128
return {
83129
method: 'POST',
84130
url: 'https://prebid.smilewanted.com',
@@ -90,18 +136,21 @@ export const spec = {
90136
/**
91137
* Unpack the response from the server into a list of bids.
92138
*
93-
* @param {*} serverResponse A successful response from the server.
139+
* @param {ServerResponse} serverResponse A successful response from the server.
140+
* @param {BidRequest} bidRequest
94141
* @return {Bid[]} An array of bids which were nested inside the server.
95142
*/
96143
interpretResponse: function(serverResponse, bidRequest) {
144+
if (!serverResponse.body) return [];
97145
const bidResponses = [];
98-
var response = serverResponse.body;
99146

100147
try {
148+
const response = serverResponse.body;
149+
const bidRequestData = JSON.parse(bidRequest.data);
101150
if (response) {
102151
const dealId = response.dealId || '';
103152
const bidResponse = {
104-
requestId: JSON.parse(bidRequest.data).bidId,
153+
requestId: bidRequestData.bidId,
105154
cpm: response.cpm,
106155
width: response.width,
107156
height: response.height,
@@ -113,38 +162,48 @@ export const spec = {
113162
ad: response.ad,
114163
};
115164

116-
if (response.formatTypeSw == 'video_instream' || response.formatTypeSw == 'video_outstream') {
165+
if (response.formatTypeSw === 'video_instream' || response.formatTypeSw === 'video_outstream') {
117166
bidResponse['mediaType'] = 'video';
118167
bidResponse['vastUrl'] = response.ad;
119168
bidResponse['ad'] = null;
169+
170+
if (response.formatTypeSw === 'video_outstream') {
171+
bidResponse['renderer'] = newRenderer(bidRequestData, response);
172+
}
120173
}
121174

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);
124180
}
125181

126182
if (dealId.length > 0) {
127183
bidResponse.dealId = dealId;
128184
}
129185

130186
bidResponse.meta = {};
131-
if (response.meta && response.meta.advertiserDomains && isArray(response.meta.advertiserDomains)) {
187+
if (response.meta?.advertiserDomains && isArray(response.meta.advertiserDomains)) {
132188
bidResponse.meta.advertiserDomains = response.meta.advertiserDomains;
133189
}
134190
bidResponses.push(bidResponse);
135191
}
136192
} catch (error) {
137193
logError('Error while parsing smilewanted response', error);
138194
}
195+
139196
return bidResponses;
140197
},
141198

142199
/**
143-
* User syncs.
200+
* Register the user sync pixels which should be dropped after the auction.
144201
*
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.
148207
*/
149208
getUserSyncs: function(syncOptions, responses, gdprConsent, uspConsent) {
150209
let params = '';
@@ -177,7 +236,8 @@ export const spec = {
177236

178237
/**
179238
* Create SmileWanted renderer
180-
* @param requestId
239+
* @param bidRequest
240+
* @param bidResponse
181241
* @returns {*}
182242
*/
183243
function newRenderer(bidRequest, bidResponse) {

0 commit comments

Comments
 (0)