2018-01-03 21:24:07 +00:00
|
|
|
/* global ga */
|
|
|
|
|
|
|
|
(function(ctx) {
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
*/
|
2018-02-12 19:36:10 +00:00
|
|
|
function Analytics(options) {
|
2018-01-03 21:24:07 +00:00
|
|
|
/* eslint-disable */
|
|
|
|
|
2018-02-12 19:36:10 +00:00
|
|
|
if (!options.googleAnalyticsTrackingId) {
|
|
|
|
console.log(
|
|
|
|
'Failed to initialize Google Analytics handler, no tracking ID');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-03 21:24:07 +00:00
|
|
|
/**
|
|
|
|
* Google Analytics
|
2018-02-12 19:36:10 +00:00
|
|
|
* TODO: Keep this local, there's no need to add it to window.
|
2018-01-03 21:24:07 +00:00
|
|
|
*/
|
|
|
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
|
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
|
|
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
2018-05-11 15:32:02 +00:00
|
|
|
ga('create', options.googleAnalyticsTrackingId, 'auto');
|
2018-01-03 21:24:07 +00:00
|
|
|
ga('send', 'pageview');
|
|
|
|
|
|
|
|
/* eslint-enable */
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts the integer to use for a Google Analytics event's value field
|
|
|
|
* from a lib-jitsi-meet analytics event.
|
|
|
|
* @param {Object} event - The lib-jitsi-meet analytics event.
|
|
|
|
* @returns {Object} - The integer to use for the 'value' of a Google
|
|
|
|
* Analytics event.
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Analytics.prototype._extractAction = function(event) {
|
|
|
|
// Page events have a single 'name' field.
|
|
|
|
if (event.type === 'page') {
|
|
|
|
return event.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// All other events have action, actionSubject, and source fields. All
|
|
|
|
// three fields are required, and the often jitsi-meet and
|
|
|
|
// lib-jitsi-meet use the same value when separate values are not
|
|
|
|
// necessary (i.e. event.action == event.actionSubject).
|
|
|
|
// Here we concatenate these three fields, but avoid adding the same
|
|
|
|
// value twice, because it would only make the GA event's action harder
|
|
|
|
// to read.
|
|
|
|
let action = event.action;
|
|
|
|
|
|
|
|
if (event.actionSubject && event.actionSubject !== event.action) {
|
|
|
|
// Intentionally use string concatenation as analytics needs to
|
|
|
|
// work on IE but this file does not go through babel. For some
|
|
|
|
// reason disabling this globally for the file does not have an
|
|
|
|
// effect.
|
|
|
|
// eslint-disable-next-line prefer-template
|
|
|
|
action = event.actionSubject + '.' + action;
|
|
|
|
}
|
|
|
|
if (event.source && event.source !== event.action
|
|
|
|
&& event.source !== event.action) {
|
|
|
|
// eslint-disable-next-line prefer-template
|
|
|
|
action = event.source + '.' + action;
|
|
|
|
}
|
|
|
|
|
|
|
|
return action;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts the integer to use for a Google Analytics event's value field
|
|
|
|
* from a lib-jitsi-meet analytics event.
|
|
|
|
* @param {Object} event - The lib-jitsi-meet analytics event.
|
|
|
|
* @returns {Object} - The integer to use for the 'value' of a Google
|
|
|
|
* Analytics event, or NaN if the lib-jitsi-meet event doesn't contain a
|
|
|
|
* suitable value.
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Analytics.prototype._extractValue = function(event) {
|
|
|
|
let value = event && event.attributes && event.attributes.value;
|
|
|
|
|
|
|
|
// Try to extract an integer from the "value" attribute.
|
|
|
|
value = Math.round(parseFloat(value));
|
|
|
|
|
|
|
|
return value;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Extracts the string to use for a Google Analytics event's label field
|
|
|
|
* from a lib-jitsi-meet analytics event.
|
|
|
|
* @param {Object} event - The lib-jitsi-meet analytics event.
|
|
|
|
* @returns {string} - The string to use for the 'label' of a Google
|
|
|
|
* Analytics event.
|
|
|
|
* @private
|
|
|
|
*/
|
|
|
|
Analytics.prototype._extractLabel = function(event) {
|
|
|
|
let label = '';
|
|
|
|
|
|
|
|
// The label field is limited to 500B. We will concatenate all
|
|
|
|
// attributes of the event, except the user agent because it may be
|
|
|
|
// lengthy and is probably included from elsewhere.
|
|
|
|
for (const property in event.attributes) {
|
|
|
|
if (property !== 'permanent_user_agent'
|
2018-02-12 20:00:15 +00:00
|
|
|
&& property !== 'permanent_callstats_name'
|
2018-01-03 21:24:07 +00:00
|
|
|
&& event.attributes.hasOwnProperty(property)) {
|
|
|
|
// eslint-disable-next-line prefer-template
|
|
|
|
label += property + '=' + event.attributes[property] + '&';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (label.length > 0) {
|
|
|
|
label = label.slice(0, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return label;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is the entry point of the API. The function sends an event to
|
|
|
|
* google analytics. The format of the event is described in
|
|
|
|
* AnalyticsAdapter in lib-jitsi-meet.
|
|
|
|
* @param {Object} event - the event in the format specified by
|
|
|
|
* lib-jitsi-meet.
|
|
|
|
*/
|
|
|
|
Analytics.prototype.sendEvent = function(event) {
|
2018-02-12 19:36:10 +00:00
|
|
|
if (!event || !ga) {
|
2018-01-03 21:24:07 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-22 20:12:43 +00:00
|
|
|
const ignoredEvents
|
|
|
|
= [ 'e2e_rtt', 'rtp.stats', 'rtt.by.region', 'available.device',
|
|
|
|
'stream.switch.delay', 'ice.state.changed', 'ice.duration' ];
|
|
|
|
|
|
|
|
// Temporary removing some of the events that are too noisy.
|
|
|
|
if (ignoredEvents.indexOf(event.action) !== -1) {
|
2018-09-25 16:00:46 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-01-03 21:24:07 +00:00
|
|
|
const gaEvent = {
|
|
|
|
'eventCategory': 'jitsi-meet',
|
|
|
|
'eventAction': this._extractAction(event),
|
|
|
|
'eventLabel': this._extractLabel(event)
|
|
|
|
};
|
|
|
|
const value = this._extractValue(event);
|
|
|
|
|
|
|
|
if (!isNaN(value)) {
|
|
|
|
gaEvent.eventValue = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
ga('send', 'event', gaEvent);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (typeof ctx.JitsiMeetJS === 'undefined') {
|
|
|
|
ctx.JitsiMeetJS = {};
|
|
|
|
}
|
|
|
|
if (typeof ctx.JitsiMeetJS.app === 'undefined') {
|
|
|
|
ctx.JitsiMeetJS.app = {};
|
|
|
|
}
|
|
|
|
if (typeof ctx.JitsiMeetJS.app.analyticsHandlers === 'undefined') {
|
|
|
|
ctx.JitsiMeetJS.app.analyticsHandlers = [];
|
|
|
|
}
|
|
|
|
ctx.JitsiMeetJS.app.analyticsHandlers.push(Analytics);
|
|
|
|
})(window);
|
|
|
|
/* eslint-enable prefer-template */
|