Skip to content

Commit

Permalink
feat(Analytics): Multiple analytics handlers support
Browse files Browse the repository at this point in the history
  • Loading branch information
hristoterezov committed Nov 16, 2016
1 parent 6d1f42b commit dc0a7e7
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 30 deletions.
4 changes: 3 additions & 1 deletion analytics.js
Expand Up @@ -27,5 +27,7 @@
action + '.' + data.browserName, label, value);
};

ctx.Analytics = Analytics;
if(typeof ctx.analyticsHandlers === "undefined")
ctx.analyticsHandlers = [];
ctx.analyticsHandlers.push(Analytics);
}(window));
30 changes: 7 additions & 23 deletions conference.js
Expand Up @@ -13,6 +13,8 @@ import {reportError} from './modules/util/helpers';
import UIEvents from './service/UI/UIEvents';
import UIUtil from './modules/UI/util/UIUtil';

import analytics from './modules/analytics/analytics';

const ConnectionEvents = JitsiMeetJS.events.connection;
const ConnectionErrors = JitsiMeetJS.errors.connection;

Expand Down Expand Up @@ -438,26 +440,6 @@ function disconnect() {
return Promise.resolve();
}

/**
* Set permanent properties to analytics.
* NOTE: Has to be used after JitsiMeetJS.init. Otherwise analytics will be
* null.
*/
function setAnalyticsPermanentProperties() {
let permanentProperties = {
userAgent: navigator.userAgent,
roomName: APP.conference.roomName
};
let {server, group} = APP.tokenData;
if(server) {
permanentProperties.server = server;
}
if(group) {
permanentProperties.group = group;
}
JitsiMeetJS.analytics.addPermanentProperties(permanentProperties);
}

export default {
isModerator: false,
audioMuted: false,
Expand Down Expand Up @@ -504,9 +486,11 @@ export default {
};
}

return JitsiMeetJS.init(config)
.then(() => {
setAnalyticsPermanentProperties();
return JitsiMeetJS.init(
Object.assign(
{enableAnalyticsLogging: analytics.isEnabled()}, config)
).then(() => {
analytics.init();
return createInitialLocalTracksAndConnect(options.roomName);
}).then(([tracks, con]) => {
console.log('initialized with %s local tracks', tracks.length);
Expand Down
128 changes: 128 additions & 0 deletions modules/analytics/analytics.js
@@ -0,0 +1,128 @@
/* global JitsiMeetJS, config, APP */
/**
* Load the integration of a third-party analytics API such as Google
* Analytics. Since we cannot guarantee the quality of the third-party service
* (e.g. their server may take noticeably long time to respond), it is in our
* best interest (in the sense that the intergration of the analytics API is
* important to us but not enough to allow it to prevent people from joining
* a conference) to download the API asynchronously. Additionally, Google
* Analytics will download its implementation asynchronously anyway so it makes
* sense to append the loading on our side rather than prepend it.
* @param {string} url the url to be loaded
* @returns {Promise} resolved with no arguments when the script is loaded and
* rejected with the error from JitsiMeetJS.ScriptUtil.loadScript method
*/
function loadScript(url) {
return new Promise((resolve, reject) =>
JitsiMeetJS.util.ScriptUtil.loadScript(
url,
/* async */ true,
/* prepend */ false,
/* relativeURL */ false,
/* loadCallback */ () => resolve(),
/* errorCallback */ error => reject(error)));
}

/**
* Handles the initialization of analytics.
*/
class Analytics {
constructor() {
this._scriptURLs = Array.isArray(config.analyticsScriptUrls)
? config.analyticsScriptUrls : [];
this._enabled = !!this._scriptURLs.length
&& !config.disableThirdPartyRequests;
window.analyticsHandlers = [];
const machineId = JitsiMeetJS.getMachineId();
this._handlerConstructorOptions = {
product: "lib-jitsi-meet",
version: JitsiMeetJS.version,
session: machineId,
user: "uid-" + machineId
};
}

/**
* Returns whether analytics is enabled or not.
* @returns {boolean} whether analytics is enabled or not.
*/
isEnabled() {
return this._enabled;
}

/**
* Tries to load the scripts for the analytics handlers.
* @returns {Promise} resolves with the handlers that have been
* successfully loaded and rejects if there are no handlers loaded or the
* analytics is disabled.
*/
_loadHandlers() {
if(!this.isEnabled()) {
return Promise.reject(new Error("Analytics is disabled!"));
}
let handlersPromises = [];
this._scriptURLs.forEach(url =>
handlersPromises.push(
loadScript(url).then(
() => {
return {type: "success"};
},
error => {
return {type: "error", error, url};
}))
);
return new Promise((resolve, reject) =>
{
Promise.all(handlersPromises).then(values => {
values.forEach(el => {
if(el.type === "error") {
console.log("Fialed to load " + el.url);
console.error(el.error);
}
});

if(window.analyticsHandlers.length === 0) {
reject(new Error("No analytics handlers available"));
} else {
let handlerInstances = [];
window.analyticsHandlers.forEach(
Handler => handlerInstances.push(
new Handler(this._handlerConstructorOptions)));
resolve(handlerInstances);
}
});
});
}

/**
* Loads the analytics scripts and inits JitsiMeetJS.analytics by setting
* permanent properties and setting the handlers from the loaded scripts.
* NOTE: Has to be used after JitsiMeetJS.init. Otherwise analytics will be
* null.
*/
init() {
let analytics = JitsiMeetJS.analytics;
if(!this.isEnabled() || !analytics)
return;

this._loadHandlers()
.then(handlers => {
let permanentProperties = {
userAgent: navigator.userAgent,
roomName: APP.conference.roomName
};
let {server, group} = APP.tokenData;
if(server) {
permanentProperties.server = server;
}
if(group) {
permanentProperties.group = group;
}
analytics.addPermanentProperties(permanentProperties);
analytics.setAnalyticsHandlers(handlers);
}, error => analytics.dispose() && console.error(error));

}
}

export default new Analytics();
2 changes: 1 addition & 1 deletion modules/config/URLProcessor.js
Expand Up @@ -38,7 +38,7 @@ var URLProcessor = {
confKey = key.substr("config.".length);

// prevent passing some parameters which can inject scripts
if (confKey === 'analyticsScriptUrl'
if (confKey === 'analyticsScriptUrls'
|| confKey === 'callStatsCustomScriptUrl')
continue;

Expand Down
5 changes: 0 additions & 5 deletions modules/settings/Settings.js
Expand Up @@ -9,11 +9,6 @@ function generateUniqueId() {
return _p8() + _p8() + _p8() + _p8();
}

if (!jitsiLocalStorage.getItem("jitsiMeetId")) {
jitsiLocalStorage.setItem("jitsiMeetId",generateUniqueId());
console.log("generated id", jitsiLocalStorage.getItem("jitsiMeetId"));
}

let avatarUrl = '';

let email = UIUtil.unescapeHtml(jitsiLocalStorage.getItem("email") || '');
Expand Down

0 comments on commit dc0a7e7

Please sign in to comment.