From aa0c2de6d308ea0142828af836e6a63c4ee75f7e Mon Sep 17 00:00:00 2001 From: smartclip AdTechnology Date: Wed, 20 May 2020 16:34:34 +0200 Subject: [PATCH 1/6] 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 2/6] 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 3/6] - 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 4/6] 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 5/6] 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 6/6] 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) {