diff --git a/src/Analytics.js b/src/Analytics.js index f33138bc95..a660a214c7 100644 --- a/src/Analytics.js +++ b/src/Analytics.js @@ -15,6 +15,7 @@ */ import MatrixClientPeg from './MatrixClientPeg'; +import SdkConfig from './SdkConfig'; function redact(str) { return str.replace(/#\/(room|user)\/(.+)/, "#/$1/"); @@ -23,34 +24,78 @@ function redact(str) { class Analytics { constructor() { this.tracker = null; + this.disabled = true; } - set(tracker) { - this.tracker = tracker; + /** + * Enable Analytics if initialized but disabled + * otherwise try and initalize, no-op if piwik config missing + */ + enable() { + if (this.tracker || this._init()) { + this.disabled = false; + } + } + /** + * Disable Analytics calls, will not fully unload Piwik until a refresh, + * but this is second best, Piwik should not pull anything implicitly. + */ + disable() { + this.disabled = true; + } + + _init() { + const config = SdkConfig.get(); + if (!config || !config.piwik || !config.piwik.url || !config.piwik.siteId) return; + + const url = config.piwik.url; + const siteId = config.piwik.siteId; + const self = this; + + (function() { + const g = document.createElement('script'); + const s = document.getElementsByTagName('script')[0]; + g.type='text/javascript'; g.async=true; g.defer=true; g.src=url+'piwik.js'; + + g.onload = function() { + const tracker = window.Piwik.getTracker(url+'piwik.php', siteId); + console.log('Initialised anonymous analytics'); + self._set(tracker); + }; + + s.parentNode.insertBefore(g, s); + })(); + + return true; + } + + _set(tracker) { + this.tracker = tracker; + this.tracker.discardHashTag(false); this.tracker.enableHeartBeatTimer(); this.tracker.enableLinkTracking(true); } async trackPageChange() { - if (!this.tracker) return; + if (this.disabled) return; this.tracker.setCustomUrl(redact(window.location.href)); this.tracker.trackPageView(); } async trackEvent(category, action, name) { - if (!this.tracker) return; + if (this.disabled) return; this.tracker.trackEvent(category, action, name); } async logout() { - if (!this.tracker) return; + if (this.disabled) return; this.tracker.deleteCookies(); } async login() { // not used currently const cli = MatrixClientPeg.get(); - if (!this.tracker || !cli) return; + if (this.disabled || !cli) return; this.tracker.setUserId(`@${cli.getUserIdLocalpart()}:${cli.getDomain()}`); } diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index 7cbc4d3ea7..eb52443a55 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -21,6 +21,7 @@ import React from 'react'; import Matrix from "matrix-js-sdk"; import Analytics from "../../Analytics"; +import UserSettingsStore from '../../UserSettingsStore'; import MatrixClientPeg from "../../MatrixClientPeg"; import PlatformPeg from "../../PlatformPeg"; import SdkConfig from "../../SdkConfig"; @@ -190,6 +191,8 @@ module.exports = React.createClass({ componentWillMount: function() { SdkConfig.put(this.props.config); + if (!UserSettingsStore.getLocalSetting('analyticsOptOut', false)) Analytics.enable(); + // Used by _viewRoom before getting state from sync this.firstSyncComplete = false; this.firstSyncPromise = q.defer();