Created
April 21, 2020 19:05
-
-
Save walia/b625b2dcb6c37dc5f4d2194fb8bed6d9 to your computer and use it in GitHub Desktop.
ix adapter work
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Dependencies //////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
var Inspector = require('../../../libs/external/schema-inspector.js'); | |
//////////////////////////////////////////////////////////////////////////////// | |
// Main //////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
/* ============================================================================= | |
* STEP 0 | Config Validation | |
* ----------------------------------------------------------------------------- | |
* This file contains the necessary validation for the partner configuration. | |
* This validation will be performed on the partner specific configuration object | |
* that is passed into the wrapper. The wrapper uses an outside library called | |
* schema-insepctor to perform the validation. Information about it can be found here: | |
* https://atinux.fr/schema-inspector/. | |
*/ | |
function partnerValidator(configs) { | |
var result = Inspector.validate({ | |
type: 'object', | |
properties: { | |
partnerId: { | |
type: 'string', | |
minLength: 1 | |
}, | |
xSlots: { | |
type: 'object', | |
properties: { | |
'*': { | |
type: 'object', | |
properties: { | |
sizes: { | |
type: 'array', | |
minLength: 1, | |
items: { | |
type: 'array', | |
exactLength: 2, | |
items: { | |
type: 'integer' | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
}, configs); | |
if (!result.valid) { | |
return result.format(); | |
} | |
return null; | |
} | |
module.exports = partnerValidator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
//////////////////////////////////////////////////////////////////////////////// | |
// Dependencies //////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
var Browser = require('browser.js'); | |
var Classify = require('classify.js'); | |
var Constants = require('constants.js'); | |
var Partner = require('partner.js'); | |
var Size = require('size.js'); | |
var SpaceCamp = require('space-camp.js'); | |
var System = require('system.js'); | |
var Network = require('network.js'); | |
var Utilities = require('utilities.js'); | |
var ComplianceService; | |
var RenderService; | |
//? if (DEBUG) { | |
var ConfigValidators = require('config-validators.js'); | |
var PartnerSpecificValidator = require('vroom-htb-validator.js'); | |
var Scribe = require('scribe.js'); | |
var Whoopsie = require('whoopsie.js'); | |
//? } | |
//////////////////////////////////////////////////////////////////////////////// | |
// Main //////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
/** | |
* Partner module template | |
* | |
* @class | |
*/ | |
function VroomHtb(configs) { | |
/* ===================================== | |
* Data | |
* ---------------------------------- */ | |
/* Private | |
* ---------------------------------- */ | |
/** | |
* Reference to the partner base class. | |
* | |
* @private {object} | |
*/ | |
var __baseClass; | |
/** | |
* Profile for this partner. | |
* | |
* @private {object} | |
*/ | |
var __profile; | |
/* ===================================== | |
* Functions | |
* ---------------------------------- */ | |
/* Utilities | |
* ---------------------------------- */ | |
/** | |
* Generates the request URL and query data to the endpoint for the xSlots | |
* in the given returnParcels. | |
* | |
* @param {object[]} returnParcels | |
* | |
* @return {object} | |
*/ | |
function __generateRequestObj(returnParcels) { | |
/* ============================================================================= | |
* STEP 2 | Generate Request URL | |
* ----------------------------------------------------------------------------- | |
* / | |
/* ---------------------- PUT CODE HERE ------------------------------------ */ | |
console.log("😭😭😭😭"); | |
console.log(configs); | |
var callbackId = System.generateUniqueId(); | |
var queryObj = { | |
slots: returnParcels.map(function (parcel) { | |
return { | |
name: parcel.xSlotName, | |
sizes: parcel.xSlotRef.sizes, | |
partnerId: configs.partnerId, | |
callbackId: callbackId | |
}; | |
}), | |
meta: { | |
adapterVersion: __profile.version, | |
pageUrl: Browser.getPageUrl(), | |
screen: Size.arrayToString([Browser.getScreenWidth(), Browser.getScreenHeight()]), | |
debug: true | |
} | |
}; | |
console.log(queryObj); | |
console.log('🦠🦠🦠'); | |
/* Change this to your bidder endpoint. */ | |
// var baseUrl = Browser.getProtocol() + '//someAdapterEndpoint.com/bid'; | |
// var baseUrl = 'https://bids.concert.io/bids/index'; | |
var baseUrl = 'http://localhost:8080/bids/index'; | |
/* ------------------------ Get consent information ------------------------- | |
* If you want to implement GDPR consent in your adapter, use the function | |
* ComplianceService.gdpr.getConsent() which will return an object. | |
* | |
* Here is what the values in that object mean: | |
* - applies: the boolean value indicating if the request is subject to | |
* GDPR regulations | |
* - consentString: the consent string developed by GDPR Consent Working | |
* Group under the auspices of IAB Europe | |
* | |
* The return object should look something like this: | |
* { | |
* applies: true, | |
* consentString: "BOQ7WlgOQ7WlgABABwAAABJOACgACAAQABA" | |
* } | |
* | |
* You can also determine whether or not the publisher has enabled privacy | |
* features in their wrapper by querying ComplianceService.isPrivacyEnabled(). | |
* | |
* This function will return a boolean, which indicates whether the wrapper's | |
* privacy features are on (true) or off (false). If they are off, the values | |
* returned from gdpr.getConsent() are safe defaults and no attempt has been | |
* made by the wrapper to contact a Consent Management Platform. | |
*/ | |
// var gdprStatus = ComplianceService.gdpr.getConsent(); | |
// var privacyEnabled = ComplianceService.isPrivacyEnabled(); | |
/* ---------------- Craft bid request using the above returnParcels --------- */ | |
/* ------- Put GDPR consent code here if you are implementing GDPR ---------- */ | |
/* -------------------------------------------------------------------------- */ | |
return { | |
url: baseUrl, | |
data: queryObj, | |
callbackId: callbackId, | |
networkParamOverrides: { | |
method: 'POST', | |
contentType: 'text/plain' | |
// contentType: 'application/json' | |
} | |
}; | |
} | |
/* ============================================================================= | |
* STEP 3 | Response callback | |
* ----------------------------------------------------------------------------- | |
* | |
* This generator is only necessary if the partner's endpoint has the ability | |
* to return an arbitrary ID that is sent to it. It should retrieve that ID from | |
* the response and save the response to adResponseStore keyed by that ID. | |
* | |
* If the endpoint does not have an appropriate field for this, set the profile's | |
* callback type to CallbackTypes.CALLBACK_NAME and omit this function. | |
*/ | |
function adResponseCallback(adResponse) { | |
console.log("😻😻😻😻😻😻😻"); | |
/* Get callbackId from adResponse here */ | |
var callbackId = 0; | |
__baseClass._adResponseStore[callbackId] = adResponse; | |
} | |
/* -------------------------------------------------------------------------- */ | |
/* Helpers | |
* ---------------------------------- */ | |
/* ============================================================================= | |
* STEP 5 | Rendering Pixel | |
* ----------------------------------------------------------------------------- | |
* | |
*/ | |
/** | |
* This function will render the pixel given. | |
* @param {string} pixelUrl Tracking pixel img url. | |
*/ | |
function __renderPixel(pixelUrl) { | |
console.log('😻😻😻😻😻😻😻'); | |
if (pixelUrl) { | |
Network.img({ | |
url: decodeURIComponent(pixelUrl), | |
method: 'GET' | |
}); | |
} | |
} | |
/** | |
* Parses and extracts demand from adResponse according to the adapter and then attaches it | |
* to the corresponding bid's returnParcel in the correct format using targeting keys. | |
* | |
* @param {string} sessionId The sessionId, used for stats and other events. | |
* | |
* @param {any} adResponse This is the bid response as returned from the bid request, that was either | |
* passed to a JSONP callback or simply sent back via AJAX. | |
* | |
* @param {object[]} returnParcels The array of original parcels, SAME array that was passed to | |
* generateRequestObj to signal which slots need demand. In this funciton, the demand needs to be | |
* attached to each one of the objects for which the demand was originally requested for. | |
*/ | |
function __parseResponse(sessionId, adResponse, returnParcels) { | |
console.log('🤙🤙🤙🤙🤙🤙 PARSE RESPONSE'); | |
console.log(sessionId); | |
console.log(adResponse); | |
console.log(returnParcels); | |
/* ============================================================================= | |
* STEP 4 | Parse & store demand response | |
* ----------------------------------------------------------------------------- | |
* | |
* Fill the below variables with information about the bid from the partner, using | |
* the adResponse variable that contains your module adResponse. | |
*/ | |
/* This an array of all the bids in your response that will be iterated over below. Each of | |
* these will be mapped back to a returnParcel object using some criteria explained below. | |
* The following variables will also be parsed and attached to that returnParcel object as | |
* returned demand. | |
* | |
* Use the adResponse variable to extract your bid information and insert it into the | |
* bids array. Each element in the bids array should represent a single bid and should | |
* match up to a single element from the returnParcel array. | |
* | |
*/ | |
/* ---------- Process adResponse and extract the bids into the bids array ------------ */ | |
var bids = adResponse.bids; | |
/* --------------------------------------------------------------------------------- */ | |
for (var j = 0; j < returnParcels.length; j++) { | |
var curReturnParcel = returnParcels[j]; | |
var headerStatsInfo = {}; | |
var htSlotId = curReturnParcel.htSlot.getId(); | |
headerStatsInfo[htSlotId] = {}; | |
headerStatsInfo[htSlotId][curReturnParcel.requestId] = [curReturnParcel.xSlotName]; | |
var curBid; | |
for (var i = 0; i < bids.length; i++) { | |
/** | |
* This section maps internal returnParcels and demand returned from the bid request. | |
* In order to match them correctly, they must be matched via some criteria. This | |
* is usually some sort of placements or inventory codes. Please replace the someCriteria | |
* key to a key that represents the placement in the configuration and in the bid responses. | |
*/ | |
/* ----------- Fill this out to find a matching bid for the current parcel ------------- */ | |
if (curReturnParcel.xSlotName === bids[i].bidId) { | |
curBid = bids[i]; | |
bids.splice(i, 1); | |
break; | |
} | |
} | |
/* No matching bid found so its a pass */ | |
if (!curBid) { | |
if (__profile.enabledAnalytics.requestTime) { | |
__baseClass._emitStatsEvent(sessionId, 'hs_slot_pass', headerStatsInfo); | |
} | |
curReturnParcel.pass = true; | |
continue; | |
} | |
/* ---------- Fill the bid variables with data from the bid response here. ------------ */ | |
/* Using the above variable, curBid, extract various information about the bid and assign it to | |
* these local variables */ | |
/* The bid price for the given slot */ | |
var bidPrice = Number(curBid.cpm); | |
/* The size of the given slot */ | |
var bidSize = [Number(curBid.width), Number(curBid.height)]; | |
/* The creative/adm for the given slot that will be rendered if is the winner. | |
* Please make sure the URL is decoded and ready to be document.written. | |
*/ | |
var bidCreative = curBid.ad; | |
/* The dealId if applicable for this slot. */ | |
var bidDealId = null; // curBid.creativeId; | |
/* Explicitly pass */ | |
var bidIsPass = bidPrice <= 0; | |
/* OPTIONAL: tracking pixel url to be fired AFTER rendering a winning creative. | |
* If firing a tracking pixel is not required or the pixel url is part of the adm, | |
* leave empty; | |
*/ | |
var pixelUrl = ''; | |
/* --------------------------------------------------------------------------------------- */ | |
curBid = null; | |
if (bidIsPass) { | |
//? if (DEBUG) { | |
Scribe.info(__profile.partnerId + ' returned pass for { id: ' + adResponse.id + ' }.'); | |
//? } | |
if (__profile.enabledAnalytics.requestTime) { | |
__baseClass._emitStatsEvent(sessionId, 'hs_slot_pass', headerStatsInfo); | |
} | |
curReturnParcel.pass = true; | |
continue; | |
} | |
if (__profile.enabledAnalytics.requestTime) { | |
__baseClass._emitStatsEvent(sessionId, 'hs_slot_bid', headerStatsInfo); | |
} | |
curReturnParcel.size = bidSize; | |
curReturnParcel.targetingType = 'slot'; | |
curReturnParcel.targeting = {}; | |
var targetingCpm = ''; | |
//? if (FEATURES.GPT_LINE_ITEMS) { | |
targetingCpm = __baseClass._bidTransformers.targeting.apply(bidPrice); | |
var sizeKey = Size.arrayToString(curReturnParcel.size); | |
if (bidDealId) { | |
curReturnParcel.targeting[__baseClass._configs.targetingKeys.pmid] = [sizeKey + '_' + bidDealId]; | |
curReturnParcel.targeting[__baseClass._configs.targetingKeys.pm] = [sizeKey + '_' + targetingCpm]; | |
} else { | |
curReturnParcel.targeting[__baseClass._configs.targetingKeys.om] = [sizeKey + '_' + targetingCpm]; | |
} | |
curReturnParcel.targeting[__baseClass._configs.targetingKeys.id] = [curReturnParcel.requestId]; | |
//? } | |
//? if (FEATURES.RETURN_CREATIVE) { | |
curReturnParcel.adm = bidCreative; | |
if (pixelUrl) { | |
curReturnParcel.winNotice = __renderPixel.bind(null, pixelUrl); | |
} | |
//? } | |
//? if (FEATURES.RETURN_PRICE) { | |
curReturnParcel.price = Number(__baseClass._bidTransformers.price.apply(bidPrice)); | |
//? } | |
var expiry = 0; | |
if (__profile.features.demandExpiry.enabled) { | |
expiry = __profile.features.demandExpiry.value + System.now(); | |
} | |
var pubKitAdId = RenderService.registerAd({ | |
sessionId: sessionId, | |
partnerId: __profile.partnerId, | |
adm: bidCreative, | |
requestId: curReturnParcel.requestId, | |
size: curReturnParcel.size, | |
price: targetingCpm, | |
dealId: bidDealId || null, | |
timeOfExpiry: expiry, | |
auxFn: __renderPixel, | |
auxArgs: [pixelUrl] | |
}); | |
console.log('🧼🧼🧼🧼'); | |
console.log(pubKitAdId); | |
//? if (FEATURES.INTERNAL_RENDER) { | |
curReturnParcel.targeting.pubKitAdId = pubKitAdId; | |
//? } | |
} | |
} | |
/* ===================================== | |
* Constructors | |
* ---------------------------------- */ | |
(function __constructor() { | |
ComplianceService = SpaceCamp.services.ComplianceService; | |
RenderService = SpaceCamp.services.RenderService; | |
/* ============================================================================= | |
* STEP 1 | Partner Configuration | |
* ----------------------------------------------------------------------------- | |
* | |
* Please fill out the below partner profile according to the steps in the README doc. | |
*/ | |
/* ---------- Please fill out this partner profile according to your module ------------ */ | |
__profile = { | |
partnerId: 'VroomHtb', | |
namespace: 'VroomHtb', | |
statsId: 'VRO', | |
version: '2.0.0', | |
targetingType: 'slot', | |
enabledAnalytics: { | |
requestTime: true | |
}, | |
features: { | |
demandExpiry: { | |
enabled: false, | |
value: 0 | |
}, | |
rateLimiting: { | |
enabled: false, | |
value: 0 | |
} | |
}, | |
/* Targeting keys for demand, should follow format ix_{statsId}_id */ | |
targetingKeys: { | |
id: 'ix_vro_id', | |
om: 'ix_vro_cpm', | |
pm: 'ix_vro_cpm', | |
pmid: 'ix_vro_dealid' | |
}, | |
/* The bid price unit (in cents) the endpoint returns, please refer to the readme for details */ | |
bidUnitInCents: 1, | |
lineItemType: Constants.LineItemTypes.ID_AND_SIZE, | |
callbackType: Partner.CallbackTypes.NONE, | |
architecture: Partner.Architectures.SRA, | |
requestType: Partner.RequestTypes.ANY | |
}; | |
/* --------------------------------------------------------------------------------------- */ | |
//? if (DEBUG) { | |
var results = ConfigValidators.partnerBaseConfig(configs) || PartnerSpecificValidator(configs); | |
if (results) { | |
throw Whoopsie('INVALID_CONFIG', results); | |
} | |
//? } | |
__baseClass = Partner(__profile, configs, null, { | |
parseResponse: __parseResponse, | |
generateRequestObj: __generateRequestObj, | |
adResponseCallback: adResponseCallback | |
}); | |
})(); | |
/* ===================================== | |
* Public Interface | |
* ---------------------------------- */ | |
var derivedClass = { | |
/* Class Information | |
* ---------------------------------- */ | |
//? if (DEBUG) { | |
__type__: 'VroomHtb', | |
//? } | |
//? if (TEST) { | |
__baseClass: __baseClass, | |
//? } | |
/* Data | |
* ---------------------------------- */ | |
//? if (TEST) { | |
profile: __profile, | |
//? } | |
/* Functions | |
* ---------------------------------- */ | |
//? if (TEST) { | |
parseResponse: __parseResponse, | |
generateRequestObj: __generateRequestObj, | |
adResponseCallback: adResponseCallback | |
//? } | |
}; | |
return Classify.derive(__baseClass, derivedClass); | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Exports ///////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////////// | |
module.exports = VroomHtb; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment