From 007e78b17a041fc32dd8ba28f649ff8467df47d2 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Tue, 25 Sep 2018 10:49:02 -0500 Subject: [PATCH 01/17] =?UTF-8?q?Added=20=E2=80=9Ctab=20selected=E2=80=9D?= =?UTF-8?q?=20events?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 6 ++++++ .../ViewRelated/Dashboard/DashboardViewController.swift | 1 + .../Classes/ViewRelated/NotificationsViewController.swift | 5 +++++ .../Classes/ViewRelated/Orders/OrdersViewController.swift | 5 +++++ 4 files changed, 17 insertions(+) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index 806b791c7df..ec5a9f9b8e3 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -9,6 +9,12 @@ public enum WooAnalyticsStat: String { // case applicationOpened = "application_opened" case applicationClosed = "application_closed" + case dashboardSelected = "main_tab_dashboard_selected" + case dashboardReselected = "main_tab_dashboard_reselected" + case notificationsSelected = "main_tab_notifications_selected" + case notificationsReselected = "main_tab_notifications_reselected" + case ordersSelected = "main_tab_orders_selected" + case ordersReselected = "main_tab_orders_reselected" // Authentication Events // diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index 07699be56e7..7efc65193f7 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -44,6 +44,7 @@ class DashboardViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + WooAnalytics.shared.track(.dashboardSelected) if storeStatsViewController.isDataMissing { reloadData() } diff --git a/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift b/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift index a01852983a9..38eb53687c6 100644 --- a/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift @@ -14,6 +14,11 @@ class NotificationsViewController: UIViewController { displayPlaceholder() } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + WooAnalytics.shared.track(.notificationsSelected) + } + /// Displays the Empty State Overlay. /// func displayPlaceholder() { diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift index c08908bfd69..9abfcbd636c 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift @@ -111,6 +111,11 @@ class OrdersViewController: UIViewController { syncingCoordinator.synchronizeFirstPage() } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + WooAnalytics.shared.track(.ordersSelected) + } } From 74a6b5b2863c7e46e25cb273174741673f5034c4 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Tue, 25 Sep 2018 12:27:31 -0500 Subject: [PATCH 02/17] Cleaned up tab tracks events --- .../Dashboard/DashboardViewController.swift | 1 - .../ViewRelated/MainTabBarController.swift | 29 +++++++++++++++++++ .../NotificationsViewController.swift | 1 - .../Orders/OrdersViewController.swift | 5 ---- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index 7efc65193f7..07699be56e7 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -44,7 +44,6 @@ class DashboardViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - WooAnalytics.shared.track(.dashboardSelected) if storeStatsViewController.isDataMissing { reloadData() } diff --git a/WooCommerce/Classes/ViewRelated/MainTabBarController.swift b/WooCommerce/Classes/ViewRelated/MainTabBarController.swift index 79dc0d5f017..15b54371093 100644 --- a/WooCommerce/Classes/ViewRelated/MainTabBarController.swift +++ b/WooCommerce/Classes/ViewRelated/MainTabBarController.swift @@ -65,6 +65,35 @@ class MainTabBarController: UITabBarController { item.image = tab.tabIcon } } + + override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { + guard let currentlySelectedTab = WooTab(rawValue: selectedIndex), + let userSelectedIndex = tabBar.items?.index(of: item), + let userSelectedTab = WooTab(rawValue: userSelectedIndex) else { + return + } + + // Did we reselect the already-selected tab? + if currentlySelectedTab == userSelectedTab { + switch userSelectedTab { + case .myStore: + WooAnalytics.shared.track(.dashboardReselected) + case .orders: + WooAnalytics.shared.track(.ordersReselected) + case .notifications: + WooAnalytics.shared.track(.notificationsReselected) + } + } else { + switch userSelectedTab { + case .myStore: + WooAnalytics.shared.track(.dashboardSelected) + case .orders: + WooAnalytics.shared.track(.ordersSelected) + case .notifications: + WooAnalytics.shared.track(.notificationsSelected) + } + } + } } diff --git a/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift b/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift index 38eb53687c6..39e8429cfa5 100644 --- a/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/NotificationsViewController.swift @@ -16,7 +16,6 @@ class NotificationsViewController: UIViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - WooAnalytics.shared.track(.notificationsSelected) } /// Displays the Empty State Overlay. diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift index 9abfcbd636c..c08908bfd69 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift @@ -111,11 +111,6 @@ class OrdersViewController: UIViewController { syncingCoordinator.synchronizeFirstPage() } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - WooAnalytics.shared.track(.ordersSelected) - } } From 1c92073f0b204d38ee5502e2c1b37cab590a0e58 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Tue, 25 Sep 2018 13:07:54 -0500 Subject: [PATCH 03/17] Added settings events --- .../Classes/Analytics/WooAnalyticsStat.swift | 28 +++++++++++++++---- .../Dashboard/DashboardViewController.swift | 1 + .../Settings/SettingsViewController.swift | 8 ++++-- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index ec5a9f9b8e3..c76fce11166 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -9,12 +9,6 @@ public enum WooAnalyticsStat: String { // case applicationOpened = "application_opened" case applicationClosed = "application_closed" - case dashboardSelected = "main_tab_dashboard_selected" - case dashboardReselected = "main_tab_dashboard_reselected" - case notificationsSelected = "main_tab_notifications_selected" - case notificationsReselected = "main_tab_notifications_reselected" - case ordersSelected = "main_tab_orders_selected" - case ordersReselected = "main_tab_orders_reselected" // Authentication Events // @@ -55,6 +49,28 @@ public enum WooAnalyticsStat: String { case onePasswordSignup = "one_password_signup" case twoFactorCodeRequested = "two_factor_code_requested" case twoFactorSentSMS = "two_factor_sent_sms" + + // Dashboard Events + // + case dashboardSelected = "main_tab_dashboard_selected" + case dashboardReselected = "main_tab_dashboard_reselected" + + // Settings Events + // + case settingsTapped = "main_menu_settings_tapped" + case settingsContactSupportTapped = "main_menu_contact_support_tapped" + case settingsLogoutTapped = "settings_logout_button_tapped" + case settingsLogoutConfirmation = "settings_logout_confirmation_dialog_result" + + // Order Events + // + case ordersSelected = "main_tab_orders_selected" + case ordersReselected = "main_tab_orders_reselected" + + // Notification Events + // + case notificationsSelected = "main_tab_notifications_selected" + case notificationsReselected = "main_tab_notifications_reselected" } public extension WooAnalyticsStat { diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index 07699be56e7..e78402c4818 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -106,6 +106,7 @@ private extension DashboardViewController { private extension DashboardViewController { @objc func settingsTapped() { + WooAnalytics.shared.track(.settingsTapped) performSegue(withIdentifier: Segues.settingsSegue, sender: nil) } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/SettingsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/SettingsViewController.swift index 1fe7699e1d8..a1a1b94bf10 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/SettingsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/SettingsViewController.swift @@ -123,15 +123,19 @@ private extension SettingsViewController { private extension SettingsViewController { func logoutWasPressed() { + WooAnalytics.shared.track(.settingsLogoutTapped) let messageUnformatted = NSLocalizedString("Are you sure you want to log out of the account %@?", comment: "Alert message to confirm a user meant to log out.") let messageFormatted = String(format: messageUnformatted, accountName) let alertController = UIAlertController(title: "", message: messageFormatted, preferredStyle: .alert) let cancelText = NSLocalizedString("Back", comment: "Alert button title - dismisses alert, which cancels the log out attempt") - alertController.addActionWithTitle(cancelText, style: .cancel) + alertController.addActionWithTitle(cancelText, style: .cancel) { _ in + WooAnalytics.shared.track(.settingsLogoutConfirmation, withProperties: ["result": "negative"]) + } let logoutText = NSLocalizedString("Log Out", comment: "Alert button title - confirms and logs out the user") alertController.addDefaultActionWithTitle(logoutText) { _ in + WooAnalytics.shared.track(.settingsLogoutConfirmation, withProperties: ["result": "positive"]) self.logOutUser() } @@ -139,6 +143,7 @@ private extension SettingsViewController { } func supportWasPressed() { + WooAnalytics.shared.track(.settingsContactSupportTapped) guard shouldDisplayEmailComposer() else { displayContactUsAlert() return @@ -148,7 +153,6 @@ private extension SettingsViewController { } func logOutUser() { - WooAnalytics.shared.track(.logout) StoresManager.shared.deauthenticate() navigationController?.popToRootViewController(animated: true) } From 044b3e571140cde11bb088f9be87b24c1f49d6c0 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Tue, 25 Sep 2018 14:36:14 -0500 Subject: [PATCH 04/17] Added install and upgrade tracks events --- .../Classes/Analytics/WooAnalyticsStat.swift | 2 ++ WooCommerce/Classes/AppDelegate.swift | 21 +++++++++++++++++++ .../Classes/Extensions/UserDefaults+Woo.swift | 1 + WooCommerce/Classes/Tools/UserAgent.swift | 4 ++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index c76fce11166..b91c15eee65 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -7,6 +7,8 @@ public enum WooAnalyticsStat: String { // Application Events // + case applicationInstalled = "application_installed" + case applicationUpgraded = "application_upgraded" case applicationOpened = "application_opened" case applicationClosed = "application_closed" diff --git a/WooCommerce/Classes/AppDelegate.swift b/WooCommerce/Classes/AppDelegate.swift index 33781ae711d..bc38f7ffa3d 100644 --- a/WooCommerce/Classes/AppDelegate.swift +++ b/WooCommerce/Classes/AppDelegate.swift @@ -70,6 +70,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Yosemite Initialization synchronizeEntitiesIfPossible() + // Upgrade check... + checkForUpgrades() + return true } @@ -198,6 +201,24 @@ private extension AppDelegate { } +private extension AppDelegate { + + func checkForUpgrades() { + let currentVersion = UserAgent.bundleShortVersion + let versionOfLastRun = UserDefaults.standard[.versionOfLastRun] as? String + if versionOfLastRun == nil { + // First run after a fresh install + WooAnalytics.shared.track(.applicationInstalled) + } else if versionOfLastRun != currentVersion { + // App was upgraded + WooAnalytics.shared.track(.applicationInstalled, withProperties: ["previous_version": versionOfLastRun ?? String()]) + } + + UserDefaults.standard[.versionOfLastRun] = currentVersion + } +} + + // MARK: - Authentication Methods // extension AppDelegate { diff --git a/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift b/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift index 7f44fe9355c..895960e870b 100644 --- a/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift +++ b/WooCommerce/Classes/Extensions/UserDefaults+Woo.swift @@ -10,6 +10,7 @@ extension UserDefaults { case defaultUsername case defaultStoreID case defaultAnonymousID + case versionOfLastRun } } diff --git a/WooCommerce/Classes/Tools/UserAgent.swift b/WooCommerce/Classes/Tools/UserAgent.swift index 9652855c2e3..96e64b6bcc9 100644 --- a/WooCommerce/Classes/Tools/UserAgent.swift +++ b/WooCommerce/Classes/Tools/UserAgent.swift @@ -19,13 +19,13 @@ class UserAgent { /// Returns the WebKit User Agent /// - private static var webkitUserAgent: String { + static var webkitUserAgent: String { return UIWebView().stringByEvaluatingJavaScript(from: Constants.loadUserAgentScript) ?? String() } /// Returns the Bundle Version ID /// - private static var bundleShortVersion: String { + static var bundleShortVersion: String { let version = Bundle.main.object(forInfoDictionaryKey: Constants.shortVersionKey) as? String return version ?? String() } From 2c4188a92ed8851caa6571bfb400328ab879fb6c Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Tue, 25 Sep 2018 15:13:40 -0500 Subject: [PATCH 05/17] Login Prologue: tracks events --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 8 ++++++-- .../Epilogue/StorePickerViewController.swift | 3 +++ .../Prologue/LoginPrologueViewController.swift | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index b91c15eee65..d6571970df4 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -20,8 +20,6 @@ public enum WooAnalyticsStat: String { case loginFailed = "login_failed_to_login" case loginAutoFillCredentialsFilled = "login_autofill_credentials_filled" case loginAutoFillCredentialsUpdated = "login_autofill_credentials_updated" - case loginProloguePaged = "login_prologue_paged" - case loginPrologueViewed = "login_prologue_viewed" case loginEmailFormViewed = "login_email_form_viewed" case loginMagicLinkOpenEmailClientViewed = "login_magic_link_open_email_client_viewed" case loginMagicLinkRequestFormViewed = "login_magic_link_request_form_viewed" @@ -36,6 +34,12 @@ public enum WooAnalyticsStat: String { case loginUsernamePasswordFormViewed = "login_username_password_form_viewed" case loginTwoFactorFormViewed = "login_two_factor_form_viewed" case loginEpilogueViewed = "login_epilogue_viewed" + case loginEpilogueStoresShown = "login_epilogue_stores_shown" + case loginEpilogueContinueTapped = "login_epilogue_store_picker_continue_tapped" + case loginProloguePaged = "login_prologue_paged" + case loginPrologueViewed = "login_prologue_viewed" + case loginPrologueContinueTapped = "login_prologue_jetpack_login_button_tapped" + case loginPrologueJetpackInstructions = "login_prologue_jetpack_configuration_instructions_link_tapped" case loginForgotPasswordClicked = "login_forgot_password_clicked" case loginSocialButtonClick = "login_social_button_click" case loginSocialButtonFailure = "login_social_button_failure" diff --git a/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift b/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift index c9af2bf9867..4a3cedf4963 100644 --- a/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift +++ b/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift @@ -133,6 +133,7 @@ private extension StorePickerViewController { func refreshResults() { try? resultsController.performFetch() + WooAnalytics.shared.track(.loginEpilogueStoresShown, withProperties: ["num_of_stores": resultsController.numberOfObjects]) state = StorePickerState(sites: resultsController.fetchedObjects) } @@ -229,6 +230,8 @@ extension StorePickerViewController { case .empty: restartAuthentication() default: + WooAnalytics.shared.track(.loginEpilogueContinueTapped, + withProperties: ["selected_store_id": StoresManager.shared.sessionManager.defaultStoreID ?? ""]) dismiss(animated: true, completion: nil) } } diff --git a/WooCommerce/Classes/Authentication/Prologue/LoginPrologueViewController.swift b/WooCommerce/Classes/Authentication/Prologue/LoginPrologueViewController.swift index fff1d252cbc..8dfd30e27a0 100644 --- a/WooCommerce/Classes/Authentication/Prologue/LoginPrologueViewController.swift +++ b/WooCommerce/Classes/Authentication/Prologue/LoginPrologueViewController.swift @@ -126,6 +126,7 @@ extension LoginPrologueViewController { /// Opens SafariViewController at the specified URL. /// func displaySafariViewController(at url: URL) { + WooAnalytics.shared.track(.loginPrologueJetpackInstructions) let safariViewController = SafariViewController(url: url) safariViewController.modalPresentationStyle = .pageSheet present(safariViewController, animated: true, completion: nil) @@ -134,6 +135,7 @@ extension LoginPrologueViewController { /// Proceeds with the Login Flow. /// @IBAction func loginWasPressed() { + WooAnalytics.shared.track(.loginPrologueContinueTapped) let loginViewController = AppDelegate.shared.authenticationManager.loginForWordPressDotCom() navigationController?.pushViewController(loginViewController, animated: true) From 49a8f756e5c8b67c668f48460f2ff2c4bda6ef4b Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Tue, 25 Sep 2018 16:29:08 -0500 Subject: [PATCH 06/17] Updated tracks user props --- .../Classes/Analytics/TracksProvider.swift | 20 ++++++++++++++++--- .../Epilogue/StorePickerViewController.swift | 3 +++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/Analytics/TracksProvider.swift b/WooCommerce/Classes/Analytics/TracksProvider.swift index a6d49109632..e865d38d813 100644 --- a/WooCommerce/Classes/Analytics/TracksProvider.swift +++ b/WooCommerce/Classes/Analytics/TracksProvider.swift @@ -52,10 +52,16 @@ public extension TracksProvider { // private extension TracksProvider { func refreshMetadata() { + DDLogInfo("♻️ Refreshing tracks metadata...") var userProperties = [String: Any]() - userProperties["platform"] = "iOS" - userProperties["accessibility_voice_over_enabled"] = UIAccessibility.isVoiceOverRunning - userProperties["is_rtl_language"] = (UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft) + userProperties[UserProperties.platformKey] = "iOS" + userProperties[UserProperties.voiceOverKey] = UIAccessibility.isVoiceOverRunning + userProperties[UserProperties.rtlKey] = (UIApplication.shared.userInterfaceLayoutDirection == .rightToLeft) + if StoresManager.shared.isAuthenticated { + let site = StoresManager.shared.sessionManager.defaultSite + userProperties[UserProperties.blogIDKey] = site?.siteID + userProperties[UserProperties.wpcomStoreKey] = site?.isWordPressStore + } tracksService.userProperties.removeAllObjects() tracksService.userProperties.addEntries(from: userProperties) } @@ -69,4 +75,12 @@ private extension TracksProvider { enum Constants { static let eventNamePrefix = "woocommerceios" } + + enum UserProperties { + static let platformKey = "platform" + static let voiceOverKey = "accessibility_voice_over_enabled" + static let rtlKey = "is_rtl_language" + static let blogIDKey = "user_info_blog_id" + static let wpcomStoreKey = "user_info_is_wpcom_store" + } } diff --git a/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift b/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift index 4a3cedf4963..4efb60fe62e 100644 --- a/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift +++ b/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift @@ -230,6 +230,9 @@ extension StorePickerViewController { case .empty: restartAuthentication() default: + // We need to call refreshUserData() here because the user selected + // their default store and tracks should to know about it. + WooAnalytics.shared.refreshUserData() WooAnalytics.shared.track(.loginEpilogueContinueTapped, withProperties: ["selected_store_id": StoresManager.shared.sessionManager.defaultStoreID ?? ""]) dismiss(animated: true, completion: nil) From f61470194951a18ae0d7128453690a758c5b474c Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Tue, 25 Sep 2018 16:54:53 -0500 Subject: [PATCH 07/17] More event properties --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 6 ++++++ .../ViewRelated/Dashboard/DashboardViewController.swift | 1 + .../OrderDetails/AddNote/AddANoteViewController.swift | 3 +++ .../Orders/OrderDetails/OrderDetailsViewController.swift | 2 ++ .../Classes/ViewRelated/Orders/OrdersViewController.swift | 1 + 5 files changed, 13 insertions(+) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index d6571970df4..f8ce3072417 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -60,6 +60,7 @@ public enum WooAnalyticsStat: String { // case dashboardSelected = "main_tab_dashboard_selected" case dashboardReselected = "main_tab_dashboard_reselected" + case dashboardPulledToRefresh = "dashboard_pulled_to_refresh" // Settings Events // @@ -72,6 +73,11 @@ public enum WooAnalyticsStat: String { // case ordersSelected = "main_tab_orders_selected" case ordersReselected = "main_tab_orders_reselected" + case ordersListPulledToRefresh = "orders_list_pulled_to_refresh" + case orderDetailAddNoteButtonTapped = "order_detail_add_note_button_tapped" + case orderDetailPulledToRefresh = "order_detail_pulled_to_refresh" + case orderNoteAddButtonTapped = "add_order_note_add_button_tapped" + case orderNoteEmailCustomerToggled = "add_order_note_email_note_to_customer_toggled" // Notification Events // diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index e78402c4818..7262d65623e 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -111,6 +111,7 @@ private extension DashboardViewController { } @objc func pullToRefresh() { + WooAnalytics.shared.track(.dashboardPulledToRefresh) applyHideAnimation(for: newOrdersContainerView) reloadData() } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift index fdf9a4a78ad..21fe4f4cf9a 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift @@ -63,6 +63,7 @@ class AddANoteViewController: UIViewController { } @objc func addButtonTapped() { + WooAnalytics.shared.track(.orderNoteAddButtonTapped) let action = OrderNoteAction.addOrderNote(siteID: viewModel.order.siteID, orderID: viewModel.order.orderID, isCustomerNote: isCustomerNote, note: noteText) { [weak self] (orderNote, error) in if let error = error { DDLogError("⛔️ Error adding a note: \(error.localizedDescription)") @@ -163,6 +164,8 @@ private extension AddANoteViewController { self.refreshTextViewCell() cell.accessibilityLabel = String.localizedStringWithFormat(NSLocalizedString("Email note to customer %@", comment: ""), self.isCustomerNote ? NSLocalizedString("On", comment: "Spoken label to indicate switch control is turned on") : NSLocalizedString("Off", comment: "Spoken label to indicate switch control is turned off.")) cell.accessibilityHint = NSLocalizedString("Double tap to toggle setting.", comment: "VoiceOver accessibility hint, informing the user that double-tapping will toggle the switch off and on.") + let stateValue = self.isCustomerNote ? "on" : "off" + WooAnalytics.shared.track(.orderNoteEmailCustomerToggled, withProperties: ["state": stateValue]) } } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 6e7c6180640..42bfdcaf278 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -245,6 +245,7 @@ private extension OrderDetailsViewController { extension OrderDetailsViewController { @objc func pullToRefresh() { + WooAnalytics.shared.track(.orderDetailPulledToRefresh) let group = DispatchGroup() group.enter() @@ -538,6 +539,7 @@ extension OrderDetailsViewController: UITableViewDelegate { switch sections[indexPath.section].rows[indexPath.row] { case .addOrderNote: + WooAnalytics.shared.track(.orderDetailAddNoteButtonTapped) let addANoteViewController = self.storyboard!.instantiateViewController(withIdentifier: Constants.noteViewController) as! AddANoteViewController addANoteViewController.viewModel = viewModel let navController = UINavigationController(rootViewController: addANoteViewController) diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift index c08908bfd69..8135ec7e50c 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift @@ -195,6 +195,7 @@ extension OrdersViewController { } @IBAction func pullToRefresh(sender: UIRefreshControl) { + WooAnalytics.shared.track(.ordersListPulledToRefresh) syncingCoordinator.synchronizeFirstPage { sender.endRefreshing() } From a429d2cc65ee8ea60c19606e6b6a391c9d4e3590 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 08:47:41 -0500 Subject: [PATCH 08/17] Moar analytics! --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 10 ++++++++++ .../Dashboard/MyStore/NewOrdersViewController.swift | 1 + .../OrderDetails/OrderDetailsViewController.swift | 12 +++++++++++- .../ViewRelated/Orders/OrdersViewController.swift | 3 +++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index f8ce3072417..fb0e73aeeb8 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -61,6 +61,7 @@ public enum WooAnalyticsStat: String { case dashboardSelected = "main_tab_dashboard_selected" case dashboardReselected = "main_tab_dashboard_reselected" case dashboardPulledToRefresh = "dashboard_pulled_to_refresh" + case dashboardNewOrdersButtonTapped = "dashboard_unfulfilled_orders_button_tapped" // Settings Events // @@ -74,10 +75,19 @@ public enum WooAnalyticsStat: String { case ordersSelected = "main_tab_orders_selected" case ordersReselected = "main_tab_orders_reselected" case ordersListPulledToRefresh = "orders_list_pulled_to_refresh" + case ordersListFilterTapped = "orders_list_menu_filter_tapped" + case filterOrdersOptionSelected = "filter_orders_by_status_dialog_option_selected" case orderDetailAddNoteButtonTapped = "order_detail_add_note_button_tapped" case orderDetailPulledToRefresh = "order_detail_pulled_to_refresh" case orderNoteAddButtonTapped = "add_order_note_add_button_tapped" case orderNoteEmailCustomerToggled = "add_order_note_email_note_to_customer_toggled" + case orderDetailShowBillingTapped = "order_detail_customer_info_show_billing_tapped" + case orderDetailHideBillingTapped = "order_detail_customer_info_hide_billing_tapped" + case orderDetailFulfillButtonTapped = "order_detail_fulfill_order_button_tapped" + case orderDetailCustomerEmailTapped = "order_detail_customer_info_email_menu_email_tapped" + case orderDetailCustomerPhoneMenuTapped = "order_detail_customer_info_phone_menu_tapped" + case orderDetailCustomerPhoneOptionTapped = "order_detail_customer_info_phone_menu_phone_tapped" + case orderDetailCustomerSMSOptionTapped = "order_detail_customer_info_phone_menu_sms_tapped" // Notification Events // diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/NewOrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/NewOrdersViewController.swift index 011c79fcff7..df1d99979b9 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/NewOrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/NewOrdersViewController.swift @@ -98,6 +98,7 @@ private extension NewOrdersViewController { @IBAction func buttonTouchUpInside(_ sender: UIButton) { sender.fadeOutSelectedBackground { + WooAnalytics.shared.track(.dashboardNewOrdersButtonTapped) MainTabBarController.switchToOrdersTab(filter: .processing) } } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 42bfdcaf278..1861e43d4e5 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -424,6 +424,7 @@ extension OrderDetailsViewController { actionSheet.addAction(dismissAction) let callAction = UIAlertAction(title: NSLocalizedString("Call", comment: "Call phone number button title"), style: .default) { [weak self] action in + WooAnalytics.shared.track(.orderDetailCustomerPhoneOptionTapped) guard let phone = self?.viewModel.order.billingAddress?.cleanedPhoneNumber else { return } @@ -435,22 +436,31 @@ extension OrderDetailsViewController { actionSheet.addAction(callAction) let messageAction = UIAlertAction(title: NSLocalizedString("Message", comment: "Message phone number button title"), style: .default) { [weak self] action in + WooAnalytics.shared.track(.orderDetailCustomerSMSOptionTapped) self?.sendTextMessageIfPossible() } - actionSheet.addAction(messageAction) + actionSheet.addAction(messageAction) + WooAnalytics.shared.track(.orderDetailCustomerPhoneMenuTapped) present(actionSheet, animated: true) } @objc func emailButtonAction() { + WooAnalytics.shared.track(.orderDetailCustomerEmailTapped) sendEmailIfPossible() } func toggleBillingFooter() { displaysBillingDetails = !displaysBillingDetails + if displaysBillingDetails { + WooAnalytics.shared.track(.orderDetailShowBillingTapped) + } else { + WooAnalytics.shared.track(.orderDetailHideBillingTapped) + } } func fulfillWasPressed() { + WooAnalytics.shared.track(.orderDetailFulfillButtonTapped) let fulfillViewController = FulfillViewController(order: viewModel.order) navigationController?.pushViewController(fulfillViewController, animated: true) } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift index 8135ec7e50c..58996590dda 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift @@ -177,6 +177,7 @@ private extension OrdersViewController { extension OrdersViewController { @IBAction func displayFiltersAlert() { + WooAnalytics.shared.track(.ordersListFilterTapped) let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) actionSheet.view.tintColor = StyleManager.wooCommerceBrandColor @@ -208,6 +209,8 @@ extension OrdersViewController { private extension OrdersViewController { func didChangeFilter(newFilter: OrderStatus?) { + WooAnalytics.shared.track(.filterOrdersOptionSelected, + withProperties: ["status": newFilter?.description ?? String()]) // Display the Filter in the Title refreshTitle() From a0aa8c4e905bda5ae1d6e55249652a54f0cdcf17 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 08:53:31 -0500 Subject: [PATCH 09/17] Added orderDetailProductDetailTapped --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 1 + .../Orders/OrderDetails/OrderDetailsViewController.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index fb0e73aeeb8..415ad210ec0 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -88,6 +88,7 @@ public enum WooAnalyticsStat: String { case orderDetailCustomerPhoneMenuTapped = "order_detail_customer_info_phone_menu_tapped" case orderDetailCustomerPhoneOptionTapped = "order_detail_customer_info_phone_menu_phone_tapped" case orderDetailCustomerSMSOptionTapped = "order_detail_customer_info_phone_menu_sms_tapped" + case orderDetailProductDetailTapped = "order_detail_product_detail_button_tapped" // Notification Events // diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 1861e43d4e5..473ea6217b3 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -555,6 +555,7 @@ extension OrderDetailsViewController: UITableViewDelegate { let navController = UINavigationController(rootViewController: addANoteViewController) present(navController, animated: true, completion: nil) case .productDetails: + WooAnalytics.shared.track(.orderDetailProductDetailTapped) performSegue(withIdentifier: Constants.productDetailsSegue, sender: nil) default: break From b3572ba63dc71fd82ed21f085366c0a84d363796 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 09:32:00 -0500 Subject: [PATCH 10/17] Order Fulfillment: tracks stuff --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 2 ++ .../Classes/ViewRelated/Orders/FulfillViewController.swift | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index 415ad210ec0..a9ebed4c624 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -89,6 +89,8 @@ public enum WooAnalyticsStat: String { case orderDetailCustomerPhoneOptionTapped = "order_detail_customer_info_phone_menu_phone_tapped" case orderDetailCustomerSMSOptionTapped = "order_detail_customer_info_phone_menu_sms_tapped" case orderDetailProductDetailTapped = "order_detail_product_detail_button_tapped" + case orderFulfillmentCompleteButtonTapped = "order_fulfillment_mark_order_complete_button_tapped" + case orderMarkedCompleteUndoButtonTapped = "snack_order_marked_complete_undo_button_tapped" // Notification Events // diff --git a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift index f319f0f3a63..f6c374da8e0 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/FulfillViewController.swift @@ -132,8 +132,9 @@ extension FulfillViewController { let undo = updateOrderAction(siteID: order.siteID, orderID: order.orderID, status: order.status) StoresManager.shared.dispatch(done) - + WooAnalytics.shared.track(.orderFulfillmentCompleteButtonTapped) displayOrderCompleteNotice { + WooAnalytics.shared.track(.orderMarkedCompleteUndoButtonTapped) StoresManager.shared.dispatch(undo) } From 9a55f045cc724ae06e4100188bb70ea772f30eff Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 11:46:03 -0500 Subject: [PATCH 11/17] More order + note analytics --- .../Classes/Analytics/WooAnalyticsStat.swift | 13 ++++++++++--- .../AddNote/AddANoteViewController.swift | 2 ++ .../OrderDetails/OrderDetailsViewController.swift | 2 ++ .../ViewRelated/Orders/OrdersViewController.swift | 2 ++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index a9ebed4c624..5e0ba9c6f8f 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -56,21 +56,21 @@ public enum WooAnalyticsStat: String { case twoFactorCodeRequested = "two_factor_code_requested" case twoFactorSentSMS = "two_factor_sent_sms" - // Dashboard Events + // Dashboard View Events // case dashboardSelected = "main_tab_dashboard_selected" case dashboardReselected = "main_tab_dashboard_reselected" case dashboardPulledToRefresh = "dashboard_pulled_to_refresh" case dashboardNewOrdersButtonTapped = "dashboard_unfulfilled_orders_button_tapped" - // Settings Events + // Settings View Events // case settingsTapped = "main_menu_settings_tapped" case settingsContactSupportTapped = "main_menu_contact_support_tapped" case settingsLogoutTapped = "settings_logout_button_tapped" case settingsLogoutConfirmation = "settings_logout_confirmation_dialog_result" - // Order Events + // Order View Events // case ordersSelected = "main_tab_orders_selected" case ordersReselected = "main_tab_orders_reselected" @@ -92,6 +92,13 @@ public enum WooAnalyticsStat: String { case orderFulfillmentCompleteButtonTapped = "order_fulfillment_mark_order_complete_button_tapped" case orderMarkedCompleteUndoButtonTapped = "snack_order_marked_complete_undo_button_tapped" + // Order Data/Action Events + // + case orderOpen = "order_open" + case orderNotesLoaded = "order_notes_loaded" + case orderNoteAddSuccess = "order_note_add_success" + case orderNoteAddFailed = "order_note_add_failed" + // Notification Events // case notificationsSelected = "main_tab_notifications_selected" diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift index 21fe4f4cf9a..70c9ec77dd8 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift @@ -67,9 +67,11 @@ class AddANoteViewController: UIViewController { let action = OrderNoteAction.addOrderNote(siteID: viewModel.order.siteID, orderID: viewModel.order.orderID, isCustomerNote: isCustomerNote, note: noteText) { [weak self] (orderNote, error) in if let error = error { DDLogError("⛔️ Error adding a note: \(error.localizedDescription)") + WooAnalytics.shared.track(.orderNoteAddFailed, withError: error) // TODO: should this alert the user that there was an error? return } + WooAnalytics.shared.track(.orderNoteAddSuccess) self?.dismiss(animated: true, completion: nil) } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 473ea6217b3..912fdc46a40 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -402,10 +402,12 @@ private extension OrderDetailsViewController { DDLogError("⛔️ Error synchronizing Order Notes: \(error.debugDescription)") self?.orderNotes = [] onCompletion?(error) + return } self?.orderNotes = orderNotes.map { OrderNoteViewModel(with: $0) } + WooAnalytics.shared.track(.orderNotesLoaded, withProperties: ["id": self?.viewModel.order.orderID ?? 0]) onCompletion?(nil) } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift index 58996590dda..c75ebf650b3 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift @@ -461,6 +461,8 @@ extension OrdersViewController { return } + WooAnalytics.shared.track(.orderOpen, withProperties: ["id": viewModel.order.orderID, + "status": viewModel.order.status.description]) singleOrderViewController.viewModel = viewModel } } From c06c59b3eff694ea77597cb636279c28535d5da5 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 14:13:04 -0500 Subject: [PATCH 12/17] Updated Tracks UserProperties keys --- WooCommerce/Classes/Analytics/TracksProvider.swift | 4 ++-- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/Analytics/TracksProvider.swift b/WooCommerce/Classes/Analytics/TracksProvider.swift index e865d38d813..e7096b77a08 100644 --- a/WooCommerce/Classes/Analytics/TracksProvider.swift +++ b/WooCommerce/Classes/Analytics/TracksProvider.swift @@ -80,7 +80,7 @@ private extension TracksProvider { static let platformKey = "platform" static let voiceOverKey = "accessibility_voice_over_enabled" static let rtlKey = "is_rtl_language" - static let blogIDKey = "user_info_blog_id" - static let wpcomStoreKey = "user_info_is_wpcom_store" + static let blogIDKey = "blog_id" + static let wpcomStoreKey = "is_wpcom_store" } } diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index 5e0ba9c6f8f..1f63a14c103 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -1,7 +1,8 @@ import WordPressShared -/// This enum contains all of the events we track in the app. +/// This enum contains all of the events we track in the app. Please reference the "Woo Mobile Events Draft i2" +/// spreadsheet for more details. /// public enum WooAnalyticsStat: String { From d2f21a54058835b5b99eacc9e8a065ff47723190 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 15:22:26 -0500 Subject: [PATCH 13/17] Added tab changed tracks events in dashboard --- .../Classes/Analytics/WooAnalyticsStat.swift | 2 ++ .../MyStore/PeriodDataViewController.swift | 12 ++++++++++++ .../TopPerformerDataViewController.swift | 17 +++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index 1f63a14c103..6c33a903a6a 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -63,6 +63,8 @@ public enum WooAnalyticsStat: String { case dashboardReselected = "main_tab_dashboard_reselected" case dashboardPulledToRefresh = "dashboard_pulled_to_refresh" case dashboardNewOrdersButtonTapped = "dashboard_unfulfilled_orders_button_tapped" + case dashboardRevenueChartTabTapped = "dashboard_revenue_chart_tab_tapped" + case dashboardTopPerformerTabTapped = "dashboard_top_performer_tab_tapped" // Settings View Events // diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift index 1c5f2970ee1..8a9fde4232a 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift @@ -25,6 +25,7 @@ class PeriodDataViewController: UIViewController, IndicatorInfoProvider { private var lastUpdatedDate: Date? private var yAxisMinimum: String = Constants.chartYAxisMinimum.friendlyString() private var yAxisMaximum: String = "" + private var isInitialLoad: Bool = true // Used in trackChangedTabIfNeeded() public let granularity: StatGranularity public var orderStats: OrderStats? { @@ -109,6 +110,7 @@ class PeriodDataViewController: UIViewController, IndicatorInfoProvider { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) reloadAllFields() + trackChangedTabIfNeeded() } override func viewDidDisappear(_ animated: Bool) { @@ -309,6 +311,16 @@ private extension PeriodDataViewController { // private extension PeriodDataViewController { + func trackChangedTabIfNeeded() { + // This is a little bit of a workaround to prevent the "tab tapped" tracks event from firing when launching the app. + if granularity == .day && isInitialLoad { + isInitialLoad = false + return + } + WooAnalytics.shared.track(.dashboardRevenueChartTabTapped, withProperties: ["selected_tab": granularity.rawValue]) + isInitialLoad = false + } + func reloadAllFields() { reloadOrderFields() reloadSiteFields() diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift index c0d59dc4bbb..26f9471eb59 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift @@ -24,6 +24,8 @@ class TopPerformerDataViewController: UIViewController, IndicatorInfoProvider { return ResultsController(storageManager: storageManager, matching: predicate, sortedBy: [descriptor]) }() + private var isInitialLoad: Bool = true // Used in trackChangedTabIfNeeded() + // MARK: - Computed Properties private var topEarnerStats: TopEarnerStats? { @@ -72,6 +74,11 @@ class TopPerformerDataViewController: UIViewController, IndicatorInfoProvider { registerTableViewCells() registerTableViewHeaderFooters() } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + trackChangedTabIfNeeded() + } } @@ -208,6 +215,16 @@ extension TopPerformerDataViewController: UITableViewDelegate { // private extension TopPerformerDataViewController { + func trackChangedTabIfNeeded() { + // This is a little bit of a workaround to prevent the "tab tapped" tracks event from firing when launching the app. + if granularity == .day && isInitialLoad { + isInitialLoad = false + return + } + WooAnalytics.shared.track(.dashboardTopPerformerTabTapped, withProperties: ["selected_tab": granularity.rawValue]) + isInitialLoad = false + } + func statsItem(at indexPath: IndexPath) -> TopEarnerStatsItem? { guard let topEarnerStatsItem = topEarnerStats?.items?.sorted(by: >)[safe: indexPath.row] else { return nil From 1836fa30ffb8e63bdf70f120ca6717aee9a4ecef Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 15:32:30 -0500 Subject: [PATCH 14/17] Added order note add data event --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 1 + .../Authentication/Epilogue/StorePickerViewController.swift | 2 +- .../Orders/OrderDetails/AddNote/AddANoteViewController.swift | 4 ++++ .../Classes/ViewRelated/Orders/OrdersViewController.swift | 4 ++-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index 6c33a903a6a..bf0ffe1cd43 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -99,6 +99,7 @@ public enum WooAnalyticsStat: String { // case orderOpen = "order_open" case orderNotesLoaded = "order_notes_loaded" + case orderNoteAdd = "order_note_add" case orderNoteAddSuccess = "order_note_add_success" case orderNoteAddFailed = "order_note_add_failed" diff --git a/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift b/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift index 4efb60fe62e..ec0de38a5ea 100644 --- a/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift +++ b/WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift @@ -234,7 +234,7 @@ extension StorePickerViewController { // their default store and tracks should to know about it. WooAnalytics.shared.refreshUserData() WooAnalytics.shared.track(.loginEpilogueContinueTapped, - withProperties: ["selected_store_id": StoresManager.shared.sessionManager.defaultStoreID ?? ""]) + withProperties: ["selected_store_id": StoresManager.shared.sessionManager.defaultStoreID ?? String()]) dismiss(animated: true, completion: nil) } } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift index 70c9ec77dd8..925b4f6fed2 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/AddNote/AddANoteViewController.swift @@ -64,6 +64,10 @@ class AddANoteViewController: UIViewController { @objc func addButtonTapped() { WooAnalytics.shared.track(.orderNoteAddButtonTapped) + WooAnalytics.shared.track(.orderNoteAdd, withProperties: ["parent_id": viewModel.order.orderID, + "status": viewModel.order.status.rawValue, + "type": isCustomerNote ? "customer" : "private"]) + let action = OrderNoteAction.addOrderNote(siteID: viewModel.order.siteID, orderID: viewModel.order.orderID, isCustomerNote: isCustomerNote, note: noteText) { [weak self] (orderNote, error) in if let error = error { DDLogError("⛔️ Error adding a note: \(error.localizedDescription)") diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift index c75ebf650b3..06b9fcff019 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift @@ -210,7 +210,7 @@ private extension OrdersViewController { func didChangeFilter(newFilter: OrderStatus?) { WooAnalytics.shared.track(.filterOrdersOptionSelected, - withProperties: ["status": newFilter?.description ?? String()]) + withProperties: ["status": newFilter?.rawValue ?? String()]) // Display the Filter in the Title refreshTitle() @@ -462,7 +462,7 @@ extension OrdersViewController { } WooAnalytics.shared.track(.orderOpen, withProperties: ["id": viewModel.order.orderID, - "status": viewModel.order.status.description]) + "status": viewModel.order.status.rawValue]) singleOrderViewController.viewModel = viewModel } } From 44402e1535fca6edfc7470002bedb185d2a4bcaf Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 16:17:31 -0500 Subject: [PATCH 15/17] Moar tracks events --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 11 +++++++++-- .../Dashboard/DashboardViewController.swift | 2 ++ .../Dashboard/MyStore/PeriodDataViewController.swift | 2 +- .../Dashboard/MyStore/StoreStatsViewController.swift | 1 + .../MyStore/TopPerformerDataViewController.swift | 6 ++++-- .../OrderDetails/OrderDetailsViewController.swift | 9 +++++++++ 6 files changed, 26 insertions(+), 5 deletions(-) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index bf0ffe1cd43..2f11c03bd0d 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -63,8 +63,14 @@ public enum WooAnalyticsStat: String { case dashboardReselected = "main_tab_dashboard_reselected" case dashboardPulledToRefresh = "dashboard_pulled_to_refresh" case dashboardNewOrdersButtonTapped = "dashboard_unfulfilled_orders_button_tapped" - case dashboardRevenueChartTabTapped = "dashboard_revenue_chart_tab_tapped" - case dashboardTopPerformerTabTapped = "dashboard_top_performer_tab_tapped" + + // Dashboard Data/Action Events + // + case dashboardMainStatsDate = "dashboard_main_stats_date" + case dashboardMainStatsLoaded = "dashboard_main_stats_loaded" + case dashboardTopPerformersDate = "dashboard_top_performers_date" + case dashboardTopPerformersLoaded = "dashboard_top_performers_loaded" + case dashboardUnfulfilledOrdersLoaded = "dashboard_unfulfilled_orders_loaded" // Settings View Events // @@ -102,6 +108,7 @@ public enum WooAnalyticsStat: String { case orderNoteAdd = "order_note_add" case orderNoteAddSuccess = "order_note_add_success" case orderNoteAddFailed = "order_note_add_failed" + case orderContactAction = "order_contact_action" // Notification Events // diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift index 7262d65623e..d1c2be6aef7 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/DashboardViewController.swift @@ -124,8 +124,10 @@ extension DashboardViewController: NewOrdersDelegate { func didUpdateNewOrdersData(hasNewOrders: Bool) { if hasNewOrders { applyUnhideAnimation(for: newOrdersContainerView) + WooAnalytics.shared.track(.dashboardUnfulfilledOrdersLoaded, withProperties: ["has_unfulfilled_orders": "true"]) } else { applyHideAnimation(for: newOrdersContainerView) + WooAnalytics.shared.track(.dashboardUnfulfilledOrdersLoaded, withProperties: ["has_unfulfilled_orders": "false"]) } } } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift index 8a9fde4232a..4aa15e04075 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/PeriodDataViewController.swift @@ -317,7 +317,7 @@ private extension PeriodDataViewController { isInitialLoad = false return } - WooAnalytics.shared.track(.dashboardRevenueChartTabTapped, withProperties: ["selected_tab": granularity.rawValue]) + WooAnalytics.shared.track(.dashboardMainStatsDate, withProperties: ["range": granularity.rawValue]) isInitialLoad = false } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift index 94818078809..b8974147c1c 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/StoreStatsViewController.swift @@ -151,6 +151,7 @@ private extension StoreStatsViewController { let vc = self.periodDataVC(for: granularity) vc?.orderStats = orderStats + WooAnalytics.shared.track(.dashboardMainStatsLoaded, withProperties: ["granularity": granularity.rawValue]) onCompletion?(nil) } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift index 26f9471eb59..83fba02d7d1 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/MyStore/TopPerformerDataViewController.swift @@ -92,9 +92,11 @@ extension TopPerformerDataViewController { return } - let action = StatsAction.retrieveTopEarnerStats(siteID: siteID, granularity: granularity, latestDateToInclude: Date()) { (error) in + let action = StatsAction.retrieveTopEarnerStats(siteID: siteID, granularity: granularity, latestDateToInclude: Date()) { [weak self] (error) in if let error = error { DDLogError("⛔️ Dashboard (Top Performers) — Error synchronizing top earner stats: \(error)") + } else { + WooAnalytics.shared.track(.dashboardTopPerformersLoaded, withProperties: ["granularity": self?.granularity.rawValue ?? String()]) } } StoresManager.shared.dispatch(action) @@ -221,7 +223,7 @@ private extension TopPerformerDataViewController { isInitialLoad = false return } - WooAnalytics.shared.track(.dashboardTopPerformerTabTapped, withProperties: ["selected_tab": granularity.rawValue]) + WooAnalytics.shared.track(.dashboardTopPerformersDate, withProperties: ["range": granularity.rawValue]) isInitialLoad = false } diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 912fdc46a40..f7ce46f0b5e 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -433,6 +433,9 @@ extension OrderDetailsViewController { if let url = URL(string: "telprompt://" + phone), UIApplication.shared.canOpenURL(url) { UIApplication.shared.open(url, options: [:], completionHandler: nil) + WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": self?.viewModel.order.orderID ?? 0, + "status": self?.viewModel.order.status.rawValue ?? String(), + "type": "call"]) } } actionSheet.addAction(callAction) @@ -582,6 +585,9 @@ extension OrderDetailsViewController: MFMessageComposeViewControllerDelegate { if MFMessageComposeViewController.canSendText() { sendTextMessage(to: phoneNumber) + WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": viewModel.order.orderID, + "status": viewModel.order.status.rawValue, + "type": "sms"]) } } @@ -608,6 +614,9 @@ extension OrderDetailsViewController: MFMailComposeViewControllerDelegate { } sendEmail(to: email) + WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": viewModel.order.orderID, + "status": viewModel.order.status.rawValue, + "type": "email"]) } } From 9f81258f50900d5a989dfc5c6bf9085aea1ed507 Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 16:37:38 -0500 Subject: [PATCH 16/17] Order data/action tracks events --- WooCommerce/Classes/Analytics/WooAnalyticsStat.swift | 2 ++ .../Classes/ViewRelated/Orders/OrdersViewController.swift | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift index 2f11c03bd0d..cfd7a31e326 100644 --- a/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift +++ b/WooCommerce/Classes/Analytics/WooAnalyticsStat.swift @@ -109,6 +109,8 @@ public enum WooAnalyticsStat: String { case orderNoteAddSuccess = "order_note_add_success" case orderNoteAddFailed = "order_note_add_failed" case orderContactAction = "order_contact_action" + case ordersListFilterOrSearch = "orders_list_filter" + case ordersListLoaded = "orders_list_loaded" // Notification Events // diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift index 06b9fcff019..6ac1440c669 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrdersViewController.swift @@ -211,6 +211,9 @@ private extension OrdersViewController { func didChangeFilter(newFilter: OrderStatus?) { WooAnalytics.shared.track(.filterOrdersOptionSelected, withProperties: ["status": newFilter?.rawValue ?? String()]) + WooAnalytics.shared.track(.ordersListFilterOrSearch, + withProperties: ["filter": newFilter?.rawValue ?? String(), + "search": ""]) // Display the Filter in the Title refreshTitle() @@ -261,6 +264,8 @@ extension OrdersViewController: SyncingCoordinatorDelegate { if let error = error { DDLogError("⛔️ Error synchronizing orders: \(error)") self.displaySyncingErrorNotice(pageNumber: pageNumber, pageSize: pageSize) + } else { + WooAnalytics.shared.track(.ordersListLoaded, withProperties: ["status": self.statusFilter?.rawValue ?? String()]) } self.transitionToResultsUpdatedState() From 197455d5fff241789512a1fc092e28535e1bdb8d Mon Sep 17 00:00:00 2001 From: Matt Bumgardner Date: Wed, 26 Sep 2018 23:15:16 -0500 Subject: [PATCH 17/17] Merge fix --- .../Orders/OrderDetails/OrderDetailsViewController.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift index 28aae276d77..149b47d170d 100644 --- a/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift +++ b/WooCommerce/Classes/ViewRelated/Orders/OrderDetails/OrderDetailsViewController.swift @@ -613,10 +613,9 @@ extension OrderDetailsViewController: MFMailComposeViewControllerDelegate { } sendEmail(to: email) - WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": viewModel.order.orderID, - "status": viewModel.order.status.rawValue, - "type": "email"]) - } + WooAnalytics.shared.track(.orderContactAction, withProperties: ["id": viewModel.order.orderID, + "status": viewModel.order.status.rawValue, + "type": "email"]) } private func sendEmail(to email: String) {