From aa0c2de6d308ea0142828af836e6a63c4ee75f7e Mon Sep 17 00:00:00 2001 From: smartclip AdTechnology Date: Wed, 20 May 2020 16:34:34 +0200 Subject: [PATCH 01/22] Add smartclipBidAdapter --- modules/smartclipBidAdapter.js | 394 +++++++++++++++++++++++++++++++++ modules/smartclipBidAdapter.md | 51 +++++ 2 files changed, 445 insertions(+) create mode 100644 modules/smartclipBidAdapter.js create mode 100644 modules/smartclipBidAdapter.md diff --git a/modules/smartclipBidAdapter.js b/modules/smartclipBidAdapter.js new file mode 100644 index 00000000000..03c1231f128 --- /dev/null +++ b/modules/smartclipBidAdapter.js @@ -0,0 +1,394 @@ +import * as utils from 'src/utils'; +import { Renderer } from 'src/Renderer'; +import { registerBidder } from 'src/adapters/bidderFactory'; +import { VIDEO } from 'src/mediaTypes'; + +const BIDDER_CODE = 'smartx'; +const URL = '//bid.sxp.smartclip.net/bid/1000'; + +export const spec = { + code: BIDDER_CODE, + aliases: ['smartx'], + supportedMediaTypes: [VIDEO], + + /** + * Determines whether or not the given bid request is valid. + * From Prebid.js: isBidRequestValid - Verify the the AdUnits.bids, respond with true (valid) or false (invalid). + * + * @param {object} bid The bid to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: function(bid) { + if (bid && typeof bid.params !== 'object') { + utils.logError(BIDDER_CODE + ': params is not defined or is incorrect in the bidder settings.'); + return false; + } + + if (!utils.deepAccess(bid, 'mediaTypes.video')) { + utils.logError(BIDDER_CODE + ': mediaTypes.video is not present in the bidder settings.'); + return false; + } + + const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + if (!playerSize || !utils.isArray(playerSize)) { + utils.logError(BIDDER_CODE + ': mediaTypes.video.playerSize is not defined in the bidder settings.'); + return false; + } + + if (!utils.getBidIdParameter('tagId', bid.params)) { + utils.logError(BIDDER_CODE + ': tagId is not present in bidder params'); + return false; + } + + if (!utils.getBidIdParameter('publisherId', bid.params)) { + utils.logError(BIDDER_CODE + ': publisherId is not present in bidder params'); + return false; + } + + if (!utils.getBidIdParameter('siteId', bid.params)) { + utils.logError(BIDDER_CODE + ': siteId is not present in bidder params'); + return false; + } + + /* + if (!utils.getBidIdParameter('domain', bid.params)) { + utils.logError(BIDDER_CODE + ': domain is not present in bidder params'); + return false; + } + */ + + if (utils.deepAccess(bid, 'mediaTypes.video.context') == 'outstream' || utils.deepAccess(bid, 'params.ad_unit') == 'outstream') { + if (!utils.getBidIdParameter('outstream_function', bid.params)) { + if (!utils.getBidIdParameter('outstream_options', bid.params)) { + utils.logMessage(BIDDER_CODE + ': outstream_options parameter is not defined. The default outstream renderer will be injected in the header. You can override the default SmartX outstream rendering by defining your own Outstream function using field outstream_function.'); + return true; + } + if (!utils.getBidIdParameter('slot', bid.params.outstream_options)) { + utils.logMessage(BIDDER_CODE + ': slot parameter is not defined in outstream_options object in the configuration. The default outstream renderer will be injected in the header.'); + return true; + } + } + } + + return true; + }, + + /** + * Make a server request from the list of BidRequests. + * from Prebid.js: buildRequests - Takes an array of valid bid requests, all of which are guaranteed to have passed the isBidRequestValid() test. + * + * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: function(bidRequests, bidderRequest) { + const page = bidderRequest.refererInfo.referer; + const isPageSecure = !!page.match(/^https:/) + //const domain = page.match(/:\/\/(.[^/]+)/)[1]; + + const smartxRequests = bidRequests.map(function(bid) { + const tagId = utils.getBidIdParameter('tagId', bid.params); + const publisherId = utils.getBidIdParameter('publisherId', bid.params); + const siteId = utils.getBidIdParameter('siteId', bid.params); + const domain = utils.getBidIdParameter('domain', bid.params); + const cat = utils.getBidIdParameter('cat', bid.params); + + let pubcid = null; + + const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); + const contentWidth = playerSize[0][0]; + const contentHeight = playerSize[0][1]; + + const secure = +(isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0)); + + const ext = { + sdk_name: 'Prebid 1+' + }; + + const mimes = utils.getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm']; + const linearity = utils.getBidIdParameter('linearity', bid.params) || 1; + const minduration = utils.getBidIdParameter('minduration', bid.params) || 0; + const maxduration = utils.getBidIdParameter('maxduration', bid.params) || 500; + const startdelay = utils.getBidIdParameter('startdelay', bid.params) || 0; + const minbitrate = utils.getBidIdParameter('minbitrate', bid.params) || 0; + const maxbitrate = utils.getBidIdParameter('maxbitrate', bid.params) || 3500; + const delivery = utils.getBidIdParameter('delivery', bid.params) || [2]; + const pos = utils.getBidIdParameter('pos', bid.params) || 1; + const api = utils.getBidIdParameter('api', bid.params) || [2]; + const protocols = utils.getBidIdParameter('protocols', bid.params) || [2, 3, 5, 6]; + var contextcustom = utils.deepAccess(bid, 'mediaTypes.video.context'); + var placement = 1; + if (contextcustom == 'outstream') { + placement = 3; + } + + let smartxReq = { + id: bid.bidId, + secure: secure, + video: { + w: contentWidth, + h: contentHeight, + mimes: mimes, + linearity: linearity, + minduration: minduration, + maxduration: maxduration, + startdelay: startdelay, + protocols: protocols, + minbitrate: minbitrate, + maxbitrate: maxbitrate, + delivery: delivery, + pos: pos, + placement: placement, + api: api, + ext: ext + }, + tagid: tagId, + ext: { + 'smart.bidpricetype': 1 + } + }; + + if (utils.getBidIdParameter('bidfloor', bid.params) != '') { + smartxReq.bidfloor = utils.getBidIdParameter('bidfloor', bid.params); + } + + if (utils.getBidIdParameter('bidfloorcur', bid.params) != '') { + smartxReq.bidfloorcur = utils.getBidIdParameter('bidfloorcur', bid.params); + } + + if (bid.crumbs && bid.crumbs.pubcid) { + pubcid = bid.crumbs.pubcid; + } + + const language = navigator.language ? 'language' : 'userLanguage'; + const device = { + h: screen.height, + w: screen.width, + dnt: utils.getDNT() ? 1 : 0, + language: navigator[language].split('-')[0], + make: navigator.vendor ? navigator.vendor : '', + ua: navigator.userAgent + }; + + const at = utils.getBidIdParameter('at', bid.params) || 2; + const cur = utils.getBidIdParameter('cur', bid.params) || ['EUR']; + const requestPayload = { + id: utils.generateUUID(), + imp: smartxReq, + site: { + id: siteId, + page: page, + cat: cat, + content: 'content', + domain: domain, + publisher: { + id: publisherId + } + }, + device: device, + at: at, + cur: cur + }; + + const userExt = {}; + + // Add GDPR flag and consent string + if (bidderRequest && bidderRequest.gdprConsent) { + userExt.consent = bidderRequest.gdprConsent.consentString; + + if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { + requestPayload.regs = { + ext: { + gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) + } + }; + } + } + + // Add common id if available + if (pubcid) { + userExt.fpc = pubcid; + } + + // Only add the user object if it's not empty + if (!utils.isEmpty(userExt)) { + requestPayload.user = { ext: userExt }; + } + + //CUSTOM - Emetriq Targeting + var isemq = (bid.params.user[0].data.name) || 'empty'; + if(isemq!=='empty'){ + var emqstring = (bid.params.user[0].data.segment[0].value) || 'empty'; + requestPayload.user = { + ext: userExt, + data: [{ + id: 'emq', + name:'emq', + segment: { + name : "emq", + value: emqstring, + } + }] + } + } + //CUSTOM - Emetriq Targeting + + + return { + method: 'POST', + url: URL, + data: requestPayload, + bidRequest: bidderRequest, + options: { + contentType: 'application/json', + customHeaders: { + 'x-openrtb-version': '2.3' + } + } + }; + }); + + return smartxRequests; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: function(serverResponse, bidderRequest) { + const bidResponses = []; + const serverResponseBody = serverResponse.body; + + if (serverResponseBody && utils.isArray(serverResponseBody.seatbid)) { + utils._each(serverResponseBody.seatbid, function(bids) { + utils._each(bids.bid, function(smartxBid) { + let currentBidRequest = {}; + for (let i in bidderRequest.bidRequest.bids) { + if (smartxBid.impid == bidderRequest.bidRequest.bids[i].bidId) { + currentBidRequest = bidderRequest.bidRequest.bids[i]; + } + } + + /** + * Make sure currency and price are the right ones + * TODO: what about the pre_market_bid partners sizes? + */ + utils._each(currentBidRequest.params.pre_market_bids, function(pmb) { + if (pmb.deal_id == smartxBid.id) { + smartxBid.price = pmb.price; + serverResponseBody.cur = pmb.currency; + } + }); + + const bid = { + requestId: currentBidRequest.bidId, + currency: serverResponseBody.cur || 'USD', + cpm: smartxBid.price, + creativeId: smartxBid.crid || '', + ttl: 360, + netRevenue: true, + vastContent: smartxBid.adm, + vastXml: smartxBid.adm, + mediaType: VIDEO, + width: smartxBid.w, + height: smartxBid.h + }; + + const context1 = utils.deepAccess(currentBidRequest, 'mediaTypes.video.context'); + const context2 = utils.deepAccess(currentBidRequest, 'params.ad_unit'); + if (context1 == 'outstream' || context2 == 'outstream') { + const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); + const renderer = Renderer.install({ + id: 0, + url: '//', + config: { + adText: 'SmartX Outstream Video Ad via Prebid.js', + player_width: playersize[0][0], + player_height: playersize[0][1], + content_page_url: utils.deepAccess(bidderRequest, 'data.site.page'), + ad_mute: +!!utils.deepAccess(currentBidRequest, 'params.ad_mute'), + hide_skin: +!!utils.deepAccess(currentBidRequest, 'params.hide_skin'), + outstream_options: utils.deepAccess(currentBidRequest, 'params.outstream_options'), + outstream_function: utils.deepAccess(currentBidRequest, 'params.outstream_function') + } + }); + + try { + renderer.setRender(outstreamRender); + renderer.setEventHandlers({ + impression: function impression() { + return utils.logMessage('SmartX outstream video impression event'); + }, + loaded: function loaded() { + return utils.logMessage('SmartX outstream video loaded event'); + }, + ended: function ended() { + utils.logMessage('SmartX outstream renderer video event'); + } + }); + } catch (err) { + utils.logWarn('Prebid Error calling setRender or setEve,tHandlers on renderer', err); + } + bid.renderer = renderer; + } + + bidResponses.push(bid); + }) + }); + } + + return bidResponses; + } +} + +function createOutstreamScript(bid) { + // const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); + utils.logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); + + const elementId = bid.adUnitCode; + let smartPlayObj = { + minAdWidth: 290, + maxAdWidth: 900, + elementLocator: { allowInViewport: false, minimumElementWidth: 290, scanPixelsBelowViewport: 800 }, + onStartCallback: function(m, n) { try { sc_smartIntxtStart(n); } catch (f) {} }, + onCappedCallback: function(m, n) { try { sc_smartIntxtNoad(n); } catch (f) {} }, + onEndCallback: function(m, n) { try { sc_smartIntxtEnd(n); } catch (f) {} }, + debug: true + }; + + smartPlayObj.adResponse = bid.vastContent; + const script = window.document.createElement('script'); + script.type = 'text/javascript'; + script.async = 'true'; + script.src = '//dco.smartclip.net/?plc=7777777'; + script.onload = script.onreadystatechange = function() { + var rs = this.readyState; + if (rs && rs != 'complete' && rs != 'loaded') return; + try { + SmartPlay(elementId, smartPlayObj); + } catch (e) { console.warn('error caught : ' + e); } + }; + + return script; +} + +function outstreamRender(bid) { + const script = createOutstreamScript(bid); + if (bid.renderer.config.outstream_function != null && typeof bid.renderer.config.outstream_function === 'function') { + bid.renderer.config.outstream_function(bid, script); + } else { + try { + const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); + if (slot && window.document.getElementById(slot)) { + window.document.getElementById(slot).appendChild(script); + } else { + window.document.getElementsByTagName('head')[0].appendChild(script); + } + } catch (err) { + utils.logError('[SMARTX][renderer] Error:' + err.message) + } + } +} + +registerBidder(spec); diff --git a/modules/smartclipBidAdapter.md b/modules/smartclipBidAdapter.md new file mode 100644 index 00000000000..42ae736650b --- /dev/null +++ b/modules/smartclipBidAdapter.md @@ -0,0 +1,51 @@ +Overview +Module Name: smartclip Bidder Adapter +Module Type: Bidder Adapter +Maintainer: adtech@smartclip.tv +Description +Connect to smartclip for bids. + +This adapter requires setup and approval from the smartclip team. + +Test Parameters - Use case #1 - outstream with default rendering options + +var adUnits = [{ + code: 'video1', + mediaTypes: { + banner: { + sizes: sizes + }, + video: { + context: 'outstream', + playerSize: [640, 480] + } + }, + bids: [{ + bidder: 'smartclip', + params: { + tagId: 'Nu68JuOWAvrbzoyrOR9a7A', + publisherId: 'pubid', + siteId: 'siteId', + cat: "category", + bidfloor: 0.3, + bidfloorcur: "EUR", + at: 2, + cur: ["EUR"], + outstream_options: { + slot: 'video1' + }, + user: [{ + data: { + id: 'emq', + name: 'emq', + segment: [{ + id: 'emq', + name:'emq', + value: 'e0:k14' + }] + } + }] + //outstream_function: myOutstreamFunction + } + }], + }]; \ No newline at end of file From a4daadc9450a813fc58d37ab129a09a628d5d9f0 Mon Sep 17 00:00:00 2001 From: Gino Date: Wed, 2 Sep 2020 12:57:48 +0200 Subject: [PATCH 02/22] smartxBidAdapter.js - removed unused variables, removed debug, added window before the outstream related functions --- modules/smartxBidAdapter.js | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index a745c54e39c..4409e4e9dfb 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -331,13 +331,6 @@ function createOutstreamScript(bid) { // const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); utils.logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); const elementId = bid.adUnitCode; - // eslint-disable-next-line camelcase - var sc_smartIntxtStart; - // eslint-disable-next-line camelcase - var sc_smartIntxtNoad; - // eslint-disable-next-line camelcase - var sc_smartIntxtEnd; - var SmartPlay; let smartPlayObj = { minAdWidth: 290, maxAdWidth: 900, @@ -348,20 +341,19 @@ function createOutstreamScript(bid) { }, onStartCallback: function (m, n) { try { - sc_smartIntxtStart(n); + window.sc_smartIntxtStart(n); } catch (f) {} }, onCappedCallback: function (m, n) { try { - sc_smartIntxtNoad(n); + window.sc_smartIntxtNoad(n); } catch (f) {} }, onEndCallback: function (m, n) { try { - sc_smartIntxtEnd(n); + window.sc_smartIntxtEnd(n); } catch (f) {} }, - debug: true }; smartPlayObj.adResponse = bid.vastContent; const script = window.document.createElement('script'); @@ -372,7 +364,7 @@ function createOutstreamScript(bid) { var rs = this.readyState; if (rs && rs != 'complete' && rs != 'loaded') return; try { - SmartPlay(elementId, smartPlayObj); + window.SmartPlay(elementId, smartPlayObj); } catch (e) { utils.logError('error caught : ' + e); } From 2a965c9a5e31535d4150344d00207d8e8956a063 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Fri, 29 Jan 2021 11:46:27 +0100 Subject: [PATCH 03/22] - made outstream player configurable --- modules/smartxBidAdapter.js | 50 +++++++++++++++++++++++++++++++------ modules/smartxBidAdapter.md | 34 +++++++++++++++++-------- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 4409e4e9dfb..b2381c41d8e 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -328,16 +328,49 @@ export const spec = { } function createOutstreamScript(bid) { - // const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); + // for SmartPlay 4.12 + function sc_prebidClose(ele, completeCollapsed) { + if (completeCollapsed) { + document.getElementById(ele.id).style.display = 'none'; + } + } + + const confMinAdWidth = bid.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; + const confMaxAdWidth = bid.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; + const confStartOpen = bid.getBidIdParameter('startOpen', bid.renderer.config.outstream_options) || 'false'; + const confEndingScreen = bid.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options) || 'true'; + const confHeaderText = bid.getBidIdParameter('headerText', bid.renderer.config.outstream_options) || ''; + const confSkipOffset = bid.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options) || 0; + const confDesiredBitrate = bid.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options) || 1600; + const elementId = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; + + // for SmartPlay 4.12 + let initCollapsed = true; + let completeCollapsed = true; + if (confStartOpen === 'true') { + initCollapsed = false; + } + if (confEndingScreen === 'true') { + completeCollapsed = false; + } + utils.logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); - const elementId = bid.adUnitCode; + let smartPlayObj = { - minAdWidth: 290, - maxAdWidth: 900, - elementLocator: { - allowInViewport: false, - minimumElementWidth: 290, - scanPixelsBelowViewport: 800 + minAdWidth: confMinAdWidth, + maxAdWidth: confMaxAdWidth, + headerText: confHeaderText, + skipOffset: confSkipOffset, + behaviourMatrix: { + init: { + 'collapsed': initCollapsed + }, + complete: { + 'collapsed': completeCollapsed + } + }, + environmentVars: { + desiredBitrate: confDesiredBitrate, }, onStartCallback: function (m, n) { try { @@ -351,6 +384,7 @@ function createOutstreamScript(bid) { }, onEndCallback: function (m, n) { try { + sc_prebidClose(n, completeCollapsed); // for SmartPlay 4.12 window.sc_smartIntxtEnd(n); } catch (f) {} }, diff --git a/modules/smartxBidAdapter.md b/modules/smartxBidAdapter.md index a53af839e2b..082a36f3dde 100644 --- a/modules/smartxBidAdapter.md +++ b/modules/smartxBidAdapter.md @@ -29,11 +29,18 @@ This adapter requires setup and approval from the smartclip team. publisherId: '11986', siteId: '22860', bidfloor: 0.3, - bidfloorcur: "EUR", + bidfloorcur: 'EUR', at: 2, - cur: ["EUR"], + cur: ['EUR'], outstream_options: { - slot: 'video1' + slot: 'video1', + minAdWidth: 290, + maxAdWidth: 900, + headerText: '', + skipOffset: 0, + startOpen: 'true', + endingScreen: 'true', + desiredBitrate: 1600, }, } }], @@ -57,11 +64,18 @@ This adapter requires setup and approval from the smartclip team. publisherId: '11986', siteId: '22860', bidfloor: 0.3, - bidfloorcur: "EUR", + bidfloorcur: 'EUR', at: 2, - cur: ["EUR"], + cur: ['EUR'], outstream_options: { - slot: 'video1' + slot: 'video1', + minAdWidth: 290, + maxAdWidth: 900, + headerText: '', + skipOffset: 0, + startOpen: 'true', + endingScreen: 'true', + desiredBitrate: 1600, }, user: { data: [{ @@ -104,9 +118,9 @@ This adapter requires setup and approval from the smartclip team. publisherId: '11986', siteId: '22860', bidfloor: 0.3, - bidfloorcur: "EUR", + bidfloorcur: 'EUR', at: 2, - cur: ["EUR"] + cur: ['EUR'] } }], }]; @@ -129,9 +143,9 @@ This adapter requires setup and approval from the smartclip team. publisherId: '11986', siteId: '22860', bidfloor: 0.3, - bidfloorcur: "EUR", + bidfloorcur: 'EUR', at: 2, - cur: ["EUR"], + cur: ['EUR'], user: { data: [{ id: 'emq', From b577bd3f602cb4a9fa68af0b23a5f59e1b72b4d4 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Fri, 29 Jan 2021 12:11:19 +0100 Subject: [PATCH 04/22] remove wrong named files --- modules/smartclipBidAdapter.js | 394 --------------------------------- modules/smartclipBidAdapter.md | 51 ----- 2 files changed, 445 deletions(-) delete mode 100644 modules/smartclipBidAdapter.js delete mode 100644 modules/smartclipBidAdapter.md diff --git a/modules/smartclipBidAdapter.js b/modules/smartclipBidAdapter.js deleted file mode 100644 index 03c1231f128..00000000000 --- a/modules/smartclipBidAdapter.js +++ /dev/null @@ -1,394 +0,0 @@ -import * as utils from 'src/utils'; -import { Renderer } from 'src/Renderer'; -import { registerBidder } from 'src/adapters/bidderFactory'; -import { VIDEO } from 'src/mediaTypes'; - -const BIDDER_CODE = 'smartx'; -const URL = '//bid.sxp.smartclip.net/bid/1000'; - -export const spec = { - code: BIDDER_CODE, - aliases: ['smartx'], - supportedMediaTypes: [VIDEO], - - /** - * Determines whether or not the given bid request is valid. - * From Prebid.js: isBidRequestValid - Verify the the AdUnits.bids, respond with true (valid) or false (invalid). - * - * @param {object} bid The bid to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function(bid) { - if (bid && typeof bid.params !== 'object') { - utils.logError(BIDDER_CODE + ': params is not defined or is incorrect in the bidder settings.'); - return false; - } - - if (!utils.deepAccess(bid, 'mediaTypes.video')) { - utils.logError(BIDDER_CODE + ': mediaTypes.video is not present in the bidder settings.'); - return false; - } - - const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); - if (!playerSize || !utils.isArray(playerSize)) { - utils.logError(BIDDER_CODE + ': mediaTypes.video.playerSize is not defined in the bidder settings.'); - return false; - } - - if (!utils.getBidIdParameter('tagId', bid.params)) { - utils.logError(BIDDER_CODE + ': tagId is not present in bidder params'); - return false; - } - - if (!utils.getBidIdParameter('publisherId', bid.params)) { - utils.logError(BIDDER_CODE + ': publisherId is not present in bidder params'); - return false; - } - - if (!utils.getBidIdParameter('siteId', bid.params)) { - utils.logError(BIDDER_CODE + ': siteId is not present in bidder params'); - return false; - } - - /* - if (!utils.getBidIdParameter('domain', bid.params)) { - utils.logError(BIDDER_CODE + ': domain is not present in bidder params'); - return false; - } - */ - - if (utils.deepAccess(bid, 'mediaTypes.video.context') == 'outstream' || utils.deepAccess(bid, 'params.ad_unit') == 'outstream') { - if (!utils.getBidIdParameter('outstream_function', bid.params)) { - if (!utils.getBidIdParameter('outstream_options', bid.params)) { - utils.logMessage(BIDDER_CODE + ': outstream_options parameter is not defined. The default outstream renderer will be injected in the header. You can override the default SmartX outstream rendering by defining your own Outstream function using field outstream_function.'); - return true; - } - if (!utils.getBidIdParameter('slot', bid.params.outstream_options)) { - utils.logMessage(BIDDER_CODE + ': slot parameter is not defined in outstream_options object in the configuration. The default outstream renderer will be injected in the header.'); - return true; - } - } - } - - return true; - }, - - /** - * Make a server request from the list of BidRequests. - * from Prebid.js: buildRequests - Takes an array of valid bid requests, all of which are guaranteed to have passed the isBidRequestValid() test. - * - * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. - * @return ServerRequest Info describing the request to the server. - */ - buildRequests: function(bidRequests, bidderRequest) { - const page = bidderRequest.refererInfo.referer; - const isPageSecure = !!page.match(/^https:/) - //const domain = page.match(/:\/\/(.[^/]+)/)[1]; - - const smartxRequests = bidRequests.map(function(bid) { - const tagId = utils.getBidIdParameter('tagId', bid.params); - const publisherId = utils.getBidIdParameter('publisherId', bid.params); - const siteId = utils.getBidIdParameter('siteId', bid.params); - const domain = utils.getBidIdParameter('domain', bid.params); - const cat = utils.getBidIdParameter('cat', bid.params); - - let pubcid = null; - - const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); - const contentWidth = playerSize[0][0]; - const contentHeight = playerSize[0][1]; - - const secure = +(isPageSecure || (utils.getBidIdParameter('secure', bid.params) ? 1 : 0)); - - const ext = { - sdk_name: 'Prebid 1+' - }; - - const mimes = utils.getBidIdParameter('mimes', bid.params) || ['application/javascript', 'video/mp4', 'video/webm']; - const linearity = utils.getBidIdParameter('linearity', bid.params) || 1; - const minduration = utils.getBidIdParameter('minduration', bid.params) || 0; - const maxduration = utils.getBidIdParameter('maxduration', bid.params) || 500; - const startdelay = utils.getBidIdParameter('startdelay', bid.params) || 0; - const minbitrate = utils.getBidIdParameter('minbitrate', bid.params) || 0; - const maxbitrate = utils.getBidIdParameter('maxbitrate', bid.params) || 3500; - const delivery = utils.getBidIdParameter('delivery', bid.params) || [2]; - const pos = utils.getBidIdParameter('pos', bid.params) || 1; - const api = utils.getBidIdParameter('api', bid.params) || [2]; - const protocols = utils.getBidIdParameter('protocols', bid.params) || [2, 3, 5, 6]; - var contextcustom = utils.deepAccess(bid, 'mediaTypes.video.context'); - var placement = 1; - if (contextcustom == 'outstream') { - placement = 3; - } - - let smartxReq = { - id: bid.bidId, - secure: secure, - video: { - w: contentWidth, - h: contentHeight, - mimes: mimes, - linearity: linearity, - minduration: minduration, - maxduration: maxduration, - startdelay: startdelay, - protocols: protocols, - minbitrate: minbitrate, - maxbitrate: maxbitrate, - delivery: delivery, - pos: pos, - placement: placement, - api: api, - ext: ext - }, - tagid: tagId, - ext: { - 'smart.bidpricetype': 1 - } - }; - - if (utils.getBidIdParameter('bidfloor', bid.params) != '') { - smartxReq.bidfloor = utils.getBidIdParameter('bidfloor', bid.params); - } - - if (utils.getBidIdParameter('bidfloorcur', bid.params) != '') { - smartxReq.bidfloorcur = utils.getBidIdParameter('bidfloorcur', bid.params); - } - - if (bid.crumbs && bid.crumbs.pubcid) { - pubcid = bid.crumbs.pubcid; - } - - const language = navigator.language ? 'language' : 'userLanguage'; - const device = { - h: screen.height, - w: screen.width, - dnt: utils.getDNT() ? 1 : 0, - language: navigator[language].split('-')[0], - make: navigator.vendor ? navigator.vendor : '', - ua: navigator.userAgent - }; - - const at = utils.getBidIdParameter('at', bid.params) || 2; - const cur = utils.getBidIdParameter('cur', bid.params) || ['EUR']; - const requestPayload = { - id: utils.generateUUID(), - imp: smartxReq, - site: { - id: siteId, - page: page, - cat: cat, - content: 'content', - domain: domain, - publisher: { - id: publisherId - } - }, - device: device, - at: at, - cur: cur - }; - - const userExt = {}; - - // Add GDPR flag and consent string - if (bidderRequest && bidderRequest.gdprConsent) { - userExt.consent = bidderRequest.gdprConsent.consentString; - - if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { - requestPayload.regs = { - ext: { - gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) - } - }; - } - } - - // Add common id if available - if (pubcid) { - userExt.fpc = pubcid; - } - - // Only add the user object if it's not empty - if (!utils.isEmpty(userExt)) { - requestPayload.user = { ext: userExt }; - } - - //CUSTOM - Emetriq Targeting - var isemq = (bid.params.user[0].data.name) || 'empty'; - if(isemq!=='empty'){ - var emqstring = (bid.params.user[0].data.segment[0].value) || 'empty'; - requestPayload.user = { - ext: userExt, - data: [{ - id: 'emq', - name:'emq', - segment: { - name : "emq", - value: emqstring, - } - }] - } - } - //CUSTOM - Emetriq Targeting - - - return { - method: 'POST', - url: URL, - data: requestPayload, - bidRequest: bidderRequest, - options: { - contentType: 'application/json', - customHeaders: { - 'x-openrtb-version': '2.3' - } - } - }; - }); - - return smartxRequests; - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {*} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function(serverResponse, bidderRequest) { - const bidResponses = []; - const serverResponseBody = serverResponse.body; - - if (serverResponseBody && utils.isArray(serverResponseBody.seatbid)) { - utils._each(serverResponseBody.seatbid, function(bids) { - utils._each(bids.bid, function(smartxBid) { - let currentBidRequest = {}; - for (let i in bidderRequest.bidRequest.bids) { - if (smartxBid.impid == bidderRequest.bidRequest.bids[i].bidId) { - currentBidRequest = bidderRequest.bidRequest.bids[i]; - } - } - - /** - * Make sure currency and price are the right ones - * TODO: what about the pre_market_bid partners sizes? - */ - utils._each(currentBidRequest.params.pre_market_bids, function(pmb) { - if (pmb.deal_id == smartxBid.id) { - smartxBid.price = pmb.price; - serverResponseBody.cur = pmb.currency; - } - }); - - const bid = { - requestId: currentBidRequest.bidId, - currency: serverResponseBody.cur || 'USD', - cpm: smartxBid.price, - creativeId: smartxBid.crid || '', - ttl: 360, - netRevenue: true, - vastContent: smartxBid.adm, - vastXml: smartxBid.adm, - mediaType: VIDEO, - width: smartxBid.w, - height: smartxBid.h - }; - - const context1 = utils.deepAccess(currentBidRequest, 'mediaTypes.video.context'); - const context2 = utils.deepAccess(currentBidRequest, 'params.ad_unit'); - if (context1 == 'outstream' || context2 == 'outstream') { - const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); - const renderer = Renderer.install({ - id: 0, - url: '//', - config: { - adText: 'SmartX Outstream Video Ad via Prebid.js', - player_width: playersize[0][0], - player_height: playersize[0][1], - content_page_url: utils.deepAccess(bidderRequest, 'data.site.page'), - ad_mute: +!!utils.deepAccess(currentBidRequest, 'params.ad_mute'), - hide_skin: +!!utils.deepAccess(currentBidRequest, 'params.hide_skin'), - outstream_options: utils.deepAccess(currentBidRequest, 'params.outstream_options'), - outstream_function: utils.deepAccess(currentBidRequest, 'params.outstream_function') - } - }); - - try { - renderer.setRender(outstreamRender); - renderer.setEventHandlers({ - impression: function impression() { - return utils.logMessage('SmartX outstream video impression event'); - }, - loaded: function loaded() { - return utils.logMessage('SmartX outstream video loaded event'); - }, - ended: function ended() { - utils.logMessage('SmartX outstream renderer video event'); - } - }); - } catch (err) { - utils.logWarn('Prebid Error calling setRender or setEve,tHandlers on renderer', err); - } - bid.renderer = renderer; - } - - bidResponses.push(bid); - }) - }); - } - - return bidResponses; - } -} - -function createOutstreamScript(bid) { - // const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); - utils.logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); - - const elementId = bid.adUnitCode; - let smartPlayObj = { - minAdWidth: 290, - maxAdWidth: 900, - elementLocator: { allowInViewport: false, minimumElementWidth: 290, scanPixelsBelowViewport: 800 }, - onStartCallback: function(m, n) { try { sc_smartIntxtStart(n); } catch (f) {} }, - onCappedCallback: function(m, n) { try { sc_smartIntxtNoad(n); } catch (f) {} }, - onEndCallback: function(m, n) { try { sc_smartIntxtEnd(n); } catch (f) {} }, - debug: true - }; - - smartPlayObj.adResponse = bid.vastContent; - const script = window.document.createElement('script'); - script.type = 'text/javascript'; - script.async = 'true'; - script.src = '//dco.smartclip.net/?plc=7777777'; - script.onload = script.onreadystatechange = function() { - var rs = this.readyState; - if (rs && rs != 'complete' && rs != 'loaded') return; - try { - SmartPlay(elementId, smartPlayObj); - } catch (e) { console.warn('error caught : ' + e); } - }; - - return script; -} - -function outstreamRender(bid) { - const script = createOutstreamScript(bid); - if (bid.renderer.config.outstream_function != null && typeof bid.renderer.config.outstream_function === 'function') { - bid.renderer.config.outstream_function(bid, script); - } else { - try { - const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); - if (slot && window.document.getElementById(slot)) { - window.document.getElementById(slot).appendChild(script); - } else { - window.document.getElementsByTagName('head')[0].appendChild(script); - } - } catch (err) { - utils.logError('[SMARTX][renderer] Error:' + err.message) - } - } -} - -registerBidder(spec); diff --git a/modules/smartclipBidAdapter.md b/modules/smartclipBidAdapter.md deleted file mode 100644 index 42ae736650b..00000000000 --- a/modules/smartclipBidAdapter.md +++ /dev/null @@ -1,51 +0,0 @@ -Overview -Module Name: smartclip Bidder Adapter -Module Type: Bidder Adapter -Maintainer: adtech@smartclip.tv -Description -Connect to smartclip for bids. - -This adapter requires setup and approval from the smartclip team. - -Test Parameters - Use case #1 - outstream with default rendering options - -var adUnits = [{ - code: 'video1', - mediaTypes: { - banner: { - sizes: sizes - }, - video: { - context: 'outstream', - playerSize: [640, 480] - } - }, - bids: [{ - bidder: 'smartclip', - params: { - tagId: 'Nu68JuOWAvrbzoyrOR9a7A', - publisherId: 'pubid', - siteId: 'siteId', - cat: "category", - bidfloor: 0.3, - bidfloorcur: "EUR", - at: 2, - cur: ["EUR"], - outstream_options: { - slot: 'video1' - }, - user: [{ - data: { - id: 'emq', - name: 'emq', - segment: [{ - id: 'emq', - name:'emq', - value: 'e0:k14' - }] - } - }] - //outstream_function: myOutstreamFunction - } - }], - }]; \ No newline at end of file From 2b96ef1e9498073f54b798080ef84b87ae28d347 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Fri, 29 Jan 2021 12:53:17 +0100 Subject: [PATCH 05/22] camelcase --- modules/smartxBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index b2381c41d8e..aef90350924 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -329,7 +329,7 @@ export const spec = { function createOutstreamScript(bid) { // for SmartPlay 4.12 - function sc_prebidClose(ele, completeCollapsed) { + function scPrebidClose(ele, completeCollapsed) { if (completeCollapsed) { document.getElementById(ele.id).style.display = 'none'; } @@ -384,7 +384,7 @@ function createOutstreamScript(bid) { }, onEndCallback: function (m, n) { try { - sc_prebidClose(n, completeCollapsed); // for SmartPlay 4.12 + scPrebidClose(n, completeCollapsed); // for SmartPlay 4.12 window.sc_smartIntxtEnd(n); } catch (f) {} }, From 871582019d4ccd0081998e137a8e36e34d923d4b Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Wed, 3 Feb 2021 10:45:25 +0100 Subject: [PATCH 06/22] fix --- modules/smartxBidAdapter.js | 14 +++++++------- test/spec/modules/smartxBidAdapter_spec.js | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index aef90350924..804b25d1afc 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -335,13 +335,13 @@ function createOutstreamScript(bid) { } } - const confMinAdWidth = bid.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; - const confMaxAdWidth = bid.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; - const confStartOpen = bid.getBidIdParameter('startOpen', bid.renderer.config.outstream_options) || 'false'; - const confEndingScreen = bid.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options) || 'true'; - const confHeaderText = bid.getBidIdParameter('headerText', bid.renderer.config.outstream_options) || ''; - const confSkipOffset = bid.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options) || 0; - const confDesiredBitrate = bid.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options) || 1600; + const confMinAdWidth = utils.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; + const confMaxAdWidth = utils.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; + const confStartOpen = utils.getBidIdParameter('startOpen', bid.renderer.config.outstream_options) || 'false'; + const confEndingScreen = utils.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options) || 'true'; + const confHeaderText = utils.getBidIdParameter('headerText', bid.renderer.config.outstream_options) || ''; + const confSkipOffset = utils.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options) || 0; + const confDesiredBitrate = utils.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options) || 1600; const elementId = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; // for SmartPlay 4.12 diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index efc6abcc5fa..82c6642bd74 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -493,7 +493,7 @@ describe('The smartx adapter', function () { }; }); - it('should attempt to insert the EASI script', function () { + it('should attempt to insert the script', function () { var scriptTag; sinon.stub(window.document, 'getElementById').returns({ appendChild: sinon.stub().callsFake(function (script) { From b55fb7dd9d0d9d641e3008be9046de25f98104ab Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Mon, 1 Mar 2021 15:34:26 +0100 Subject: [PATCH 07/22] Out-Stream render update to SmartPlay 5.2 --- modules/smartxBidAdapter.js | 92 ++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 53 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 804b25d1afc..e9d3f777616 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -328,50 +328,25 @@ export const spec = { } function createOutstreamScript(bid) { - // for SmartPlay 4.12 - function scPrebidClose(ele, completeCollapsed) { - if (completeCollapsed) { - document.getElementById(ele.id).style.display = 'none'; - } - } - const confMinAdWidth = utils.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; const confMaxAdWidth = utils.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; - const confStartOpen = utils.getBidIdParameter('startOpen', bid.renderer.config.outstream_options) || 'false'; - const confEndingScreen = utils.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options) || 'true'; - const confHeaderText = utils.getBidIdParameter('headerText', bid.renderer.config.outstream_options) || ''; - const confSkipOffset = utils.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options) || 0; - const confDesiredBitrate = utils.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options) || 1600; + const confStartOpen = utils.getBidIdParameter('startOpen', bid.renderer.config.outstream_options); + const confEndingScreen = utils.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options); + const confTitle = utils.getBidIdParameter('title', bid.renderer.config.outstream_options); + const confSkipOffset = utils.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options); + const confDesiredBitrate = utils.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options); const elementId = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; - // for SmartPlay 4.12 - let initCollapsed = true; - let completeCollapsed = true; - if (confStartOpen === 'true') { - initCollapsed = false; - } - if (confEndingScreen === 'true') { - completeCollapsed = false; - } - utils.logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); - let smartPlayObj = { + var smartPlayObj = { minAdWidth: confMinAdWidth, maxAdWidth: confMaxAdWidth, - headerText: confHeaderText, + title: confTitle, skipOffset: confSkipOffset, - behaviourMatrix: { - init: { - 'collapsed': initCollapsed - }, - complete: { - 'collapsed': completeCollapsed - } - }, - environmentVars: { - desiredBitrate: confDesiredBitrate, - }, + startOpen: confStartOpen, + endingScreen: confEndingScreen, + desiredBitrate: confDesiredBitrate, onStartCallback: function (m, n) { try { window.sc_smartIntxtStart(n); @@ -384,25 +359,40 @@ function createOutstreamScript(bid) { }, onEndCallback: function (m, n) { try { - scPrebidClose(n, completeCollapsed); // for SmartPlay 4.12 window.sc_smartIntxtEnd(n); } catch (f) {} }, }; + smartPlayObj.adResponse = bid.vastContent; - const script = window.document.createElement('script'); - script.type = 'text/javascript'; - script.async = 'true'; - script.src = 'https://dco.smartclip.net/?plc=7777777'; - script.onload = script.onreadystatechange = function () { - var rs = this.readyState; - if (rs && rs != 'complete' && rs != 'loaded') return; + + let script = ''; + let divID = '#' + elementId; + + var insertJSNode = function (url, nodeId = null, fun = null) { + script = document.createElement('script'); + script.type = 'text/javascript'; + if (nodeId != null) { + script.id = nodeId; + } + if (url != '') { + script.async = 'true'; + script.src = url; + if (fun != null) { + script.onload = script.onreadystatechange = fun; + } + } else { + script.text = 'var x=' + fun + '();'; + } + } + + insertJSNode('//dco.smartclip.net/?plc=7777778', null, function () { try { - window.SmartPlay(elementId, smartPlayObj); + let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj) } catch (e) { - utils.logError('error caught : ' + e); + utils.logError('[SmartPlay][renderer] Error caught: ' + e); } - }; + }) return script; } @@ -412,15 +402,11 @@ function outstreamRender(bid) { bid.renderer.config.outstream_function(bid, script); } else { try { - const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); - if (slot && window.document.getElementById(slot)) { - window.document.getElementById(slot).appendChild(script); - } else { - window.document.getElementsByTagName('head')[0].appendChild(script); - } + const firstScriptTagOnSite = window.document.getElementsByTagName('script')[0]; + firstScriptTagOnSite.parentNode.insertBefore(script, firstScriptTagOnSite); } catch (err) { utils.logError('[SMARTX][renderer] Error:' + err.message) } } } -registerBidder(spec); +registerBidder(spec); \ No newline at end of file From 1af62e69620c7649ef0964aa6e6d45dec5635d9a Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Mon, 1 Mar 2021 16:04:18 +0100 Subject: [PATCH 08/22] ESlint fix --- modules/smartxBidAdapter.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index e9d3f777616..084438e50dc 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -387,7 +387,8 @@ function createOutstreamScript(bid) { } insertJSNode('//dco.smartclip.net/?plc=7777778', null, function () { - try { + try { + // eslint-disable-next-line no-unused-vars no-undef let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj) } catch (e) { utils.logError('[SmartPlay][renderer] Error caught: ' + e); @@ -409,4 +410,4 @@ function outstreamRender(bid) { } } } -registerBidder(spec); \ No newline at end of file +registerBidder(spec); From 1ef8d74c82bfccb0f5b560b55275c725af8198bd Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Mon, 1 Mar 2021 16:13:22 +0100 Subject: [PATCH 09/22] ESlint fix --- modules/smartxBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 084438e50dc..3589dc4a573 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -388,7 +388,7 @@ function createOutstreamScript(bid) { insertJSNode('//dco.smartclip.net/?plc=7777778', null, function () { try { - // eslint-disable-next-line no-unused-vars no-undef +// eslint-disable-next-line let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj) } catch (e) { utils.logError('[SmartPlay][renderer] Error caught: ' + e); From 9134944af2a35bd9fa8513cf0b7bcdda528dfd56 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Mon, 1 Mar 2021 16:16:19 +0100 Subject: [PATCH 10/22] ESlint fix --- modules/smartxBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 3589dc4a573..91a9b730a71 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -387,8 +387,8 @@ function createOutstreamScript(bid) { } insertJSNode('//dco.smartclip.net/?plc=7777778', null, function () { - try { -// eslint-disable-next-line + try { + // eslint-disable-next-line let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj) } catch (e) { utils.logError('[SmartPlay][renderer] Error caught: ' + e); From 335b9bdf64cacb59ac63753827e0221a0d5fbfc8 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Fri, 5 Mar 2021 16:13:59 +0100 Subject: [PATCH 11/22] adjust tests, fixes --- modules/smartxBidAdapter.js | 43 ++++++++-------------- modules/smartxBidAdapter.md | 12 +++--- test/spec/modules/smartxBidAdapter_spec.js | 6 ++- 3 files changed, 26 insertions(+), 35 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 91a9b730a71..57225d850b7 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -64,7 +64,7 @@ export const spec = { return false; } if (!utils.getBidIdParameter('outstream_function', bid.params)) { - utils.logMessage(BIDDER_CODE + ': outstream_function parameter is not defined. The default outstream renderer will be injected in the header. You can override the default SmartX outstream rendering by defining your own Outstream function using field outstream_function.'); + utils.logMessage(BIDDER_CODE + ': outstream_function parameter is not defined. The default outstream renderer will be injected in the header.'); return true; } } @@ -311,7 +311,7 @@ export const spec = { return utils.logMessage('SmartX outstream video loaded event'); }, ended: function ended() { - utils.logMessage('SmartX outstream renderer video event'); + return utils.logMessage('SmartX outstream renderer video event'); } }); } catch (err) { @@ -366,34 +366,19 @@ function createOutstreamScript(bid) { smartPlayObj.adResponse = bid.vastContent; - let script = ''; - let divID = '#' + elementId; - - var insertJSNode = function (url, nodeId = null, fun = null) { - script = document.createElement('script'); - script.type = 'text/javascript'; - if (nodeId != null) { - script.id = nodeId; - } - if (url != '') { - script.async = 'true'; - script.src = url; - if (fun != null) { - script.onload = script.onreadystatechange = fun; - } - } else { - script.text = 'var x=' + fun + '();'; - } - } - - insertJSNode('//dco.smartclip.net/?plc=7777778', null, function () { + const divID = '#' + elementId; + var script = document.createElement('script'); + script.src = 'https://dco.smartclip.net/?plc=7777778'; + script.type = 'text/javascript'; + script.async = 'true'; + script.onload = script.onreadystatechange = function () { try { // eslint-disable-next-line - let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj) + let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj); } catch (e) { utils.logError('[SmartPlay][renderer] Error caught: ' + e); } - }) + }; return script; } @@ -403,8 +388,12 @@ function outstreamRender(bid) { bid.renderer.config.outstream_function(bid, script); } else { try { - const firstScriptTagOnSite = window.document.getElementsByTagName('script')[0]; - firstScriptTagOnSite.parentNode.insertBefore(script, firstScriptTagOnSite); + const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); + if (slot && window.document.getElementById(slot)) { + window.document.getElementById(slot).appendChild(script); + } else { + window.document.getElementsByTagName('head')[0].appendChild(script); + } } catch (err) { utils.logError('[SMARTX][renderer] Error:' + err.message) } diff --git a/modules/smartxBidAdapter.md b/modules/smartxBidAdapter.md index 082a36f3dde..b25ce68bb6e 100644 --- a/modules/smartxBidAdapter.md +++ b/modules/smartxBidAdapter.md @@ -36,10 +36,10 @@ This adapter requires setup and approval from the smartclip team. slot: 'video1', minAdWidth: 290, maxAdWidth: 900, - headerText: '', + title: '', skipOffset: 0, - startOpen: 'true', - endingScreen: 'true', + startOpen: true, + endingScreen: true, desiredBitrate: 1600, }, } @@ -71,10 +71,10 @@ This adapter requires setup and approval from the smartclip team. slot: 'video1', minAdWidth: 290, maxAdWidth: 900, - headerText: '', + title: '', skipOffset: 0, - startOpen: 'true', - endingScreen: 'true', + startOpen: true, + endingScreen: true, desiredBitrate: 1600, }, user: { diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index 82c6642bd74..3bcbbff98d8 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -421,6 +421,8 @@ describe('The smartx adapter', function () { it('should return an array of bid responses', function () { var responses = spec.interpretResponse(serverResponse, bidderRequestObj); expect(responses).to.be.an('array').with.length(2); + expect(bidderRequestObj).to.be.an('Object'); + expect(bidderRequestObj.bidRequest.bids).to.be.an('array').with.length(2); expect(responses[0].requestId).to.equal(123); expect(responses[0].currency).to.equal('USD'); expect(responses[0].cpm).to.equal(12); @@ -505,8 +507,8 @@ describe('The smartx adapter', function () { responses[0].renderer.render(responses[0]); expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); - expect(scriptTag.getAttribute('src')).to.equal('https://dco.smartclip.net/?plc=7777777'); - + expect(scriptTag.getAttribute('src')).to.equal('https://dco.smartclip.net/?plc=7777778'); + window.document.getElementById.restore(); }); }); From 1ae18d1ec92edbc433e23ab3d7e31773f1e0132a Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Fri, 5 Mar 2021 16:29:04 +0100 Subject: [PATCH 12/22] ESlint --- modules/smartxBidAdapter.js | 2 +- test/spec/modules/smartxBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 57225d850b7..57c54cb5090 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -390,7 +390,7 @@ function outstreamRender(bid) { try { const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); if (slot && window.document.getElementById(slot)) { - window.document.getElementById(slot).appendChild(script); + window.document.getElementById(slot).appendChild(script); } else { window.document.getElementsByTagName('head')[0].appendChild(script); } diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index 3bcbbff98d8..abc06b48ce7 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -508,7 +508,7 @@ describe('The smartx adapter', function () { expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); expect(scriptTag.getAttribute('src')).to.equal('https://dco.smartclip.net/?plc=7777778'); - + window.document.getElementById.restore(); }); }); From f6d48166775a1dd4d96c6415c7e8caa324e52520 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Thu, 18 Mar 2021 13:01:28 +0100 Subject: [PATCH 13/22] adjusted desired bitrate examples --- modules/smartxBidAdapter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/smartxBidAdapter.md b/modules/smartxBidAdapter.md index b25ce68bb6e..223e51763b9 100644 --- a/modules/smartxBidAdapter.md +++ b/modules/smartxBidAdapter.md @@ -40,7 +40,7 @@ This adapter requires setup and approval from the smartclip team. skipOffset: 0, startOpen: true, endingScreen: true, - desiredBitrate: 1600, + desiredBitrate: 800, }, } }], @@ -75,7 +75,7 @@ This adapter requires setup and approval from the smartclip team. skipOffset: 0, startOpen: true, endingScreen: true, - desiredBitrate: 1600, + desiredBitrate: 800, }, user: { data: [{ From 94b7510a9445aede729efb26b6f9b20f2b90dcbf Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Thu, 8 Apr 2021 11:41:45 +0200 Subject: [PATCH 14/22] added bid.meta.advertiserDomains support --- modules/smartxBidAdapter.js | 13 +++++++++++++ test/spec/modules/smartxBidAdapter_spec.js | 2 ++ 2 files changed, 15 insertions(+) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 57c54cb5090..b95b31934a2 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -149,6 +149,7 @@ export const spec = { } const language = navigator.language ? 'language' : 'userLanguage'; + const device = { h: screen.height, w: screen.width, @@ -157,8 +158,11 @@ export const spec = { make: navigator.vendor ? navigator.vendor : '', ua: navigator.userAgent }; + const at = utils.getBidIdParameter('at', bid.params) || 2; + const cur = utils.getBidIdParameter('cur', bid.params) || ['EUR']; + const requestPayload = { id: utils.generateUUID(), imp: smartxReq, @@ -176,6 +180,7 @@ export const spec = { at: at, cur: cur }; + const userExt = {}; // Add GDPR flag and consent string @@ -271,6 +276,7 @@ export const spec = { serverResponseBody.cur = pmb.currency; } }); + const bid = { requestId: currentBidRequest.bidId, currency: serverResponseBody.cur || 'USD', @@ -284,7 +290,14 @@ export const spec = { width: smartxBid.w, height: smartxBid.h }; + + bid.meta = bid.meta || {}; + if (smartxBid && smartxBid.adomain && smartxBid.adomain.length > 0) { + bid.meta.advertiserDomains = smartxBid.adomain; + } + const context = utils.deepAccess(currentBidRequest, 'mediaTypes.video.context'); + if (context === 'outstream') { const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); const renderer = Renderer.install({ diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index abc06b48ce7..3c871c6f88b 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -423,6 +423,7 @@ describe('The smartx adapter', function () { expect(responses).to.be.an('array').with.length(2); expect(bidderRequestObj).to.be.an('Object'); expect(bidderRequestObj.bidRequest.bids).to.be.an('array').with.length(2); + expect(responses[0].meta.advertiserDomains[0]).to.equal('abc.com'); expect(responses[0].requestId).to.equal(123); expect(responses[0].currency).to.equal('USD'); expect(responses[0].cpm).to.equal(12); @@ -432,6 +433,7 @@ describe('The smartx adapter', function () { expect(responses[0].mediaType).to.equal('video'); expect(responses[0].width).to.equal(400); expect(responses[0].height).to.equal(300); + expect(responses[1].meta.advertiserDomains[0]).to.equal('def.com'); expect(responses[1].requestId).to.equal(124); expect(responses[1].currency).to.equal('USD'); expect(responses[1].cpm).to.equal(13); From 4861e233a0fd6e99fa2b78fe1768574e1f85a9cc Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Wed, 14 Apr 2021 16:08:21 +0200 Subject: [PATCH 15/22] bug fix for numeric elementID outstream render --- modules/smartxBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index b95b31934a2..6b34e499a99 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -379,7 +379,7 @@ function createOutstreamScript(bid) { smartPlayObj.adResponse = bid.vastContent; - const divID = '#' + elementId; + const divID = '[id="' + elementId + '"]'; var script = document.createElement('script'); script.src = 'https://dco.smartclip.net/?plc=7777778'; script.type = 'text/javascript'; From da45be6e36df51d03d7564c9a2b934b397c78dfa Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Fri, 7 May 2021 13:45:30 +0200 Subject: [PATCH 16/22] fix renderer url --- modules/smartxBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 6b34e499a99..b2c48b58f82 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -302,7 +302,7 @@ export const spec = { const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); const renderer = Renderer.install({ id: 0, - url: '//', + url: '/', config: { adText: 'SmartX Outstream Video Ad via Prebid.js', player_width: playersize[0][0], From 06edd1e1eb6fa2de11f8147fd2f95acba07d1215 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Tue, 1 Jun 2021 16:15:07 +0200 Subject: [PATCH 17/22] support for floors module --- modules/smartxBidAdapter.js | 42 +++++--- test/spec/modules/smartxBidAdapter_spec.js | 108 +++++++++++++++++++-- 2 files changed, 133 insertions(+), 17 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index b2c48b58f82..46e2055c8f0 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -46,14 +46,6 @@ export const spec = { utils.logError(BIDDER_CODE + ': siteId is not present in bidder params'); return false; } - if (!utils.getBidIdParameter('bidfloor', bid.params)) { - utils.logError(BIDDER_CODE + ': bidfloor is not present in bidder params'); - return false; - } - if (!utils.getBidIdParameter('bidfloorcur', bid.params)) { - utils.logError(BIDDER_CODE + ': bidfloorcur is not present in bidder params'); - return false; - } if (utils.deepAccess(bid, 'mediaTypes.video.context') === 'outstream') { if (!utils.getBidIdParameter('outstream_options', bid.params)) { utils.logError(BIDDER_CODE + ': outstream_options parameter is not defined'); @@ -85,8 +77,8 @@ export const spec = { const smartxRequests = bidRequests.map(function (bid) { const tagId = utils.getBidIdParameter('tagId', bid.params); const publisherId = utils.getBidIdParameter('publisherId', bid.params); - const bidfloor = utils.getBidIdParameter('bidfloor', bid.params); - const bidfloorcur = utils.getBidIdParameter('bidfloorcur', bid.params); + const bidfloor = getBidFloor(bid) || 0; + const bidfloorcur = utils.getBidIdParameter('bidfloorcur', bid.params) || 'EUR'; const siteId = utils.getBidIdParameter('siteId', bid.params); const domain = utils.getBidIdParameter('domain', bid.params); const cat = utils.getBidIdParameter('cat', bid.params); @@ -161,7 +153,7 @@ export const spec = { const at = utils.getBidIdParameter('at', bid.params) || 2; - const cur = utils.getBidIdParameter('cur', bid.params) || ['EUR']; + const cur = utils.getBidIdParameter('cur', bid.params) || 'EUR'; const requestPayload = { id: utils.generateUUID(), @@ -226,6 +218,8 @@ export const spec = { } } + // Todo: USER ID MODULE + requestPayload.user = { ext: userExt, data: targetingarr @@ -412,4 +406,30 @@ function outstreamRender(bid) { } } } + +/** + * Get the floor price from bid.params for backward compatibility. + * If not found, then check floor module. + * @param bid A valid bid object + * @returns {*|number} floor price + */ +function getBidFloor(bid) { + let floor = utils.getBidIdParameter('bidfloor', bid.params); + let floorcur = utils.getBidIdParameter('bidfloorcur', bid.params) || 'EUR'; + + if (!floor && utils.isFn(bid.getFloor)) { + const floorObj = bid.getFloor({ + currency: floorcur, + mediaType: '*', + size: '*' + }); + + if (utils.isPlainObject(floorObj) && !isNaN(floorObj.floor) && floorObj.currency === floorcur) { + floor = floorObj.floor; + } + } + + return floor; +} + registerBidder(spec); diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index 3c871c6f88b..d0659865afa 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -108,14 +108,13 @@ describe('The smartx adapter', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should fail without bidfloor', function () { + it('should succeed with floor Module set', function () { delete bid.params.bidfloor; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should fail without bidfloorcur', function () { delete bid.params.bidfloorcur; - expect(spec.isBidRequestValid(bid)).to.equal(false); + bid.floors = { + currency: 'EUR' + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); }); it('should fail with context outstream but no options set for outstream', function () { @@ -514,4 +513,101 @@ describe('The smartx adapter', function () { window.document.getElementById.restore(); }); }); + + describe('price floor module', function () { + var bid, + bidRequestObj; + + beforeEach(function () { + bid = getValidBidObject(); + bidRequestObj = { + refererInfo: { + referer: 'prebid.js' + } + }; + delete bid.params.bidfloor; + }); + + it('obtain floor from getFloor', function () { + bid.getFloor = () => { + return { + currency: 'EUR', + floor: 3.21 + }; + }; + + const payload = spec.buildRequests([bid], bidRequestObj)[0]; + expect(payload.data.imp).to.have.property('bidfloor', 3.21); + }); + + it('obtain floor from params', function() { + bid.getFloor = () => { + return { + currency: 'EUR', + floor: 3.21 + }; + }; + bid.params.bidfloor = 0.64; + + const payload = spec.buildRequests([bid], bidRequestObj)[0]; + expect(payload.data.imp).to.have.property('bidfloor', 0.64); + }); + + it('check currency USD', function() { + bid.getFloor = () => { + return { + currency: 'USD', + floor: 1.23 + }; + }; + bid.params.bidfloorcur = 'USD' + + const payload = spec.buildRequests([bid], bidRequestObj)[0]; + expect(payload.data.imp).to.have.property('bidfloorcur', 'USD'); + expect(payload.data.imp).to.have.property('bidfloor', 1.23); + }); + + it('check defaut currency EUR', function() { + delete bid.params.bidfloorcur; + + bid.getFloor = () => { + return { + currency: 'EUR', + floor: 4.56 + }; + }; + + const payload = spec.buildRequests([bid], bidRequestObj)[0]; + expect(payload.data.imp).to.have.property('bidfloorcur', 'EUR'); + expect(payload.data.imp).to.have.property('bidfloor', 4.56); + }); + + it('bad floor value', function() { + bid.getFloor = () => { + return { + currency: 'EUR', + floor: 'bad' + }; + }; + + const payload = spec.buildRequests([bid], bidRequestObj)[0]; + expect(payload.data.imp).to.have.property('bidfloor', 0); + }); + + it('empty floor object', function() { + bid.getFloor = () => { + return {}; + }; + + const payload = spec.buildRequests([bid], bidRequestObj)[0]; + expect(payload.data.imp).to.have.property('bidfloor', 0); + }); + + it('undefined floor result', function() { + bid.getFloor = () => {}; + + const payload = spec.buildRequests([bid], bidRequestObj)[0]; + expect(payload.data.imp).to.have.property('bidfloor', 0); + }); + }); }) From d1bd22aa226094be029ab046192578c1433ca460 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Thu, 10 Jun 2021 16:26:49 +0200 Subject: [PATCH 18/22] bugfixes to be openRTB 2.5 compliant --- modules/smartxBidAdapter.js | 9 ++-- test/spec/modules/smartxBidAdapter_spec.js | 55 +++++++++++----------- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 46e2055c8f0..657520bcde5 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -81,7 +81,7 @@ export const spec = { const bidfloorcur = utils.getBidIdParameter('bidfloorcur', bid.params) || 'EUR'; const siteId = utils.getBidIdParameter('siteId', bid.params); const domain = utils.getBidIdParameter('domain', bid.params); - const cat = utils.getBidIdParameter('cat', bid.params); + const cat = utils.getBidIdParameter('cat', bid.params) || ['']; let pubcid = null; const playerSize = utils.deepAccess(bid, 'mediaTypes.video.playerSize'); const contentWidth = playerSize[0][0]; @@ -108,7 +108,7 @@ export const spec = { placement = 3; } - let smartxReq = { + let smartxReq = [{ id: bid.bidId, secure: secure, bidfloor: bidfloor, @@ -134,7 +134,7 @@ export const spec = { ext: { 'smart.bidpricetype': 1 } - }; + }]; if (bid.crumbs && bid.crumbs.pubcid) { pubcid = bid.crumbs.pubcid; @@ -153,7 +153,7 @@ export const spec = { const at = utils.getBidIdParameter('at', bid.params) || 2; - const cur = utils.getBidIdParameter('cur', bid.params) || 'EUR'; + const cur = utils.getBidIdParameter('cur', bid.params) || ['EUR']; const requestPayload = { id: utils.generateUUID(), @@ -162,7 +162,6 @@ export const spec = { id: siteId, page: page, cat: cat, - content: 'content', domain: domain, publisher: { id: publisherId diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index d0659865afa..f02aa81980f 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -155,10 +155,10 @@ describe('The smartx adapter', function () { expect(request.method).to.equal('POST'); expect(request.url).to.equal('https://bid.sxp.smartclip.net/bid/1000'); expect(request.bidRequest).to.equal(bidRequestObj); - expect(request.data.imp.id).to.match(/\d+/); - expect(request.data.imp.secure).to.equal(0); + expect(request.data.imp[0].id).to.match(/\d+/); + expect(request.data.imp[0].secure).to.equal(0); - expect(request.data.imp.video).to.deep.equal({ + expect(request.data.imp[0].video).to.deep.equal({ ext: { sdk_name: 'Prebid 1+' }, @@ -183,10 +183,9 @@ describe('The smartx adapter', function () { }); expect(request.data.site).to.deep.equal({ - content: 'content', id: '__name__', page: 'prebid.js', - cat: '', + cat: [''], domain: '', publisher: { id: '__name__' @@ -197,11 +196,11 @@ describe('The smartx adapter', function () { it('should change request parameters based on options sent', function () { var request = spec.buildRequests([bid], bidRequestObj)[0]; - expect(request.data.imp.video.ext).to.deep.equal({ + expect(request.data.imp[0].video.ext).to.deep.equal({ sdk_name: 'Prebid 1+' }); - expect(request.data.imp.video).to.contain({ + expect(request.data.imp[0].video).to.contain({ placement: 1 }); @@ -233,30 +232,30 @@ describe('The smartx adapter', function () { request = spec.buildRequests([bid], bidRequestObj)[0]; - expect(request.data.imp.video.ext).to.deep.equal({ + expect(request.data.imp[0].video.ext).to.deep.equal({ sdk_name: 'Prebid 1+' }); - expect(request.data.imp.video).to.contain({ + expect(request.data.imp[0].video).to.contain({ minduration: 5, maxduration: 10 }); - expect(request.data.imp.video.startdelay).to.equal(1); + expect(request.data.imp[0].video.startdelay).to.equal(1); - expect(request.data.imp.video).to.contain({ + expect(request.data.imp[0].video).to.contain({ placement: 3 }); - expect(request.data.imp.bidfloor).to.equal(55); + expect(request.data.imp[0].bidfloor).to.equal(55); - expect(request.data.imp.bidfloorcur).to.equal('foo'); + expect(request.data.imp[0].bidfloorcur).to.equal('foo'); - expect(request.data.imp.video.linearity).to.equal(2); + expect(request.data.imp[0].video.linearity).to.equal(2); - expect(request.data.imp.video.minbitrate).to.equal(50); + expect(request.data.imp[0].video.minbitrate).to.equal(50); - expect(request.data.imp.video.maxbitrate).to.equal(500); + expect(request.data.imp[0].video.maxbitrate).to.equal(500); }); it('should pass GDPR params', function () { @@ -321,7 +320,7 @@ describe('The smartx adapter', function () { request = spec.buildRequests([bid], bidRequestObj)[0]; - expect(request.data.imp.video.linearity).to.equal(3); + expect(request.data.imp[0].video.linearity).to.equal(3); }); it('should pass min and max duration params', function () { @@ -332,8 +331,8 @@ describe('The smartx adapter', function () { request = spec.buildRequests([bid], bidRequestObj)[0]; - expect(request.data.imp.video.minduration).to.equal(3); - expect(request.data.imp.video.maxduration).to.equal(15); + expect(request.data.imp[0].video.minduration).to.equal(3); + expect(request.data.imp[0].video.maxduration).to.equal(15); }); }); @@ -537,7 +536,7 @@ describe('The smartx adapter', function () { }; const payload = spec.buildRequests([bid], bidRequestObj)[0]; - expect(payload.data.imp).to.have.property('bidfloor', 3.21); + expect(payload.data.imp[0]).to.have.property('bidfloor', 3.21); }); it('obtain floor from params', function() { @@ -550,7 +549,7 @@ describe('The smartx adapter', function () { bid.params.bidfloor = 0.64; const payload = spec.buildRequests([bid], bidRequestObj)[0]; - expect(payload.data.imp).to.have.property('bidfloor', 0.64); + expect(payload.data.imp[0]).to.have.property('bidfloor', 0.64); }); it('check currency USD', function() { @@ -563,8 +562,8 @@ describe('The smartx adapter', function () { bid.params.bidfloorcur = 'USD' const payload = spec.buildRequests([bid], bidRequestObj)[0]; - expect(payload.data.imp).to.have.property('bidfloorcur', 'USD'); - expect(payload.data.imp).to.have.property('bidfloor', 1.23); + expect(payload.data.imp[0]).to.have.property('bidfloorcur', 'USD'); + expect(payload.data.imp[0]).to.have.property('bidfloor', 1.23); }); it('check defaut currency EUR', function() { @@ -578,8 +577,8 @@ describe('The smartx adapter', function () { }; const payload = spec.buildRequests([bid], bidRequestObj)[0]; - expect(payload.data.imp).to.have.property('bidfloorcur', 'EUR'); - expect(payload.data.imp).to.have.property('bidfloor', 4.56); + expect(payload.data.imp[0]).to.have.property('bidfloorcur', 'EUR'); + expect(payload.data.imp[0]).to.have.property('bidfloor', 4.56); }); it('bad floor value', function() { @@ -591,7 +590,7 @@ describe('The smartx adapter', function () { }; const payload = spec.buildRequests([bid], bidRequestObj)[0]; - expect(payload.data.imp).to.have.property('bidfloor', 0); + expect(payload.data.imp[0]).to.have.property('bidfloor', 0); }); it('empty floor object', function() { @@ -600,14 +599,14 @@ describe('The smartx adapter', function () { }; const payload = spec.buildRequests([bid], bidRequestObj)[0]; - expect(payload.data.imp).to.have.property('bidfloor', 0); + expect(payload.data.imp[0]).to.have.property('bidfloor', 0); }); it('undefined floor result', function() { bid.getFloor = () => {}; const payload = spec.buildRequests([bid], bidRequestObj)[0]; - expect(payload.data.imp).to.have.property('bidfloor', 0); + expect(payload.data.imp[0]).to.have.property('bidfloor', 0); }); }); }) From def250bf25aebc92bc61b688dbdeaf65a1ef5449 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Thu, 1 Jul 2021 17:30:11 +0200 Subject: [PATCH 19/22] update internal renderer usage --- modules/smartxBidAdapter.js | 41 +++++----------------- test/spec/modules/smartxBidAdapter_spec.js | 5 +-- 2 files changed, 12 insertions(+), 34 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 657520bcde5..bed1d680246 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -295,7 +295,7 @@ export const spec = { const playersize = utils.deepAccess(currentBidRequest, 'mediaTypes.video.playerSize'); const renderer = Renderer.install({ id: 0, - url: '/', + url: 'https://dco.smartclip.net/?plc=7777778', config: { adText: 'SmartX Outstream Video Ad via Prebid.js', player_width: playersize[0][0], @@ -308,7 +308,7 @@ export const spec = { } }); try { - renderer.setRender(outstreamRender); + renderer.setRender(createOutstreamConfig); renderer.setEventHandlers({ impression: function impression() { return utils.logMessage('SmartX outstream video impression event'); @@ -333,7 +333,7 @@ export const spec = { } } -function createOutstreamScript(bid) { +function createOutstreamConfig(bid) { const confMinAdWidth = utils.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; const confMaxAdWidth = utils.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; const confStartOpen = utils.getBidIdParameter('startOpen', bid.renderer.config.outstream_options); @@ -373,37 +373,14 @@ function createOutstreamScript(bid) { smartPlayObj.adResponse = bid.vastContent; const divID = '[id="' + elementId + '"]'; - var script = document.createElement('script'); - script.src = 'https://dco.smartclip.net/?plc=7777778'; - script.type = 'text/javascript'; - script.async = 'true'; - script.onload = script.onreadystatechange = function () { - try { - // eslint-disable-next-line - let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj); - } catch (e) { - utils.logError('[SmartPlay][renderer] Error caught: ' + e); - } - }; - return script; -} -function outstreamRender(bid) { - const script = createOutstreamScript(bid); - if (bid.renderer.config.outstream_function != null && typeof bid.renderer.config.outstream_function === 'function') { - bid.renderer.config.outstream_function(bid, script); - } else { - try { - const slot = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options); - if (slot && window.document.getElementById(slot)) { - window.document.getElementById(slot).appendChild(script); - } else { - window.document.getElementsByTagName('head')[0].appendChild(script); - } - } catch (err) { - utils.logError('[SMARTX][renderer] Error:' + err.message) - } + try { + // eslint-disable-next-line + let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj); + } catch (e) { + utils.logError('[SMARTX][renderer] Error caught: ' + e); } + return smartPlayObj; } /** diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index f02aa81980f..89c03034ba4 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -506,8 +506,9 @@ describe('The smartx adapter', function () { responses[0].renderer.render(responses[0]); - expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); - expect(scriptTag.getAttribute('src')).to.equal('https://dco.smartclip.net/?plc=7777778'); + // expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); + // expect(scriptTag.getAttribute('src')).to.equal('https://dco.smartclip.net/?plc=7777778'); + expect(responses[0].renderer.url).to.equal('https://dco.smartclip.net/?plc=7777778'); window.document.getElementById.restore(); }); From cec1e823da2afb6277b5ffcc800af49dfbf8d7e4 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Thu, 1 Jul 2021 17:36:33 +0200 Subject: [PATCH 20/22] remove unused outstream_function logic --- modules/smartxBidAdapter.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index bed1d680246..c29708c8420 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -55,10 +55,6 @@ export const spec = { utils.logError(BIDDER_CODE + ': slot parameter is not defined in outstream_options object in the configuration'); return false; } - if (!utils.getBidIdParameter('outstream_function', bid.params)) { - utils.logMessage(BIDDER_CODE + ': outstream_function parameter is not defined. The default outstream renderer will be injected in the header.'); - return true; - } } return true; @@ -303,8 +299,7 @@ export const spec = { content_page_url: utils.deepAccess(bidderRequest, 'data.site.page'), ad_mute: +!!utils.deepAccess(currentBidRequest, 'params.ad_mute'), hide_skin: +!!utils.deepAccess(currentBidRequest, 'params.hide_skin'), - outstream_options: utils.deepAccess(currentBidRequest, 'params.outstream_options'), - outstream_function: utils.deepAccess(currentBidRequest, 'params.outstream_function') + outstream_options: utils.deepAccess(currentBidRequest, 'params.outstream_options') } }); try { From 48b6f44e6c78216d9c90e3b2e71dc895c43649f9 Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Wed, 1 Sep 2021 15:09:26 +0200 Subject: [PATCH 21/22] bugfix outstream options for default outstream renderer configuration --- modules/smartxBidAdapter.js | 47 ++++++++++++----- modules/smartxBidAdapter.md | 8 +-- test/spec/modules/smartxBidAdapter_spec.js | 61 ++++++++++++++++++---- 3 files changed, 89 insertions(+), 27 deletions(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index c29708c8420..44e70082d9d 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -329,25 +329,20 @@ export const spec = { } function createOutstreamConfig(bid) { - const confMinAdWidth = utils.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; - const confMaxAdWidth = utils.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; - const confStartOpen = utils.getBidIdParameter('startOpen', bid.renderer.config.outstream_options); - const confEndingScreen = utils.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options); - const confTitle = utils.getBidIdParameter('title', bid.renderer.config.outstream_options); - const confSkipOffset = utils.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options); - const confDesiredBitrate = utils.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options); - const elementId = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; + let confMinAdWidth = utils.getBidIdParameter('minAdWidth', bid.renderer.config.outstream_options) || 290; + let confMaxAdWidth = utils.getBidIdParameter('maxAdWidth', bid.renderer.config.outstream_options) || 900; + let confStartOpen = utils.getBidIdParameter('startOpen', bid.renderer.config.outstream_options) + let confEndingScreen = utils.getBidIdParameter('endingScreen', bid.renderer.config.outstream_options) + let confTitle = utils.getBidIdParameter('title', bid.renderer.config.outstream_options); + let confSkipOffset = utils.getBidIdParameter('skipOffset', bid.renderer.config.outstream_options); + let confDesiredBitrate = utils.getBidIdParameter('desiredBitrate', bid.renderer.config.outstream_options); + let elementId = utils.getBidIdParameter('slot', bid.renderer.config.outstream_options) || bid.adUnitCode; utils.logMessage('[SMARTX][renderer] Handle SmartX outstream renderer'); var smartPlayObj = { minAdWidth: confMinAdWidth, maxAdWidth: confMaxAdWidth, - title: confTitle, - skipOffset: confSkipOffset, - startOpen: confStartOpen, - endingScreen: confEndingScreen, - desiredBitrate: confDesiredBitrate, onStartCallback: function (m, n) { try { window.sc_smartIntxtStart(n); @@ -365,13 +360,37 @@ function createOutstreamConfig(bid) { }, }; + if (confStartOpen == 'true') { + smartPlayObj.startOpen = true; + } else if (confStartOpen == 'false') { + smartPlayObj.startOpen = false; + } + + if (confEndingScreen == 'true') { + smartPlayObj.endingScreen = true; + } else if (confEndingScreen == 'false') { + smartPlayObj.endingScreen = false; + } + + if (confTitle) { + smartPlayObj.title = confTitle; + } + + if (confSkipOffset) { + smartPlayObj.skipOffset = confSkipOffset; + } + + if (confDesiredBitrate) { + smartPlayObj.desiredBitrate = confDesiredBitrate; + } + smartPlayObj.adResponse = bid.vastContent; const divID = '[id="' + elementId + '"]'; try { // eslint-disable-next-line - let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj); + let _outstreamPlayer = new OutstreamPlayer(divID, smartPlayObj); } catch (e) { utils.logError('[SMARTX][renderer] Error caught: ' + e); } diff --git a/modules/smartxBidAdapter.md b/modules/smartxBidAdapter.md index 223e51763b9..853f06d6baf 100644 --- a/modules/smartxBidAdapter.md +++ b/modules/smartxBidAdapter.md @@ -38,8 +38,8 @@ This adapter requires setup and approval from the smartclip team. maxAdWidth: 900, title: '', skipOffset: 0, - startOpen: true, - endingScreen: true, + startOpen: 'true', + endingScreen: 'true', desiredBitrate: 800, }, } @@ -73,8 +73,8 @@ This adapter requires setup and approval from the smartclip team. maxAdWidth: 900, title: '', skipOffset: 0, - startOpen: true, - endingScreen: true, + startOpen: 'true', + endingScreen: 'true', desiredBitrate: 800, }, user: { diff --git a/test/spec/modules/smartxBidAdapter_spec.js b/test/spec/modules/smartxBidAdapter_spec.js index 89c03034ba4..4e560c87df3 100644 --- a/test/spec/modules/smartxBidAdapter_spec.js +++ b/test/spec/modules/smartxBidAdapter_spec.js @@ -495,7 +495,7 @@ describe('The smartx adapter', function () { }; }); - it('should attempt to insert the script', function () { + it('should attempt to insert the script without outstream config options set', function () { var scriptTag; sinon.stub(window.document, 'getElementById').returns({ appendChild: sinon.stub().callsFake(function (script) { @@ -506,8 +506,51 @@ describe('The smartx adapter', function () { responses[0].renderer.render(responses[0]); - // expect(scriptTag.getAttribute('type')).to.equal('text/javascript'); - // expect(scriptTag.getAttribute('src')).to.equal('https://dco.smartclip.net/?plc=7777778'); + expect(responses[0].renderer.url).to.equal('https://dco.smartclip.net/?plc=7777778'); + + window.document.getElementById.restore(); + }); + + it('should attempt to insert the script with outstream config options set', function () { + var scriptTag; + sinon.stub(window.document, 'getElementById').returns({ + appendChild: sinon.stub().callsFake(function (script) { + scriptTag = script + }) + }); + var responses = spec.interpretResponse(serverResponse, bidderRequestObj); + + bidderRequestObj.bidRequest.bids[0].params.outstream_options.startOpen = 'true'; + bidderRequestObj.bidRequest.bids[0].params.outstream_options.endingScreen = 'true'; + bidderRequestObj.bidRequest.bids[0].params.outstream_options.title = 'abc'; + bidderRequestObj.bidRequest.bids[0].params.outstream_options.skipOffset = 2; + bidderRequestObj.bidRequest.bids[0].params.outstream_options.desiredBitrate = 123; + + responses[0].renderer.render(responses[0]); + + bidderRequestObj.bidRequest.bids[0].params.outstream_options.startOpen = 'false'; + bidderRequestObj.bidRequest.bids[0].params.outstream_options.endingScreen = 'false'; + + responses[0].renderer.render(responses[0]); + + expect(responses[0].renderer.url).to.equal('https://dco.smartclip.net/?plc=7777778'); + + window.document.getElementById.restore(); + }); + + it('should attempt to insert the script without defined slot', function () { + var scriptTag; + sinon.stub(window.document, 'getElementById').returns({ + appendChild: sinon.stub().callsFake(function (script) { + scriptTag = script + }) + }); + var responses = spec.interpretResponse(serverResponse, bidderRequestObj); + + delete bidderRequestObj.bidRequest.bids[0].params.outstream_options.slot; + + responses[0].renderer.render(responses[0]); + expect(responses[0].renderer.url).to.equal('https://dco.smartclip.net/?plc=7777778'); window.document.getElementById.restore(); @@ -540,7 +583,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 3.21); }); - it('obtain floor from params', function() { + it('obtain floor from params', function () { bid.getFloor = () => { return { currency: 'EUR', @@ -553,7 +596,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 0.64); }); - it('check currency USD', function() { + it('check currency USD', function () { bid.getFloor = () => { return { currency: 'USD', @@ -567,7 +610,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 1.23); }); - it('check defaut currency EUR', function() { + it('check defaut currency EUR', function () { delete bid.params.bidfloorcur; bid.getFloor = () => { @@ -582,7 +625,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 4.56); }); - it('bad floor value', function() { + it('bad floor value', function () { bid.getFloor = () => { return { currency: 'EUR', @@ -594,7 +637,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 0); }); - it('empty floor object', function() { + it('empty floor object', function () { bid.getFloor = () => { return {}; }; @@ -603,7 +646,7 @@ describe('The smartx adapter', function () { expect(payload.data.imp[0]).to.have.property('bidfloor', 0); }); - it('undefined floor result', function() { + it('undefined floor result', function () { bid.getFloor = () => {}; const payload = spec.buildRequests([bid], bidRequestObj)[0]; From 354383519276a8033b925b5e5723b4a662c3482e Mon Sep 17 00:00:00 2001 From: Gino Cirlini Date: Wed, 15 Sep 2021 11:00:56 +0200 Subject: [PATCH 22/22] [PREB-10] fix empty title not configurable --- modules/smartxBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/smartxBidAdapter.js b/modules/smartxBidAdapter.js index 44e70082d9d..73e036cadb0 100644 --- a/modules/smartxBidAdapter.js +++ b/modules/smartxBidAdapter.js @@ -372,7 +372,7 @@ function createOutstreamConfig(bid) { smartPlayObj.endingScreen = false; } - if (confTitle) { + if (confTitle || (typeof bid.renderer.config.outstream_options.title == 'string' && bid.renderer.config.outstream_options.title == '')) { smartPlayObj.title = confTitle; }