-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New version of Konduit Accelerate module (#5164)
* Adding Konduit module * Removed superfluous arguments passed to obtainVastUrl function * Removed superfluous arguments passed to obtainVastUrl function. * Build trigger (empty commit) * Module documentation updated according to the comments * Logic in obtainVastUrl function updated according to the review comment. * Removed hook, enabled eslint * Merged recent prebid changes * New method is introduced to process a bid and return dynamic CPM data * New Konduit Analytics adapter responsible for client auction stats collection * Updated konduit analytics adapter .md file * Fixed linter issue with more than 1 blank line used * Use '$prebid.version$' instead of the $$PREBID_GLOBAL$$.version * Updated unit tests Co-authored-by: Max Shevchenko <max.shevchenko@sigma.software> Co-authored-by: Alexander Kislitsyn <alexander.kislitsyn@sigmaukraine.com>
- Loading branch information
1 parent
9c8aa04
commit 14e4a94
Showing
6 changed files
with
740 additions
and
126 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
import { ajax } from '../src/ajax.js'; | ||
import adapter from '../src/AnalyticsAdapter.js'; | ||
import adapterManager from '../src/adapterManager.js'; | ||
import * as utils from '../src/utils.js'; | ||
import { targeting } from '../src/targeting.js'; | ||
import { config } from '../src/config.js'; | ||
import CONSTANTS from '../src/constants.json'; | ||
|
||
const TRACKER_HOST = 'tracker.konduit.me'; | ||
|
||
const analyticsType = 'endpoint'; | ||
|
||
const eventDataComposerMap = { | ||
[CONSTANTS.EVENTS.AUCTION_INIT]: obtainAuctionInfo, | ||
[CONSTANTS.EVENTS.AUCTION_END]: obtainAuctionInfo, | ||
[CONSTANTS.EVENTS.BID_REQUESTED]: obtainBidRequestsInfo, | ||
[CONSTANTS.EVENTS.BID_TIMEOUT]: obtainBidTimeoutInfo, | ||
[CONSTANTS.EVENTS.BID_RESPONSE]: obtainBidResponseInfo, | ||
[CONSTANTS.EVENTS.BID_WON]: obtainWinnerBidInfo, | ||
[CONSTANTS.EVENTS.NO_BID]: obtainNoBidInfo, | ||
}; | ||
|
||
// This function is copy from prebid core | ||
function formatQS(query) { | ||
return Object | ||
.keys(query) | ||
.map(k => Array.isArray(query[k]) | ||
? query[k].map(v => `${k}[]=${v}`).join('&') | ||
: `${k}=${query[k]}`) | ||
.join('&'); | ||
} | ||
|
||
// This function is copy from prebid core | ||
function buildUrl(obj) { | ||
return (obj.protocol || 'http') + '://' + | ||
(obj.host || | ||
obj.hostname + (obj.port ? `:${obj.port}` : '')) + | ||
(obj.pathname || '') + | ||
(obj.search ? `?${formatQS(obj.search || '')}` : '') + | ||
(obj.hash ? `#${obj.hash}` : ''); | ||
} | ||
|
||
const getWinnerBidFromAggregatedEvents = () => { | ||
return konduitAnalyticsAdapter.context.aggregatedEvents | ||
.filter(evt => evt.eventType === CONSTANTS.EVENTS.BID_WON)[0]; | ||
}; | ||
|
||
const isWinnerBidDetected = () => { | ||
return !!getWinnerBidFromAggregatedEvents(); | ||
}; | ||
const isWinnerBidExist = () => { | ||
return !!targeting.getWinningBids()[0]; | ||
}; | ||
|
||
const konduitAnalyticsAdapter = Object.assign( | ||
adapter({ analyticsType }), | ||
{ | ||
track ({ eventType, args }) { | ||
if (CONSTANTS.EVENTS.AUCTION_INIT === eventType) { | ||
konduitAnalyticsAdapter.context.aggregatedEvents.splice(0); | ||
} | ||
|
||
if (eventDataComposerMap[eventType]) { | ||
konduitAnalyticsAdapter.context.aggregatedEvents.push({ | ||
eventType, | ||
data: eventDataComposerMap[eventType](args), | ||
}); | ||
} | ||
|
||
if (eventType === CONSTANTS.EVENTS.AUCTION_END) { | ||
if (!isWinnerBidDetected() && isWinnerBidExist()) { | ||
const bidWonData = eventDataComposerMap[CONSTANTS.EVENTS.BID_WON](targeting.getWinningBids()[0]); | ||
|
||
konduitAnalyticsAdapter.context.aggregatedEvents.push({ | ||
eventType: CONSTANTS.EVENTS.BID_WON, | ||
data: bidWonData, | ||
}); | ||
} | ||
sendRequest({ method: 'POST', path: '/analytics-initial-event', payload: composeRequestPayload() }); | ||
} | ||
} | ||
} | ||
); | ||
|
||
function obtainBidTimeoutInfo (args) { | ||
return args.map(item => item.bidder).filter(utils.uniques); | ||
} | ||
|
||
function obtainAuctionInfo (auction) { | ||
return { | ||
auctionId: auction.auctionId, | ||
timestamp: auction.timestamp, | ||
auctionEnd: auction.auctionEnd, | ||
auctionStatus: auction.auctionStatus, | ||
adUnitCodes: auction.adUnitCodes, | ||
labels: auction.labels, | ||
timeout: auction.timeout | ||
}; | ||
} | ||
|
||
function obtainBidRequestsInfo (bidRequests) { | ||
return { | ||
bidderCode: bidRequests.bidderCode, | ||
time: bidRequests.start, | ||
bids: bidRequests.bids.map(function (bid) { | ||
return { | ||
transactionId: bid.transactionId, | ||
adUnitCode: bid.adUnitCode, | ||
bidId: bid.bidId, | ||
startTime: bid.startTime, | ||
sizes: utils.parseSizesInput(bid.sizes).toString(), | ||
params: bid.params | ||
}; | ||
}), | ||
}; | ||
} | ||
|
||
function obtainBidResponseInfo (bidResponse) { | ||
return { | ||
bidderCode: bidResponse.bidder, | ||
transactionId: bidResponse.transactionId, | ||
adUnitCode: bidResponse.adUnitCode, | ||
statusMessage: bidResponse.statusMessage, | ||
mediaType: bidResponse.mediaType, | ||
renderedSize: bidResponse.size, | ||
cpm: bidResponse.cpm, | ||
currency: bidResponse.currency, | ||
netRevenue: bidResponse.netRevenue, | ||
timeToRespond: bidResponse.timeToRespond, | ||
bidId: bidResponse.bidId, | ||
requestId: bidResponse.requestId, | ||
creativeId: bidResponse.creativeId | ||
}; | ||
} | ||
|
||
function obtainNoBidInfo (bidResponse) { | ||
return { | ||
bidderCode: bidResponse.bidder, | ||
transactionId: bidResponse.transactionId, | ||
adUnitCode: bidResponse.adUnitCode, | ||
bidId: bidResponse.bidId, | ||
}; | ||
} | ||
|
||
function obtainWinnerBidInfo (bidResponse) { | ||
return { | ||
adId: bidResponse.adId, | ||
bidderCode: bidResponse.bidder, | ||
adUnitCode: bidResponse.adUnitCode, | ||
statusMessage: bidResponse.statusMessage, | ||
mediaType: bidResponse.mediaType, | ||
renderedSize: bidResponse.size, | ||
cpm: bidResponse.cpm, | ||
currency: bidResponse.currency, | ||
netRevenue: bidResponse.netRevenue, | ||
timeToRespond: bidResponse.timeToRespond, | ||
bidId: bidResponse.requestId, | ||
dealId: bidResponse.dealId, | ||
status: bidResponse.status, | ||
creativeId: bidResponse.creativeId | ||
}; | ||
} | ||
|
||
function composeRequestPayload () { | ||
const konduitId = config.getConfig('konduit.konduitId'); | ||
const { width, height } = window.screen; | ||
|
||
return { | ||
konduitId, | ||
prebidVersion: '$prebid.version$', | ||
environment: { | ||
screen: { width, height }, | ||
language: navigator.language, | ||
}, | ||
events: konduitAnalyticsAdapter.context.aggregatedEvents, | ||
}; | ||
} | ||
|
||
function sendRequest ({ host = TRACKER_HOST, method, path, payload }) { | ||
const formattedUrlOptions = { | ||
protocol: 'https', | ||
hostname: host, | ||
pathname: path, | ||
}; | ||
if (method === 'GET') { | ||
formattedUrlOptions.search = payload; | ||
} | ||
|
||
let konduitAnalyticsRequestUrl = buildUrl(formattedUrlOptions); | ||
|
||
ajax( | ||
konduitAnalyticsRequestUrl, | ||
undefined, | ||
method === 'POST' ? JSON.stringify(payload) : null, | ||
{ | ||
contentType: 'application/json', | ||
method, | ||
withCredentials: true | ||
} | ||
); | ||
} | ||
|
||
konduitAnalyticsAdapter.originEnableAnalytics = konduitAnalyticsAdapter.enableAnalytics; | ||
|
||
konduitAnalyticsAdapter.enableAnalytics = function (analyticsConfig) { | ||
const konduitId = config.getConfig('konduit.konduitId'); | ||
|
||
if (!konduitId) { | ||
utils.logError('A konduitId in config is required to use konduitAnalyticsAdapter'); | ||
return; | ||
} | ||
|
||
konduitAnalyticsAdapter.context = { | ||
aggregatedEvents: [], | ||
}; | ||
|
||
konduitAnalyticsAdapter.originEnableAnalytics(analyticsConfig); | ||
}; | ||
|
||
adapterManager.registerAnalyticsAdapter({ | ||
adapter: konduitAnalyticsAdapter, | ||
code: 'konduit' | ||
}); | ||
|
||
export default konduitAnalyticsAdapter; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Overview | ||
| ||
``` | ||
Module Name: Konduit Analytics Adapter | ||
Module Type: Analytics Adapter | ||
Maintainer: support@konduit.me | ||
``` | ||
| ||
| ||
# Description | ||
| ||
Konduit Analytics adapter pushes Prebid events into Konduit platform, which is then organizes the data and presents it to a client in different insightful views. | ||
| ||
For more information, visit the [official Konduit website](https://konduitvideo.com/). | ||
| ||
| ||
# Usage | ||
| ||
Konduit Analytics can be enabled with a standard `enableAnalytics` call. | ||
Note it is also important to provide a valid Konduit identifier as a config parameter. | ||
| ||
```javascript | ||
pbjs.setConfig({ | ||
konduit: { | ||
konduitId: your_konduit_id, | ||
} | ||
}); | ||
| ||
pbjs.enableAnalytics({ | ||
provider: 'konduit' | ||
}) | ||
``` |
Oops, something went wrong.