diff --git a/src/background.js b/src/background.js index 93bff0ec..2df4ac32 100644 --- a/src/background.js +++ b/src/background.js @@ -138,12 +138,24 @@ chrome.contextMenus.onClicked.addListener(function (info, tab) { for (var i = 0; i < sites.length; i++) { if (sites[i].id === id) { if (info.parentMenuItemId === 'autofill') { + ga('send', { + hitType: 'event', + eventAction: 'Autofilled From Context Menu' + }); autofillPage(sites[i]); } else if (info.parentMenuItemId === 'copy-username') { + ga('send', { + hitType: 'event', + eventAction: 'Copied Username From Context Menu' + }); copyToClipboard(sites[i].username); } else if (info.parentMenuItemId === 'copy-password') { + ga('send', { + hitType: 'event', + eventAction: 'Copied Password From Context Menu' + }); copyToClipboard(sites[i].password); } return; diff --git a/src/popup/app/accounts/accountsHintController.js b/src/popup/app/accounts/accountsHintController.js index d5ce91e8..7e4f3282 100644 --- a/src/popup/app/accounts/accountsHintController.js +++ b/src/popup/app/accounts/accountsHintController.js @@ -1,7 +1,8 @@ angular .module('bit.accounts') - .controller('accountsHintController', function ($scope, $state, apiService, toastr, $q, utilsService) { + .controller('accountsHintController', function ($scope, $state, apiService, toastr, $q, utilsService, + $analytics) { $scope.model = {}; utilsService.initListSectionItemListeners($(document)); @@ -21,6 +22,7 @@ var request = new PasswordHintRequest(model.email); $scope.submitPromise = hintPromise(request); $scope.submitPromise.then(function () { + $analytics.eventTrack('Requested Hint'); toastr.success('We\'ve sent you an email with your master password hint.'); $state.go('login'); }); diff --git a/src/popup/app/accounts/accountsLoginController.js b/src/popup/app/accounts/accountsLoginController.js index 540cab38..0e2948c1 100644 --- a/src/popup/app/accounts/accountsLoginController.js +++ b/src/popup/app/accounts/accountsLoginController.js @@ -2,7 +2,7 @@ .module('bit.accounts') .controller('accountsLoginController', function ($scope, $state, $stateParams, loginService, userService, toastr, - utilsService) { + utilsService, $analytics) { utilsService.initListSectionItemListeners($(document)); if ($stateParams.email) { @@ -36,9 +36,11 @@ $scope.loginPromise.then(function () { userService.isTwoFactorAuthenticated(function (isTwoFactorAuthenticated) { if (isTwoFactorAuthenticated) { + $analytics.eventTrack('Logged In To Two-step'); $state.go('twoFactor', { animation: 'in-slide-left' }); } else { + $analytics.eventTrack('Logged In'); $state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true }); } }); diff --git a/src/popup/app/accounts/accountsLoginTwoFactorController.js b/src/popup/app/accounts/accountsLoginTwoFactorController.js index 29715c2a..7afffddb 100644 --- a/src/popup/app/accounts/accountsLoginTwoFactorController.js +++ b/src/popup/app/accounts/accountsLoginTwoFactorController.js @@ -1,7 +1,8 @@ angular .module('bit.accounts') - .controller('accountsLoginTwoFactorController', function ($scope, $state, loginService, toastr, utilsService) { + .controller('accountsLoginTwoFactorController', function ($scope, $state, loginService, toastr, utilsService, + $analytics) { $scope.model = {}; utilsService.initListSectionItemListeners($(document)); $('#code').focus(); @@ -15,6 +16,7 @@ $scope.loginPromise = loginService.logInTwoFactor(model.code); $scope.loginPromise.then(function () { + $analytics.eventTrack('Logged In From Two-step'); $state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true }); }); }; diff --git a/src/popup/app/accounts/accountsRegisterController.js b/src/popup/app/accounts/accountsRegisterController.js index 55fa7b6d..9eff9c38 100644 --- a/src/popup/app/accounts/accountsRegisterController.js +++ b/src/popup/app/accounts/accountsRegisterController.js @@ -1,7 +1,8 @@ angular .module('bit.accounts') - .controller('accountsRegisterController', function ($scope, $state, cryptoService, toastr, $q, apiService, utilsService) { + .controller('accountsRegisterController', function ($scope, $state, cryptoService, toastr, $q, apiService, utilsService, + $analytics) { $scope.model = {}; utilsService.initListSectionItemListeners($(document)); $('#email').focus(); @@ -29,6 +30,7 @@ var key = cryptoService.makeKey(model.masterPassword, email); $scope.submitPromise = registerPromise(key, model.masterPassword, email, model.hint); $scope.submitPromise.then(function () { + $analytics.eventTrack('Registered'); toastr.success('Your new account has been created! You may now log in.'); $state.go('login', { email: email, animation: 'in-slide-left' }); }); diff --git a/src/popup/app/current/currentController.js b/src/popup/app/current/currentController.js index 1b917526..68301d2f 100644 --- a/src/popup/app/current/currentController.js +++ b/src/popup/app/current/currentController.js @@ -1,7 +1,8 @@ angular .module('bit.current') - .controller('currentController', function ($scope, siteService, tldjs, toastr, $q, $window, $state, autofillService) { + .controller('currentController', function ($scope, siteService, tldjs, toastr, $q, $window, $state, autofillService, + $analytics) { var pageDetails = null, tabId = null, url = null, @@ -56,6 +57,7 @@ angular $scope.clipboardSuccess = function (e, type) { e.clearSelection(); toastr.info(type + ' copied!'); + $analytics.eventTrack('Copied ' + type); }; $scope.addSite = function () { @@ -73,6 +75,7 @@ angular } if (tabId && fillScript && fillScript.script && fillScript.script.length) { + $analytics.eventTrack('Autofilled'); chrome.tabs.sendMessage(tabId, { command: 'fillForm', fillScript: fillScript @@ -81,6 +84,7 @@ angular }); } else { + $analytics.eventTrack('Autofilled Error'); toastr.error('Unable to auto-fill the selected site on this page. ' + 'Copy/paste your username and/or password instead.'); } diff --git a/src/popup/app/settings/settingsAddFolderController.js b/src/popup/app/settings/settingsAddFolderController.js index 92e09d60..96a473ca 100644 --- a/src/popup/app/settings/settingsAddFolderController.js +++ b/src/popup/app/settings/settingsAddFolderController.js @@ -1,7 +1,8 @@ angular .module('bit.settings') - .controller('settingsAddFolderController', function ($scope, $q, folderService, $state, toastr, utilsService) { + .controller('settingsAddFolderController', function ($scope, $q, folderService, $state, toastr, utilsService, + $analytics) { $scope.folder = {}; utilsService.initListSectionItemListeners($(document)); $('#name').focus(); @@ -16,6 +17,7 @@ angular $scope.savePromise = $q.when(folderService.encrypt(model)).then(function (folderModel) { var folder = new Folder(folderModel, true); return $q.when(folderService.saveWithServer(folder)).then(function (folder) { + $analytics.eventTrack('Added Folder'); toastr.success('Added folder'); $state.go('folders', { animation: 'out-slide-down' }); }); diff --git a/src/popup/app/settings/settingsController.js b/src/popup/app/settings/settingsController.js index 92c5b834..934d45ca 100644 --- a/src/popup/app/settings/settingsController.js +++ b/src/popup/app/settings/settingsController.js @@ -1,7 +1,7 @@ angular .module('bit.settings') - .controller('settingsController', function ($scope, loginService, $state, SweetAlert, utilsService) { + .controller('settingsController', function ($scope, loginService, $state, SweetAlert, utilsService, $analytics) { $scope.logOut = function () { SweetAlert.swal({ title: 'Log Out', @@ -12,6 +12,7 @@ }, function (confirmed) { if (confirmed) { loginService.logOut(function () { + $analytics.eventTrack('Logged Out'); $state.go('home'); }); } @@ -26,7 +27,10 @@ showCancelButton: true, confirmButtonText: 'Yes', cancelButtonText: 'Cancel' - }, alertCallback); + }, function (confirmed) { + $analytics.eventTrack('Clicked Change Password'); + alertCallback(confirmed); + }); }; $scope.changeEmail = function () { @@ -37,7 +41,10 @@ showCancelButton: true, confirmButtonText: 'Yes', cancelButtonText: 'Cancel' - }, alertCallback); + }, function (confirmed) { + $analytics.eventTrack('Clicked Change Email'); + alertCallback(confirmed); + }); }; $scope.twoStep = function () { @@ -49,7 +56,10 @@ showCancelButton: true, confirmButtonText: 'Yes', cancelButtonText: 'Cancel' - }, alertCallback); + }, function (confirmed) { + $analytics.eventTrack('Clicked Two-step Login'); + alertCallback(confirmed); + }); }; function alertCallback(confirmed) { @@ -59,6 +69,8 @@ } $scope.rate = function () { + $analytics.eventTrack('Rate Extension'); + switch (utilsService.getBrowser()) { case 'chrome': chrome.tabs.create({ url: 'https://chrome.com' }); diff --git a/src/popup/app/settings/settingsEditFolderController.js b/src/popup/app/settings/settingsEditFolderController.js index a251094f..10c0cbbf 100644 --- a/src/popup/app/settings/settingsEditFolderController.js +++ b/src/popup/app/settings/settingsEditFolderController.js @@ -2,7 +2,7 @@ .module('bit.settings') .controller('settingsEditFolderController', function ($scope, $stateParams, folderService, toastr, $q, $state, SweetAlert, - utilsService) { + utilsService, $analytics) { $scope.folder = {}; var folderId = $stateParams.folderId; @@ -24,6 +24,7 @@ $scope.savePromise = $q.when(folderService.encrypt(model)).then(function (folderModel) { var folder = new Folder(folderModel, true); return $q.when(folderService.saveWithServer(folder)).then(function (folder) { + $analytics.eventTrack('Edited Folder'); toastr.success('Edited folder'); $state.go('folders', { animation: 'out-slide-down' }); }); @@ -40,6 +41,7 @@ }, function (confirmed) { if (confirmed) { $q.when(folderService.deleteWithServer(folderId)).then(function () { + $analytics.eventTrack('Deleted Folder'); toastr.success('Deleted folder'); $state.go('folders', { animation: 'out-slide-down' diff --git a/src/popup/app/settings/settingsHelpController.js b/src/popup/app/settings/settingsHelpController.js index e0021f78..c771c02e 100644 --- a/src/popup/app/settings/settingsHelpController.js +++ b/src/popup/app/settings/settingsHelpController.js @@ -1,16 +1,19 @@ angular .module('bit.settings') - .controller('settingsHelpController', function ($scope) { + .controller('settingsHelpController', function ($scope, $analytics) { $scope.email = function () { + $analytics.eventTrack('Selected Help Email'); chrome.tabs.create({ url: 'mailto:hello@bitwarden.com' }); }; $scope.website = function () { + $analytics.eventTrack('Selected Help Website'); chrome.tabs.create({ url: 'https://vault.bitwarden.com' }); }; $scope.bug = function () { + $analytics.eventTrack('Selected Help Bug Report'); chrome.tabs.create({ url: 'https://github.com/bitwarden/browser' }); }; }); diff --git a/src/popup/app/settings/settingsSyncController.js b/src/popup/app/settings/settingsSyncController.js index 3745e39a..fbb67d3e 100644 --- a/src/popup/app/settings/settingsSyncController.js +++ b/src/popup/app/settings/settingsSyncController.js @@ -1,7 +1,7 @@ angular .module('bit.settings') - .controller('settingsSyncController', function ($scope, syncService, toastr) { + .controller('settingsSyncController', function ($scope, syncService, toastr, $analytics) { $scope.lastSync = '--'; $scope.loading = false; setLastSync(); @@ -9,6 +9,7 @@ $scope.sync = function () { $scope.loading = true; syncService.fullSync(function () { + $analytics.eventTrack('Synced Full'); $scope.loading = false; toastr.success('Syncing complete'); setLastSync(); diff --git a/src/popup/app/tools/toolsPasswordGeneratorController.js b/src/popup/app/tools/toolsPasswordGeneratorController.js index f4d336a8..287eb182 100644 --- a/src/popup/app/tools/toolsPasswordGeneratorController.js +++ b/src/popup/app/tools/toolsPasswordGeneratorController.js @@ -2,7 +2,7 @@ .module('bit.tools') .controller('toolsPasswordGeneratorController', function ($scope, $state, $stateParams, passwordGenerationService, - toastr, $q, utilsService) { + toastr, $q, utilsService, $analytics) { var addState = $stateParams.addState, editState = $stateParams.editState; @@ -21,9 +21,10 @@ hidePointerLabels: true, onChange: function () { $scope.options.length = $scope.slider.value; - $scope.regenerate(); + $scope.regenerate(false); }, onEnd: function () { + $analytics.eventTrack('Generated Password'); $scope.saveOptions($scope.options); } } @@ -32,10 +33,15 @@ $q.when(passwordGenerationService.getOptions()).then(function (options) { $scope.options = options; $scope.slider.value = options.length; - $scope.regenerate(); + $scope.regenerate(false); + $analytics.eventTrack('Generated Password'); }); - $scope.regenerate = function () { + $scope.regenerate = function (trackRegenerateEvent) { + if (trackRegenerateEvent) { + $analytics.eventTrack('Regenerated Password'); + } + $scope.password = passwordGenerationService.generatePassword($scope.options); }; @@ -51,7 +57,7 @@ } passwordGenerationService.saveOptions(options); - $scope.regenerate(); + $scope.regenerate(false); }; $scope.clipboardError = function (e, password) { @@ -59,6 +65,7 @@ }; $scope.clipboardSuccess = function (e) { + $analytics.eventTrack('Copied Generated Password'); e.clearSelection(); toastr.info('Password copied!'); }; @@ -68,6 +75,8 @@ }; $scope.select = function () { + $analytics.eventTrack('Selected Generated Password'); + if (addState) { addState.site.password = $scope.password; } diff --git a/src/popup/app/tools/views/toolsPasswordGenerator.html b/src/popup/app/tools/views/toolsPasswordGenerator.html index 487281af..0fd1e229 100644 --- a/src/popup/app/tools/views/toolsPasswordGenerator.html +++ b/src/popup/app/tools/views/toolsPasswordGenerator.html @@ -14,7 +14,7 @@