Skip to content

Commit deb7e6b

Browse files
Jetpack Setup: Update tracking for setup flow (#15999)
2 parents d051c95 + 14d3f01 commit deb7e6b

File tree

11 files changed

+144
-232
lines changed

11 files changed

+144
-232
lines changed

WooCommerce/Classes/Analytics/WooAnalytics.swift

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import UIKit
44
import WordPressShared
55
import WidgetKit
66
import enum Alamofire.AFError
7+
import enum Networking.NetworkError
78
import Yosemite
89
import protocol WooFoundation.Analytics
910
import protocol WooFoundation.AnalyticsProvider
@@ -218,29 +219,31 @@ private extension Analytics {
218219
return nil
219220
}
220221

221-
let err = error as NSError
222+
let nsError = error as NSError
222223
let errorCode: String = {
223-
if let networkError = error as? AFError {
224-
if let responseCode = networkError.responseCode {
225-
return "\(responseCode)"
226-
} else if let underlyingError = networkError.underlyingError as? NSError {
227-
return "\(underlyingError.code)"
224+
if let networkError = error as? NetworkError, let code = networkError.responseCode {
225+
return code.description
226+
} else if let afError = error as? AFError {
227+
if let responseCode = afError.responseCode {
228+
return responseCode.description
229+
} else if let underlyingError = afError.underlyingError as? NSError {
230+
return underlyingError.code.description
228231
}
229232
} else if let loginError = error as? SiteCredentialLoginError {
230-
return "\(loginError.underlyingError.code)"
233+
return loginError.underlyingError.code.description
231234
}
232-
return "\(err.code)"
235+
return nsError.code.description
233236
}()
234237

235238
let errorDomain: String = {
236239
if let networkError = error as? AFError,
237240
let underlyingError = networkError.underlyingError as? NSError {
238241
return underlyingError.domain
239242
}
240-
return err.domain
243+
return nsError.domain
241244
}()
242245

243-
let errorDescription = err.description
246+
let errorDescription = nsError.description
244247

245248
return [
246249
Constants.errorKeyCode: errorCode,

WooCommerce/Classes/Analytics/WooAnalyticsEvent+JetpackSetup.swift

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ extension WooAnalyticsEvent {
99
case tap
1010
case step
1111
case isSignup = "is_signup"
12+
case connectionType = "connection_type"
13+
case usingApplicationPassword = "is_using_application_password"
1214
}
1315

1416
enum LoginFlow {
@@ -35,6 +37,11 @@ extension WooAnalyticsEvent {
3537
}
3638
}
3739

40+
enum ConnectionType: String {
41+
case native
42+
case web
43+
}
44+
3845
static func connectionCheckCompleted(isAlreadyConnected: Bool, requiresConnectionOnly: Bool) -> WooAnalyticsEvent {
3946
.init(statName: .jetpackSetupConnectionCheckCompleted, properties: [
4047
Key.isAlreadyConnected.rawValue: isAlreadyConnected,
@@ -56,8 +63,24 @@ extension WooAnalyticsEvent {
5663
return .init(statName: .jetpackSetupLoginFlow, properties: properties, error: failure)
5764
}
5865

59-
static func setupFlow(step: JetpackInstallStep, tap: SetupFlow.TapTarget? = nil, failure: Error? = nil) -> WooAnalyticsEvent {
60-
var properties: [String: WooAnalyticsEventPropertyType] = [Key.step.rawValue: step.analyticsValue]
66+
static func setupFlow(step: JetpackInstallStep,
67+
tap: SetupFlow.TapTarget? = nil,
68+
connectionType: ConnectionType,
69+
failure: Error? = nil) -> WooAnalyticsEvent {
70+
let isApplicationPassword: Bool = {
71+
let credentials = ServiceLocator.stores.sessionManager.defaultCredentials
72+
switch credentials {
73+
case .some(.applicationPassword):
74+
return true
75+
default:
76+
return false
77+
}
78+
}()
79+
var properties: [String: WooAnalyticsEventPropertyType] = [
80+
Key.step.rawValue: step.analyticsValue,
81+
Key.connectionType.rawValue: connectionType.rawValue,
82+
Key.usingApplicationPassword.rawValue: isApplicationPassword
83+
]
6184
if let tap {
6285
properties[Key.tap.rawValue] = tap.rawValue
6386
}

WooCommerce/Classes/Analytics/WooAnalyticsStat.swift

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -107,32 +107,6 @@ enum WooAnalyticsStat: String {
107107
case loginSiteCredentialsAppPasswordLoginExitConfirmation = "login_site_credentials_app_password_login_exit_confirmation"
108108
case loginSiteCredentialsAppPasswordLoginDismissed = "login_site_credentials_app_password_login_dismissed"
109109

110-
111-
// MARK: Install/Setup Jetpack (`LoginJetpackSetupView`)
112-
//
113-
case loginJetpackSetupScreenViewed = "login_jetpack_setup_screen_viewed"
114-
case loginJetpackSetupScreenDismissed = "login_jetpack_setup_screen_dismissed"
115-
116-
case loginJetpackSetupScreenInstallSuccessful = "login_jetpack_setup_install_successful"
117-
case loginJetpackSetupScreenInstallFailed = "login_jetpack_setup_install_failed"
118-
119-
case loginJetpackSetupActivationSuccessful = "login_jetpack_setup_activation_successful"
120-
case loginJetpackSetupActivationFailed = "login_jetpack_setup_activation_failed"
121-
122-
case loginJetpackSetupFetchJetpackConnectionURLSuccessful = "login_jetpack_setup_fetch_jetpack_connection_url_successful"
123-
case loginJetpackSetupFetchJetpackConnectionURLFailed = "login_jetpack_setup_fetch_jetpack_connection_url_failed"
124-
125-
case loginJetpackSetupCannotFindWPCOMUser = "login_jetpack_setup_cannot_find_WPCOM_user"
126-
case loginJetpackSetupAllStepsMarkedDone = "login_jetpack_setup_all_steps_marked_done"
127-
case loginJetpackSetupErrorCheckingJetpackConnection = "login_jetpack_setup_error_checking_jetpack_connection"
128-
129-
case loginJetpackSetupGoToStoreTapped = "login_jetpack_setup_go_to_store_button_tapped"
130-
131-
case loginJetpackSetupAuthorizedUsingDifferentWPCOMAccount = "login_jetpack_setup_authorized_using_different_wpcom_account"
132-
133-
case loginJetpackSetupScreenTryAgainButtonTapped = "login_jetpack_setup_try_again_button_tapped"
134-
case loginJetpackSetupScreenGetSupportTapped = "login_jetpack_setup_get_support_button_tapped"
135-
136110
// MARK: No matched site alert
137111
//
138112
case loginJetpackNoMatchedSiteErrorViewed = "login_jetpack_no_matched_site_error_viewed"

WooCommerce/Classes/Authentication/Jetpack Setup/LoginJetpackSetupCoordinator.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ private extension LoginJetpackSetupCoordinator {
5252
guard let self, let email = connectedEmail else { return }
5353
if email != self.stores.sessionManager.defaultAccount?.email {
5454
// if the user authorized Jetpack with a different account, support them to log in with that account.
55-
self.analytics.track(.loginJetpackSetupAuthorizedUsingDifferentWPCOMAccount)
5655
self.showVerifyWPComAccount(email: email)
5756
} else {
5857
// dismiss the setup view

WooCommerce/Classes/Authentication/Jetpack Setup/Native Jetpack Setup/JetpackSetupView.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ final class JetpackSetupHostingController: UIHostingController<JetpackSetupView>
3232

3333
rootView.supportHandler = { [weak self] in
3434
guard let self else { return }
35-
36-
self.viewModel.trackSetupDuringLogin(.loginJetpackSetupScreenGetSupportTapped, properties: self.viewModel.currentSetupStep?.analyticsDescription)
37-
self.viewModel.trackSetupAfterLogin(tap: .support)
35+
self.viewModel.trackSetup(tap: .support)
3836
self.presentSupport()
3937
}
4038

@@ -48,8 +46,6 @@ final class JetpackSetupHostingController: UIHostingController<JetpackSetupView>
4846

4947
override func viewDidLoad() {
5048
super.viewDidLoad()
51-
52-
viewModel.trackSetupDuringLogin(.loginJetpackSetupScreenViewed)
5349
configureNavigationBarAppearance()
5450
}
5551

@@ -62,8 +58,7 @@ final class JetpackSetupHostingController: UIHostingController<JetpackSetupView>
6258

6359
@objc
6460
private func dismissView() {
65-
viewModel.trackSetupDuringLogin(.loginJetpackSetupScreenDismissed, properties: viewModel.currentSetupStep?.analyticsDescription)
66-
viewModel.trackSetupAfterLogin(tap: .dismiss)
61+
viewModel.trackSetup(tap: .dismiss)
6762
dismiss(animated: true)
6863
}
6964

WooCommerce/Classes/Authentication/Jetpack Setup/Native Jetpack Setup/JetpackSetupViewModel.swift

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ final class JetpackSetupViewModel: ObservableObject {
1717
private let storeNavigationHandler: (_ connectedEmail: String?) -> Void
1818
private let wpcomCredentials: Credentials?
1919
private var isPluginActivated = false
20+
private var connectionType = WooAnalyticsEvent.JetpackSetup.ConnectionType.native
2021

2122
@Published private(set) var setupSteps: [JetpackInstallStep]
2223

@@ -151,15 +152,12 @@ final class JetpackSetupViewModel: ObservableObject {
151152
}
152153

153154
func navigateToStore() {
154-
trackSetupDuringLogin(.loginJetpackSetupGoToStoreTapped)
155-
trackSetupAfterLogin(tap: .goToStore)
155+
trackSetup(tap: .goToStore)
156156
storeNavigationHandler(jetpackConnectedEmail)
157157
}
158158

159159
func retryAllSteps() {
160-
trackSetupDuringLogin(.loginJetpackSetupScreenTryAgainButtonTapped,
161-
properties: currentSetupStep?.analyticsDescription)
162-
trackSetupAfterLogin(tap: .retry)
160+
trackSetup(tap: .retry)
163161

164162
setupFailed = false
165163
setupError = nil
@@ -172,31 +170,18 @@ final class JetpackSetupViewModel: ObservableObject {
172170

173171
/// LoginJetpackSetupInterruptedView
174172
func didTapContinueConnectionButton() {
175-
trackSetupDuringLogin(.loginJetpackSetupScreenTryAgainButtonTapped)
176-
trackSetupAfterLogin(tap: .continueSetup)
173+
trackSetup(tap: .continueSetup)
177174
checkJetpackConnection(afterConnection: false)
178175
}
179176

180-
/// Tracks events if the current flow is Jetpack setup during login
181-
func trackSetupDuringLogin(_ stat: WooAnalyticsStat,
182-
properties: [AnyHashable: Any]? = nil,
183-
failure: Error? = nil) {
184-
guard stores.isAuthenticated == false else {
185-
return
186-
}
187-
analytics.track(stat, properties: properties, error: failure)
188-
}
189-
190177
/// Tracks events if the current flow is Jetpack setup after login with site credentials
191-
func trackSetupAfterLogin(tap: WooAnalyticsEvent.JetpackSetup.SetupFlow.TapTarget? = nil,
192-
failure: Error? = nil) {
193-
guard stores.isAuthenticated else {
194-
return
195-
}
178+
func trackSetup(tap: WooAnalyticsEvent.JetpackSetup.SetupFlow.TapTarget? = nil,
179+
failure: Error? = nil) {
196180
/// Helper for analytics since `currentSetupStep` is optional.
197181
let currentStepForAnalytics: JetpackInstallStep = currentSetupStep ?? (connectionOnly ? .connection : .installation)
198182
analytics.track(event: .JetpackSetup.setupFlow(step: currentStepForAnalytics,
199183
tap: tap,
184+
connectionType: connectionType,
200185
failure: failure))
201186
}
202187
}
@@ -236,17 +221,15 @@ private extension JetpackSetupViewModel {
236221

237222
func installJetpack() {
238223
currentSetupStep = .installation
239-
trackSetupAfterLogin()
224+
trackSetup()
240225

241226
let action = JetpackConnectionAction.installJetpackPlugin { [weak self] result in
242227
guard let self else { return }
243228
switch result {
244229
case .success:
245-
self.trackSetupDuringLogin(.loginJetpackSetupScreenInstallSuccessful)
246230
self.activateJetpack()
247231
case .failure(let error):
248-
self.trackSetupDuringLogin(.loginJetpackSetupScreenInstallFailed, failure: error)
249-
self.trackSetupAfterLogin(failure: error)
232+
self.trackSetup(failure: error)
250233
DDLogError("⛔️ Error installing Jetpack: \(error)")
251234
self.setupError = error
252235
self.setupFailed = true
@@ -257,17 +240,15 @@ private extension JetpackSetupViewModel {
257240

258241
func activateJetpack() {
259242
currentSetupStep = .activation
260-
trackSetupAfterLogin()
243+
trackSetup()
261244
let action = JetpackConnectionAction.activateJetpackPlugin { [weak self] result in
262245
guard let self else { return }
263246
switch result {
264247
case .success:
265248
isPluginActivated = true
266-
self.trackSetupDuringLogin(.loginJetpackSetupActivationSuccessful)
267249
self.checkJetpackConnection(afterConnection: false)
268250
case .failure(let error):
269-
self.trackSetupDuringLogin(.loginJetpackSetupActivationFailed, failure: error)
270-
self.trackSetupAfterLogin(failure: error)
251+
self.trackSetup(failure: error)
271252
DDLogError("⛔️ Error activating Jetpack: \(error)")
272253
self.setupError = error
273254
self.setupFailed = true
@@ -281,12 +262,12 @@ private extension JetpackSetupViewModel {
281262
///
282263
func startConnectionWithWebView() {
283264
currentSetupStep = .connection
284-
trackSetupAfterLogin()
265+
connectionType = .web
266+
trackSetup()
285267
let action = JetpackConnectionAction.fetchJetpackConnectionURL { [weak self] result in
286268
guard let self else { return }
287269
switch result {
288270
case .success(let url):
289-
self.trackSetupDuringLogin(.loginJetpackSetupFetchJetpackConnectionURLSuccessful)
290271
/// Checks if the fetch URL is for account connection;
291272
/// if not, use the web view solution to avoid the need for cookie-nonce.
292273
/// Reference: pe5sF9-1le-p2#comment-1942.
@@ -297,8 +278,7 @@ private extension JetpackSetupViewModel {
297278
}
298279
self.shouldPresentWebView = true
299280
case .failure(let error):
300-
self.trackSetupDuringLogin(.loginJetpackSetupFetchJetpackConnectionURLFailed, failure: error)
301-
self.trackSetupAfterLogin(failure: error)
281+
self.trackSetup(failure: error)
302282
DDLogError("⛔️ Error fetching Jetpack connection URL: \(error)")
303283
self.setupError = error
304284
self.setupFailed = true
@@ -369,7 +349,6 @@ private extension JetpackSetupViewModel {
369349
let missingWpcomUserError = NSError(domain: Constants.errorDomain,
370350
code: Constants.errorCodeNoWPComUser,
371351
userInfo: [Constants.errorUserInfoReason: Constants.errorUserInfoNoWPComUser])
372-
trackSetupDuringLogin(.loginJetpackSetupCannotFindWPCOMUser, failure: missingWpcomUserError)
373352
if retryCount == Constants.maxRetryCount {
374353
return didFailJetpackConnection(with: missingWpcomUserError)
375354
}
@@ -436,7 +415,7 @@ private extension JetpackSetupViewModel {
436415

437416
func provisionSiteConnection(blogID: Int64) {
438417
currentSetupStep = .connection
439-
trackSetupAfterLogin()
418+
trackSetup()
440419
stores.dispatch(JetpackConnectionAction.provisionConnection(completion: { [weak self] result in
441420
guard let self else { return }
442421
switch result {
@@ -475,17 +454,13 @@ private extension JetpackSetupViewModel {
475454
jetpackConnectedEmail = connectedEmail
476455
currentConnectionStep = .authorized
477456
currentSetupStep = .done
478-
479-
trackSetupDuringLogin(.loginJetpackSetupAllStepsMarkedDone)
480-
trackSetupAfterLogin()
457+
trackSetup()
481458
}
482459

483460
func didFailJetpackConnection(with error: Error) {
484-
setupFailed = true
485461
setupError = error
486-
if let setupError {
487-
analytics.track(.loginJetpackSetupErrorCheckingJetpackConnection, withError: setupError)
488-
}
462+
trackSetup(failure: error)
463+
setupFailed = true
489464
}
490465
}
491466

WooCommerce/Classes/ViewRelated/Dashboard/JCPJetpackInstall/JetpackInstallSteps.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,6 @@ extension JetpackInstallStep {
9797
}
9898
}
9999

100-
/// Description dictionary for Analytics
101-
///
102-
var analyticsDescription: [String: String] {
103-
["jetpack_install_step": analyticsValue]
104-
}
105-
106100
var analyticsValue: String {
107101
switch self {
108102
case .installation:

0 commit comments

Comments
 (0)