forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Prebid Analytics API Provides two new Prebid API methods to register analytics adapters and enable analytics tracking for any analytics module. * `pbjs.enableAnalytics()` is called once on the page after all analytics libraries have been loaded * `pbjs.registerAnalyticsAdapter` is available to register an adapter dynamically (optional) An analytics provider can be configured with these steps: 1. Add the analytics library to your page as described in the provider's documentation (see `integrationExamples/gpt/examples...` for Google Analytics.) 1. Add a call to `pbjs.enableAnalytics(analyticsAdapters)`. `analyticsAdapters` could look like: ``` pbjs.que.push(function () { pbjs.enableAnalytics([{ provider: 'ga', options: { global: 'ga', enableDistribution: false } }, { provider: 'example', options: { foo: 1234 } } ]); }); ``` 1. Create an analytics adapter to listen for Prebid events and call the analytics library (see `src/adapters/analytics/ga.js`) 1. Add the analytics adapter file name to the "analytics" array in `package.json`. * review notes: restore `enableAnalytics` method name, prevent duplicate calls to adapter.enableAnalytics * set analytics example libraries url to fqdn localhost:9999 * call _enqueue from containing scope * fix bug `this` undefined * Add `analyticsType` as 'library' or 'endpoint' and provide an `ajax` module to use when sending event payloads to an endpoint Configure cross-repo analytics builds * Consolidate logic * Use in devbuild task * Revert default param to work in node v5 * Read analytic sources before prebid source * Update to address code notes * Load adapters only if defined in array
- Loading branch information
1 parent
8fee8d7
commit e122486
Showing
23 changed files
with
763 additions
and
117 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
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
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
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 |
---|---|---|
|
@@ -117,7 +117,6 @@ | |
timeout: 1000 | ||
*/ | ||
}); | ||
|
||
}); | ||
|
||
</script> | ||
|
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,40 @@ | ||
'use strict'; | ||
|
||
const fs = require('fs'); | ||
const blockLoader = require('block-loader'); | ||
let analyticsAdapters = require('../package.json').analytics; | ||
|
||
var options = { | ||
start: '/** INSERT ANALYTICS - DO NOT EDIT OR REMOVE */', | ||
end: '/** END INSERT ANALYTICS */', | ||
process: function insertAnalytics() { | ||
// read directory for analytics adapter file names, map the file names to String.replace, | ||
// use a regex to remove file extensions, then return the array of adapter names | ||
const files = fs.readdirSync('src/adapters/analytics') | ||
.map(file => file.replace(/\.[^/.]+$/, '')); | ||
|
||
let adapters = analyticsAdapters.map(adapter => adapter.length ? adapter : Object.keys(adapter)[0]); | ||
|
||
let inserts = adapters.filter(adapter => { | ||
if (files.includes(adapter)) { | ||
return adapter; | ||
} else { | ||
console.log(`Prebid Warning: no adapter found for ${adapter}, continuing.`); | ||
} | ||
}); | ||
|
||
// if no matching adapters and no adapter files found, exit | ||
if (!inserts || !inserts.length) { | ||
return null; | ||
} | ||
|
||
// return the javascript strings to insert into adaptermanager.js | ||
return inserts.map((adapter) => { | ||
return `var ${adapter} = require('./adapters/analytics/${adapter}.js').default | ||
|| require('./adapters/analytics/${adapter}.js'); | ||
exports.registerAnalyticsAdapter({ adapter: ${adapter}, code: '${adapter}' });\n`; | ||
}).join(''); | ||
} | ||
}; | ||
|
||
module.exports = blockLoader(options); |
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
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
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,119 @@ | ||
import CONSTANTS from 'src/constants.json'; | ||
import { loadScript } from 'src/adloader'; | ||
import { ajax } from 'src/ajax'; | ||
|
||
const events = require('src/events'); | ||
const utils = require('../../utils'); | ||
|
||
const BID_REQUESTED = CONSTANTS.EVENTS.BID_REQUESTED; | ||
const BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; | ||
const BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; | ||
const BID_WON = CONSTANTS.EVENTS.BID_WON; | ||
const BID_ADJUSTMENT = CONSTANTS.EVENTS.BID_ADJUSTMENT; | ||
|
||
const LIBRARY = 'library'; | ||
const ENDPOINT = 'endpoint'; | ||
const BUNDLE = 'bundle'; | ||
|
||
var _timedOutBidders = []; | ||
|
||
export default function AnalyticsAdapter({ url, analyticsType, global, handler }) { | ||
var _queue = []; | ||
var _eventCount = 0; | ||
var _enableCheck = true; | ||
|
||
if (analyticsType === LIBRARY) { | ||
loadScript(url, _emptyQueue); | ||
} | ||
|
||
if (analyticsType === ENDPOINT || BUNDLE) { | ||
_emptyQueue(); | ||
} | ||
|
||
return { | ||
track: _track, | ||
enqueue: _enqueue, | ||
enableAnalytics: _enable, | ||
getAdapterType: () => analyticsType, | ||
getGlobal: () => global, | ||
getHandler: () => handler, | ||
getUrl: () => url | ||
}; | ||
|
||
function _track({ eventType, args }) { | ||
if (this.getAdapterType() === LIBRARY || BUNDLE) { | ||
window[global](handler, eventType, args); | ||
} | ||
|
||
if (this.getAdapterType() === ENDPOINT) { | ||
_callEndpoint(...arguments); | ||
} | ||
} | ||
|
||
function _callEndpoint({ eventType, args, callback }) { | ||
ajax(url, callback, JSON.stringify({ eventType, args })); | ||
} | ||
|
||
function _enqueue({ eventType, args }) { | ||
const _this = this; | ||
|
||
if (global && window[global] && eventType && args) { | ||
this.track({ eventType, args }); | ||
} else { | ||
_queue.push(function () { | ||
_eventCount++; | ||
_this.track({ eventType, args }); | ||
}); | ||
} | ||
} | ||
|
||
function _enable() { | ||
var _this = this; | ||
|
||
//first send all events fired before enableAnalytics called | ||
events.getEvents().forEach(event => { | ||
if (!event) { | ||
return; | ||
} | ||
|
||
const { eventType, args } = event; | ||
|
||
if (eventType === BID_TIMEOUT) { | ||
_timedOutBidders = args.bidderCode; | ||
} else { | ||
_enqueue.call(_this, { eventType, args }); | ||
} | ||
}); | ||
|
||
//Next register event listeners to send data immediately | ||
|
||
//bidRequests | ||
events.on(BID_REQUESTED, args => this.enqueue({ eventType: BID_REQUESTED, args })); | ||
events.on(BID_RESPONSE, args => this.enqueue({ eventType: BID_RESPONSE, args })); | ||
events.on(BID_TIMEOUT, args => this.enqueue({ eventType: BID_TIMEOUT, args })); | ||
events.on(BID_WON, args => this.enqueue({ eventType: BID_WON, args })); | ||
events.on(BID_ADJUSTMENT, args => this.enqueue({ eventType: BID_ADJUSTMENT, args })); | ||
|
||
// finally set this function to return log message, prevents multiple adapter listeners | ||
this.enableAnalytics = function _enable() { | ||
return utils.logMessage(`Analytics adapter for "${global}" already enabled, unnecessary call to \`enableAnalytics\`.`); | ||
}; | ||
} | ||
|
||
function _emptyQueue() { | ||
if (_enableCheck) { | ||
for (var i = 0; i < _queue.length; i++) { | ||
_queue[i](); | ||
} | ||
|
||
//override push to execute the command immediately from now on | ||
_queue.push = function (fn) { | ||
fn(); | ||
}; | ||
|
||
_enableCheck = false; | ||
} | ||
|
||
utils.logMessage(`event count sent to ${global}: ${_eventCount}`); | ||
} | ||
} |
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,12 @@ | ||
/** | ||
* appnexus.js - AppNexus Prebid Analytics Adapter | ||
*/ | ||
|
||
import adapter from 'AnalyticsAdapter'; | ||
|
||
export default adapter({ | ||
global: 'AppNexusPrebidAnalytics', | ||
handler: 'on', | ||
analyticsType: 'bundle' | ||
}); | ||
|
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,14 @@ | ||
/** | ||
* example.js - analytics adapter for Example Analytics Library example | ||
*/ | ||
|
||
import adapter from 'AnalyticsAdapter'; | ||
|
||
export default adapter( | ||
{ | ||
url: 'http://localhost:9999/src/adapters/analytics/libraries/example.js', | ||
global: 'ExampleAnalyticsGlobalObject', | ||
handler: 'on', | ||
analyticsType: 'library' | ||
} | ||
); |
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,25 @@ | ||
import { ajax } from 'src/ajax'; | ||
|
||
/** | ||
* example2.js - analytics adapter for Example2 Analytics Endpoint example | ||
*/ | ||
|
||
import adapter from 'AnalyticsAdapter'; | ||
const utils = require('../../utils'); | ||
|
||
const url = 'https://httpbin.org/post'; | ||
const analyticsType = 'endpoint'; | ||
|
||
export default utils.extend(adapter( | ||
{ | ||
url, | ||
analyticsType | ||
} | ||
), | ||
{ | ||
// Override AnalyticsAdapter functions by supplying custom methods | ||
track({ eventType, args }) { | ||
console.log('track function override for Example2 Analytics'); | ||
ajax(url, (result) => console.log('Analytics Endpoint Example2: result = ' + result), JSON.stringify({ eventType, args })); | ||
} | ||
}); |
Oops, something went wrong.