analytics event tracking

This commit is contained in:
Kyle Spearrin 2016-09-27 23:19:33 -04:00
parent a727e107fe
commit 96c8a99173
17 changed files with 86 additions and 23 deletions

View File

@ -138,12 +138,24 @@ chrome.contextMenus.onClicked.addListener(function (info, tab) {
for (var i = 0; i < sites.length; i++) { for (var i = 0; i < sites.length; i++) {
if (sites[i].id === id) { if (sites[i].id === id) {
if (info.parentMenuItemId === 'autofill') { if (info.parentMenuItemId === 'autofill') {
ga('send', {
hitType: 'event',
eventAction: 'Autofilled From Context Menu'
});
autofillPage(sites[i]); autofillPage(sites[i]);
} }
else if (info.parentMenuItemId === 'copy-username') { else if (info.parentMenuItemId === 'copy-username') {
ga('send', {
hitType: 'event',
eventAction: 'Copied Username From Context Menu'
});
copyToClipboard(sites[i].username); copyToClipboard(sites[i].username);
} }
else if (info.parentMenuItemId === 'copy-password') { else if (info.parentMenuItemId === 'copy-password') {
ga('send', {
hitType: 'event',
eventAction: 'Copied Password From Context Menu'
});
copyToClipboard(sites[i].password); copyToClipboard(sites[i].password);
} }
return; return;

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.accounts') .module('bit.accounts')
.controller('accountsHintController', function ($scope, $state, apiService, toastr, $q, utilsService) { .controller('accountsHintController', function ($scope, $state, apiService, toastr, $q, utilsService,
$analytics) {
$scope.model = {}; $scope.model = {};
utilsService.initListSectionItemListeners($(document)); utilsService.initListSectionItemListeners($(document));
@ -21,6 +22,7 @@
var request = new PasswordHintRequest(model.email); var request = new PasswordHintRequest(model.email);
$scope.submitPromise = hintPromise(request); $scope.submitPromise = hintPromise(request);
$scope.submitPromise.then(function () { $scope.submitPromise.then(function () {
$analytics.eventTrack('Requested Hint');
toastr.success('We\'ve sent you an email with your master password hint.'); toastr.success('We\'ve sent you an email with your master password hint.');
$state.go('login'); $state.go('login');
}); });

View File

@ -2,7 +2,7 @@
.module('bit.accounts') .module('bit.accounts')
.controller('accountsLoginController', function ($scope, $state, $stateParams, loginService, userService, toastr, .controller('accountsLoginController', function ($scope, $state, $stateParams, loginService, userService, toastr,
utilsService) { utilsService, $analytics) {
utilsService.initListSectionItemListeners($(document)); utilsService.initListSectionItemListeners($(document));
if ($stateParams.email) { if ($stateParams.email) {
@ -36,9 +36,11 @@
$scope.loginPromise.then(function () { $scope.loginPromise.then(function () {
userService.isTwoFactorAuthenticated(function (isTwoFactorAuthenticated) { userService.isTwoFactorAuthenticated(function (isTwoFactorAuthenticated) {
if (isTwoFactorAuthenticated) { if (isTwoFactorAuthenticated) {
$analytics.eventTrack('Logged In To Two-step');
$state.go('twoFactor', { animation: 'in-slide-left' }); $state.go('twoFactor', { animation: 'in-slide-left' });
} }
else { else {
$analytics.eventTrack('Logged In');
$state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true }); $state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true });
} }
}); });

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.accounts') .module('bit.accounts')
.controller('accountsLoginTwoFactorController', function ($scope, $state, loginService, toastr, utilsService) { .controller('accountsLoginTwoFactorController', function ($scope, $state, loginService, toastr, utilsService,
$analytics) {
$scope.model = {}; $scope.model = {};
utilsService.initListSectionItemListeners($(document)); utilsService.initListSectionItemListeners($(document));
$('#code').focus(); $('#code').focus();
@ -15,6 +16,7 @@
$scope.loginPromise = loginService.logInTwoFactor(model.code); $scope.loginPromise = loginService.logInTwoFactor(model.code);
$scope.loginPromise.then(function () { $scope.loginPromise.then(function () {
$analytics.eventTrack('Logged In From Two-step');
$state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true }); $state.go('tabs.vault', { animation: 'in-slide-left', syncOnLoad: true });
}); });
}; };

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.accounts') .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 = {}; $scope.model = {};
utilsService.initListSectionItemListeners($(document)); utilsService.initListSectionItemListeners($(document));
$('#email').focus(); $('#email').focus();
@ -29,6 +30,7 @@
var key = cryptoService.makeKey(model.masterPassword, email); var key = cryptoService.makeKey(model.masterPassword, email);
$scope.submitPromise = registerPromise(key, model.masterPassword, email, model.hint); $scope.submitPromise = registerPromise(key, model.masterPassword, email, model.hint);
$scope.submitPromise.then(function () { $scope.submitPromise.then(function () {
$analytics.eventTrack('Registered');
toastr.success('Your new account has been created! You may now log in.'); toastr.success('Your new account has been created! You may now log in.');
$state.go('login', { email: email, animation: 'in-slide-left' }); $state.go('login', { email: email, animation: 'in-slide-left' });
}); });

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.current') .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, var pageDetails = null,
tabId = null, tabId = null,
url = null, url = null,
@ -56,6 +57,7 @@ angular
$scope.clipboardSuccess = function (e, type) { $scope.clipboardSuccess = function (e, type) {
e.clearSelection(); e.clearSelection();
toastr.info(type + ' copied!'); toastr.info(type + ' copied!');
$analytics.eventTrack('Copied ' + type);
}; };
$scope.addSite = function () { $scope.addSite = function () {
@ -73,6 +75,7 @@ angular
} }
if (tabId && fillScript && fillScript.script && fillScript.script.length) { if (tabId && fillScript && fillScript.script && fillScript.script.length) {
$analytics.eventTrack('Autofilled');
chrome.tabs.sendMessage(tabId, { chrome.tabs.sendMessage(tabId, {
command: 'fillForm', command: 'fillForm',
fillScript: fillScript fillScript: fillScript
@ -81,6 +84,7 @@ angular
}); });
} }
else { else {
$analytics.eventTrack('Autofilled Error');
toastr.error('Unable to auto-fill the selected site on this page. ' + toastr.error('Unable to auto-fill the selected site on this page. ' +
'Copy/paste your username and/or password instead.'); 'Copy/paste your username and/or password instead.');
} }

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.settings') .module('bit.settings')
.controller('settingsAddFolderController', function ($scope, $q, folderService, $state, toastr, utilsService) { .controller('settingsAddFolderController', function ($scope, $q, folderService, $state, toastr, utilsService,
$analytics) {
$scope.folder = {}; $scope.folder = {};
utilsService.initListSectionItemListeners($(document)); utilsService.initListSectionItemListeners($(document));
$('#name').focus(); $('#name').focus();
@ -16,6 +17,7 @@ angular
$scope.savePromise = $q.when(folderService.encrypt(model)).then(function (folderModel) { $scope.savePromise = $q.when(folderService.encrypt(model)).then(function (folderModel) {
var folder = new Folder(folderModel, true); var folder = new Folder(folderModel, true);
return $q.when(folderService.saveWithServer(folder)).then(function (folder) { return $q.when(folderService.saveWithServer(folder)).then(function (folder) {
$analytics.eventTrack('Added Folder');
toastr.success('Added folder'); toastr.success('Added folder');
$state.go('folders', { animation: 'out-slide-down' }); $state.go('folders', { animation: 'out-slide-down' });
}); });

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.settings') .module('bit.settings')
.controller('settingsController', function ($scope, loginService, $state, SweetAlert, utilsService) { .controller('settingsController', function ($scope, loginService, $state, SweetAlert, utilsService, $analytics) {
$scope.logOut = function () { $scope.logOut = function () {
SweetAlert.swal({ SweetAlert.swal({
title: 'Log Out', title: 'Log Out',
@ -12,6 +12,7 @@
}, function (confirmed) { }, function (confirmed) {
if (confirmed) { if (confirmed) {
loginService.logOut(function () { loginService.logOut(function () {
$analytics.eventTrack('Logged Out');
$state.go('home'); $state.go('home');
}); });
} }
@ -26,7 +27,10 @@
showCancelButton: true, showCancelButton: true,
confirmButtonText: 'Yes', confirmButtonText: 'Yes',
cancelButtonText: 'Cancel' cancelButtonText: 'Cancel'
}, alertCallback); }, function (confirmed) {
$analytics.eventTrack('Clicked Change Password');
alertCallback(confirmed);
});
}; };
$scope.changeEmail = function () { $scope.changeEmail = function () {
@ -37,7 +41,10 @@
showCancelButton: true, showCancelButton: true,
confirmButtonText: 'Yes', confirmButtonText: 'Yes',
cancelButtonText: 'Cancel' cancelButtonText: 'Cancel'
}, alertCallback); }, function (confirmed) {
$analytics.eventTrack('Clicked Change Email');
alertCallback(confirmed);
});
}; };
$scope.twoStep = function () { $scope.twoStep = function () {
@ -49,7 +56,10 @@
showCancelButton: true, showCancelButton: true,
confirmButtonText: 'Yes', confirmButtonText: 'Yes',
cancelButtonText: 'Cancel' cancelButtonText: 'Cancel'
}, alertCallback); }, function (confirmed) {
$analytics.eventTrack('Clicked Two-step Login');
alertCallback(confirmed);
});
}; };
function alertCallback(confirmed) { function alertCallback(confirmed) {
@ -59,6 +69,8 @@
} }
$scope.rate = function () { $scope.rate = function () {
$analytics.eventTrack('Rate Extension');
switch (utilsService.getBrowser()) { switch (utilsService.getBrowser()) {
case 'chrome': case 'chrome':
chrome.tabs.create({ url: 'https://chrome.com' }); chrome.tabs.create({ url: 'https://chrome.com' });

View File

@ -2,7 +2,7 @@
.module('bit.settings') .module('bit.settings')
.controller('settingsEditFolderController', function ($scope, $stateParams, folderService, toastr, $q, $state, SweetAlert, .controller('settingsEditFolderController', function ($scope, $stateParams, folderService, toastr, $q, $state, SweetAlert,
utilsService) { utilsService, $analytics) {
$scope.folder = {}; $scope.folder = {};
var folderId = $stateParams.folderId; var folderId = $stateParams.folderId;
@ -24,6 +24,7 @@
$scope.savePromise = $q.when(folderService.encrypt(model)).then(function (folderModel) { $scope.savePromise = $q.when(folderService.encrypt(model)).then(function (folderModel) {
var folder = new Folder(folderModel, true); var folder = new Folder(folderModel, true);
return $q.when(folderService.saveWithServer(folder)).then(function (folder) { return $q.when(folderService.saveWithServer(folder)).then(function (folder) {
$analytics.eventTrack('Edited Folder');
toastr.success('Edited folder'); toastr.success('Edited folder');
$state.go('folders', { animation: 'out-slide-down' }); $state.go('folders', { animation: 'out-slide-down' });
}); });
@ -40,6 +41,7 @@
}, function (confirmed) { }, function (confirmed) {
if (confirmed) { if (confirmed) {
$q.when(folderService.deleteWithServer(folderId)).then(function () { $q.when(folderService.deleteWithServer(folderId)).then(function () {
$analytics.eventTrack('Deleted Folder');
toastr.success('Deleted folder'); toastr.success('Deleted folder');
$state.go('folders', { $state.go('folders', {
animation: 'out-slide-down' animation: 'out-slide-down'

View File

@ -1,16 +1,19 @@
angular angular
.module('bit.settings') .module('bit.settings')
.controller('settingsHelpController', function ($scope) { .controller('settingsHelpController', function ($scope, $analytics) {
$scope.email = function () { $scope.email = function () {
$analytics.eventTrack('Selected Help Email');
chrome.tabs.create({ url: 'mailto:hello@bitwarden.com' }); chrome.tabs.create({ url: 'mailto:hello@bitwarden.com' });
}; };
$scope.website = function () { $scope.website = function () {
$analytics.eventTrack('Selected Help Website');
chrome.tabs.create({ url: 'https://vault.bitwarden.com' }); chrome.tabs.create({ url: 'https://vault.bitwarden.com' });
}; };
$scope.bug = function () { $scope.bug = function () {
$analytics.eventTrack('Selected Help Bug Report');
chrome.tabs.create({ url: 'https://github.com/bitwarden/browser' }); chrome.tabs.create({ url: 'https://github.com/bitwarden/browser' });
}; };
}); });

View File

@ -1,7 +1,7 @@
angular angular
.module('bit.settings') .module('bit.settings')
.controller('settingsSyncController', function ($scope, syncService, toastr) { .controller('settingsSyncController', function ($scope, syncService, toastr, $analytics) {
$scope.lastSync = '--'; $scope.lastSync = '--';
$scope.loading = false; $scope.loading = false;
setLastSync(); setLastSync();
@ -9,6 +9,7 @@
$scope.sync = function () { $scope.sync = function () {
$scope.loading = true; $scope.loading = true;
syncService.fullSync(function () { syncService.fullSync(function () {
$analytics.eventTrack('Synced Full');
$scope.loading = false; $scope.loading = false;
toastr.success('Syncing complete'); toastr.success('Syncing complete');
setLastSync(); setLastSync();

View File

@ -2,7 +2,7 @@
.module('bit.tools') .module('bit.tools')
.controller('toolsPasswordGeneratorController', function ($scope, $state, $stateParams, passwordGenerationService, .controller('toolsPasswordGeneratorController', function ($scope, $state, $stateParams, passwordGenerationService,
toastr, $q, utilsService) { toastr, $q, utilsService, $analytics) {
var addState = $stateParams.addState, var addState = $stateParams.addState,
editState = $stateParams.editState; editState = $stateParams.editState;
@ -21,9 +21,10 @@
hidePointerLabels: true, hidePointerLabels: true,
onChange: function () { onChange: function () {
$scope.options.length = $scope.slider.value; $scope.options.length = $scope.slider.value;
$scope.regenerate(); $scope.regenerate(false);
}, },
onEnd: function () { onEnd: function () {
$analytics.eventTrack('Generated Password');
$scope.saveOptions($scope.options); $scope.saveOptions($scope.options);
} }
} }
@ -32,10 +33,15 @@
$q.when(passwordGenerationService.getOptions()).then(function (options) { $q.when(passwordGenerationService.getOptions()).then(function (options) {
$scope.options = options; $scope.options = options;
$scope.slider.value = options.length; $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); $scope.password = passwordGenerationService.generatePassword($scope.options);
}; };
@ -51,7 +57,7 @@
} }
passwordGenerationService.saveOptions(options); passwordGenerationService.saveOptions(options);
$scope.regenerate(); $scope.regenerate(false);
}; };
$scope.clipboardError = function (e, password) { $scope.clipboardError = function (e, password) {
@ -59,6 +65,7 @@
}; };
$scope.clipboardSuccess = function (e) { $scope.clipboardSuccess = function (e) {
$analytics.eventTrack('Copied Generated Password');
e.clearSelection(); e.clearSelection();
toastr.info('Password copied!'); toastr.info('Password copied!');
}; };
@ -68,6 +75,8 @@
}; };
$scope.select = function () { $scope.select = function () {
$analytics.eventTrack('Selected Generated Password');
if (addState) { if (addState) {
addState.site.password = $scope.password; addState.site.password = $scope.password;
} }

View File

@ -14,7 +14,7 @@
<div class="list" style="margin-top: 0;"> <div class="list" style="margin-top: 0;">
<div class="list-section" style="padding-top: 0;"> <div class="list-section" style="padding-top: 0;">
<div class="list-section-items"> <div class="list-section-items">
<a class="list-section-item text-primary" href="" ng-click="regenerate()"> <a class="list-section-item text-primary" href="" ng-click="regenerate(true)">
Regenerate Password Regenerate Password
</a> </a>
<a class="list-section-item text-primary" href="" ngclipboard ngclipboard-error="clipboardError(e)" <a class="list-section-item text-primary" href="" ngclipboard ngclipboard-error="clipboardError(e)"

View File

@ -2,7 +2,7 @@
.module('bit.vault') .module('bit.vault')
.controller('vaultAddSiteController', function ($scope, $state, $stateParams, siteService, folderService, .controller('vaultAddSiteController', function ($scope, $state, $stateParams, siteService, folderService,
cryptoService, $q, toastr, utilsService) { cryptoService, $q, toastr, utilsService, $analytics) {
var returnScrollY = $stateParams.returnScrollY; var returnScrollY = $stateParams.returnScrollY;
var returnSearchText = $stateParams.returnSearchText; var returnSearchText = $stateParams.returnSearchText;
var fromCurrent = $stateParams.fromCurrent || $stateParams.uri !== null; var fromCurrent = $stateParams.fromCurrent || $stateParams.uri !== null;
@ -43,6 +43,7 @@
$scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) { $scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) {
var site = new Site(siteModel, true); var site = new Site(siteModel, true);
return $q.when(siteService.saveWithServer(site)).then(function (site) { return $q.when(siteService.saveWithServer(site)).then(function (site) {
$analytics.eventTrack('Added Site');
toastr.success('Added site'); toastr.success('Added site');
$scope.close(); $scope.close();
}); });
@ -65,6 +66,7 @@
}; };
$scope.generatePassword = function () { $scope.generatePassword = function () {
$analytics.eventTrack('Clicked Generate Password');
$state.go('passwordGenerator', { $state.go('passwordGenerator', {
animation: 'in-slide-up', animation: 'in-slide-up',
addState: { addState: {

View File

@ -2,7 +2,7 @@
.module('bit.vault') .module('bit.vault')
.controller('vaultController', function ($scope, $rootScope, siteService, folderService, $q, $state, $stateParams, toastr, .controller('vaultController', function ($scope, $rootScope, siteService, folderService, $q, $state, $stateParams, toastr,
syncService, utilsService) { syncService, utilsService, $analytics) {
$('#search').focus(); $('#search').focus();
var syncOnLoad = $stateParams.syncOnLoad; var syncOnLoad = $stateParams.syncOnLoad;
@ -114,6 +114,7 @@
$scope.clipboardSuccess = function (e, type) { $scope.clipboardSuccess = function (e, type) {
e.clearSelection(); e.clearSelection();
$analytics.eventTrack('Copied ' + type);
toastr.info(type + ' copied!'); toastr.info(type + ' copied!');
}; };

View File

@ -2,7 +2,7 @@ angular
.module('bit.vault') .module('bit.vault')
.controller('vaultEditSiteController', function ($scope, $state, $stateParams, siteService, folderService, .controller('vaultEditSiteController', function ($scope, $state, $stateParams, siteService, folderService,
cryptoService, $q, toastr, SweetAlert, utilsService) { cryptoService, $q, toastr, SweetAlert, utilsService, $analytics) {
var returnScrollY = $stateParams.returnScrollY; var returnScrollY = $stateParams.returnScrollY;
var returnSearchText = $stateParams.returnSearchText; var returnSearchText = $stateParams.returnSearchText;
var siteId = $stateParams.siteId; var siteId = $stateParams.siteId;
@ -43,6 +43,7 @@ angular
$scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) { $scope.savePromise = $q.when(siteService.encrypt(model)).then(function (siteModel) {
var site = new Site(siteModel, true); var site = new Site(siteModel, true);
return $q.when(siteService.saveWithServer(site)).then(function (site) { return $q.when(siteService.saveWithServer(site)).then(function (site) {
$analytics.eventTrack('Edited Site');
toastr.success('Edited site'); toastr.success('Edited site');
$scope.close(); $scope.close();
}); });
@ -59,6 +60,7 @@ angular
}, function (confirmed) { }, function (confirmed) {
if (confirmed) { if (confirmed) {
$q.when(siteService.deleteWithServer(siteId)).then(function () { $q.when(siteService.deleteWithServer(siteId)).then(function () {
$analytics.eventTrack('Deleted Site');
toastr.success('Deleted site'); toastr.success('Deleted site');
$state.go('tabs.vault', { $state.go('tabs.vault', {
animation: 'out-slide-down' animation: 'out-slide-down'
@ -107,6 +109,7 @@ angular
}; };
function goPasswordGenerator() { function goPasswordGenerator() {
$analytics.eventTrack('Clicked Generate Password');
$state.go('passwordGenerator', { $state.go('passwordGenerator', {
animation: 'in-slide-up', animation: 'in-slide-up',
editState: { editState: {

View File

@ -1,7 +1,8 @@
angular angular
.module('bit.vault') .module('bit.vault')
.controller('vaultViewSiteController', function ($scope, $state, $stateParams, siteService, tldjs, toastr, $q) { .controller('vaultViewSiteController', function ($scope, $state, $stateParams, siteService, tldjs, toastr, $q,
$analytics) {
var returnScrollY = $stateParams.returnScrollY; var returnScrollY = $stateParams.returnScrollY;
var returnSearchText = $stateParams.returnSearchText; var returnSearchText = $stateParams.returnSearchText;
@ -59,6 +60,7 @@ angular
$scope.launchWebsite = function (site) { $scope.launchWebsite = function (site) {
if (site.showLaunch) { if (site.showLaunch) {
$analytics.eventTrack('Launched Website');
chrome.tabs.create({ url: site.uri }); chrome.tabs.create({ url: site.uri });
} }
}; };
@ -69,11 +71,13 @@ angular
$scope.clipboardSuccess = function (e, type) { $scope.clipboardSuccess = function (e, type) {
e.clearSelection(); e.clearSelection();
$analytics.eventTrack('Copied ' + type);
toastr.info(type + ' copied!'); toastr.info(type + ' copied!');
}; };
$scope.showPassword = false; $scope.showPassword = false;
$scope.togglePassword = function () { $scope.togglePassword = function () {
$analytics.eventTrack('Toggled Password');
$scope.showPassword = !$scope.showPassword; $scope.showPassword = !$scope.showPassword;
}; };
}); });