UNPKG

mk9-prebid

Version:

Header Bidding Management Library

377 lines (322 loc) 11.3 kB
import * as utils from '../src/utils.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'inskin'; const CONFIG = { BASE_URI: 'https://mfad.inskinad.com/api/v2' }; export const spec = { code: BIDDER_CODE, /** * Determines whether or not the given bid request is valid. * * @param {BidRequest} bid The bid params to validate. * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function(bid) { return !!(bid.params.networkId && bid.params.siteId); }, /** * Make a server request from the list of BidRequests. * * @param {validBidRequests[]} - an array of bids * @param {bidderRequest} - the full bidder request object * @return ServerRequest Info describing the request to the server. */ buildRequests: function(validBidRequests, bidderRequest) { // Do we need to group by bidder? i.e. to make multiple requests for // different endpoints. let ret = { method: 'POST', url: '', data: '', bidRequest: [] }; if (validBidRequests.length < 1) { return ret; } let ENDPOINT_URL; const data = Object.assign({ placements: [], time: Date.now(), user: {}, url: bidderRequest.refererInfo.referer, enableBotFiltering: true, includePricingData: true, parallel: true }, validBidRequests[0].params); data.keywords = data.keywords || []; const restrictions = []; if (bidderRequest && bidderRequest.gdprConsent) { data.consent = { gdprVendorId: 150, gdprConsentString: bidderRequest.gdprConsent.consentString, // will check if the gdprApplies field was populated with a boolean value (ie from page config). If it's undefined, then default to true gdprConsentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true }; if (bidderRequest.gdprConsent.apiVersion === 2) { const purposes = [ {id: 1, kw: 'nocookies'}, {id: 2, kw: 'nocontext'}, {id: 3, kw: 'nodmp'}, {id: 4, kw: 'nodata'}, {id: 7, kw: 'noclicks'}, {id: 9, kw: 'noresearch'} ]; const d = bidderRequest.gdprConsent.vendorData; if (d) { if (d.purposeOneTreatment) { data.keywords.push('cst-nodisclosure'); restrictions.push('nodisclosure'); } purposes.map(p => { if (!checkConsent(p.id, d)) { data.keywords.push('cst-' + p.kw); restrictions.push(p.kw); } }); } } } validBidRequests.map(bid => { ENDPOINT_URL = CONFIG.BASE_URI; const placement = Object.assign({ divName: bid.bidId, adTypes: bid.adTypes || getSize(bid.sizes), eventIds: [40, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295] }, bid.params); placement.adTypes.push(5, 9, 163, 2163, 3006); placement.properties = placement.properties || {}; placement.properties.screenWidth = screen.width; placement.properties.screenHeight = screen.height; if (restrictions.length) { placement.properties.restrictions = restrictions; } if (placement.networkId && placement.siteId) { data.placements.push(placement); } }); ret.data = JSON.stringify(data); ret.bidRequest = validBidRequests; ret.url = ENDPOINT_URL; return ret; }, /** * 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, bidRequest) { let bid; let bids; let bidId; let bidObj; let bidResponses = []; let bidsMap = {}; bids = bidRequest.bidRequest; serverResponse = (serverResponse || {}).body; for (let i = 0; i < bids.length; i++) { bid = {}; bidObj = bids[i]; bidId = bidObj.bidId; bidsMap[bidId] = bidObj; if (serverResponse) { const decision = serverResponse.decisions && serverResponse.decisions[bidId]; const data = decision && decision.contents && decision.contents[0] && decision.contents[0].data; const pubCPM = data && data.customData && data.customData.pubCPM; const clearPrice = decision && decision.pricing && decision.pricing.clearPrice; const price = pubCPM || clearPrice; if (decision && price) { decision.impressionUrl += ('&property:pubcpm=' + price); bidObj.price = price; bid.requestId = bidId; bid.cpm = price; bid.width = decision.width; bid.height = decision.height; bid.ad = retrieveAd(bidId, decision); bid.currency = 'USD'; bid.creativeId = decision.adId; bid.ttl = 360; bid.meta = { advertiserDomains: decision.adomain ? decision.adomain : [] } bid.netRevenue = true; bidResponses.push(bid); } } } if (bidResponses.length) { window.addEventListener('message', function(e) { if (!e.data || e.data.from !== 'ism-bid') { return; } const decision = serverResponse.decisions && serverResponse.decisions[e.data.bidId]; if (!decision) { return; } const id = 'ism_tag_' + Math.floor((Math.random() * 10e16)); window[id] = { plr_AdSlot: e.source && e.source.frameElement, bidId: e.data.bidId, bidPrice: bidsMap[e.data.bidId].price, serverResponse }; const script = document.createElement('script'); script.src = 'https://cdn.inskinad.com/isfe/publishercode/' + bidsMap[e.data.bidId].params.siteId + '/default.js?autoload&id=' + id; document.getElementsByTagName('head')[0].appendChild(script); }); } return bidResponses; }, getUserSyncs: function(syncOptions) { const userSyncs = []; if (syncOptions.pixelEnabled) { userSyncs.push({ type: 'image', url: 'https://e.serverbid.com/udb/9969/match?redir=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fpool%2Fset%2Fi.gif%3FpoolId%3D9969%26poolKey%3D' }); userSyncs.push({ type: 'image', url: 'https://ssum.casalemedia.com/usermatchredir?s=185638&cb=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fsync%2Fi.gif%3FpartnerId%3D1%26userId%3D' }); } if (syncOptions.iframeEnabled) { userSyncs.push({ type: 'iframe', url: 'https://ssum-sec.casalemedia.com/usermatch?s=184665&cb=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fsync%2Fi.gif%3FpartnerId%3D1%26userId%3D' }); } return userSyncs; } }; const sizeMap = [ null, '120x90', '120x90', '468x60', '728x90', '300x250', '160x600', '120x600', '300x100', '180x150', '336x280', '240x400', '234x60', '88x31', '120x60', '120x240', '125x125', '220x250', '250x250', '250x90', '0x0', '200x90', '300x50', '320x50', '320x480', '185x185', '620x45', '300x125', '800x250' ]; sizeMap[77] = '970x90'; sizeMap[123] = '970x250'; sizeMap[43] = '300x600'; function getSize(sizes) { const result = []; sizes.forEach(function(size) { const index = sizeMap.indexOf(size[0] + 'x' + size[1]); if (index >= 0) { result.push(index); } }); return result; } function retrieveAd(bidId, decision) { return "<script>window.top.postMessage({from: 'ism-bid', bidId: '" + bidId + "'}, '*');\x3c/script>" + utils.createTrackPixelHtml(decision.impressionUrl); } function checkConsent(P, d) { const GVL = {'150': {'id': 150, 'name': 'Inskin Media LTD', 'purposes': {'1': 1, '3': 3, '4': 4, '9': 9, '10': 10}, 'legIntPurposes': {'2': 2, '7': 7}, 'flexiblePurposes': {'2': 2, '7': 7}, 'specialPurposes': {'1': 1, '2': 2}, 'features': {'3': 3}, 'specialFeatures': {}, 'policyUrl': 'http://www.inskinmedia.com/privacy-policy.html'}}; const V = 150; // vendor claims (inflexible) consent as their basis, publisher doesn't // restrict the purpose, user consents to the purpose and user consents // to the vendor try { if ( GVL[V].purposes[P] && !GVL[V].flexiblePurposes[P] && d.purpose.consents[P] && d.vendor.consents[V] ) { return true; } } catch (e) {} // vendor claims (inflexible) legitimate interest as their basis, // publisher doesn't restrict the purpose, user was provided notice of the // legitimate interest basis for this purpose and user was provided notice // for the LI basis for this vendor try { if ( GVL[V].legIntPurposes[P] && !GVL[V].flexiblePurposes[P] && d.purpose.legitimateInterests[P] && d.vendor.legitimateInterests[V] ) { return true; } } catch (e) {} // vendor claims flexible legal basis with legitimate interest as the // default, publisher restriction doesn't require consent, and ((user was // provided notice of the legitimate interest basis for this // purpose + vendor) OR (user consents to purpose + vendor)) try { if ( GVL[V].legIntPurposes[P] && GVL[V].flexiblePurposes[P] && ( (d.purpose.legitimateInterests[P] && d.vendor.legitimateInterests[V]) || (d.purpose.consents[P] && d.vendor.consents[V]) ) ) { return true; } } catch (e) {} // vendor claims flexible legal basis with legitimate interest as the // default, publisher restriction does require consent, and user consents // to purpose + vendor try { if ( GVL[V].legIntPurposes[P] && GVL[V].flexiblePurposes[P] && d.purpose.consents[P] && d.vendor.consents[V] ) { return true; } } catch (e) {} // vendor claims flexible legal basis with consent as the default, // publisher restriction doesn't require legitimate interest, and ((user // was provided notice of the legitimate interest basis for this purpose + // vendor) OR (user consents to purpose + vendor)) try { if ( GVL[V].purposes[P] && GVL[V].flexiblePurposes[P] && ( (d.purpose.legitimateInterests[P] && d.vendor.legitimateInterests[V]) || (d.purpose.consents[P] && d.vendor.consents[V]) ) ) { return true; } } catch (e) {} // vendor claims flexible legal basis with consent as the default, // publisher restriction does require legitimate interest, and user was // provided notice for the legitimate interest basis for this purpose + // vendor try { if ( GVL[V].purposes[P] && GVL[V].flexiblePurposes[P] && d.purpose.legitimateInterests[P] && d.vendor.legitimateInterests[V] ) { return true; } } catch (e) {} return false; } registerBidder(spec);