diff --git a/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift b/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift index 7b7daa42c266..252f15b2b661 100644 --- a/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift +++ b/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift @@ -12,21 +12,32 @@ class ContentMigrationCoordinator { private let dataMigrator: ContentDataMigrating private let userPersistentRepository: UserPersistentRepository private let eligibilityProvider: ContentMigrationEligibilityProvider + private let tracker: MigrationAnalyticsTracker init(coreDataStack: CoreDataStack = ContextManager.shared, dataMigrator: ContentDataMigrating = DataMigrator(), userPersistentRepository: UserPersistentRepository = UserDefaults.standard, - eligibilityProvider: ContentMigrationEligibilityProvider = AppConfiguration()) { + eligibilityProvider: ContentMigrationEligibilityProvider = AppConfiguration(), + tracker: MigrationAnalyticsTracker = .init()) { self.coreDataStack = coreDataStack self.dataMigrator = dataMigrator self.userPersistentRepository = userPersistentRepository self.eligibilityProvider = eligibilityProvider + self.tracker = tracker } - enum ContentMigrationCoordinatorError: Error { + enum ContentMigrationCoordinatorError: LocalizedError { case ineligible case exportFailure case localDraftsNotSynced + + var errorDescription: String? { + switch self { + case .ineligible: return "Content export is ineligible" + case .exportFailure: return "Content export failed" + case .localDraftsNotSynced: return "Local drafts not synced" + } + } } // MARK: Methods @@ -41,22 +52,27 @@ class ContentMigrationCoordinator { /// - Parameter completion: Closure called after the export process completes. func startAndDo(completion: ((Result) -> Void)? = nil) { guard eligibilityProvider.isEligibleForMigration else { + tracker.trackContentExportEligibility(eligible: false) completion?(.failure(.ineligible)) return } guard isLocalPostsSynced() else { - completion?(.failure(.localDraftsNotSynced)) + let error = ContentMigrationCoordinatorError.localDraftsNotSynced + tracker.trackContentExportFailed(reason: error.localizedDescription) + completion?(.failure(error)) return } - dataMigrator.exportData { result in + dataMigrator.exportData { [weak self] result in switch result { case .success: + self?.tracker.trackContentExportSucceeded() completion?(.success(())) case .failure(let error): DDLogError("[Jetpack Migration] Error exporting data: \(error)") + self?.tracker.trackContentExportFailed(reason: error.localizedDescription) completion?(.failure(.exportFailure)) } } diff --git a/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift b/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift index 4c1dc1f4c1cf..77f74cf2bcd8 100644 --- a/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift +++ b/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift @@ -101,12 +101,17 @@ private extension JetpackWindowManager { func showLoadWordPressUI(schemeUrl: URL) { let actions = MigrationLoadWordPressViewModel.Actions() let loadWordPressViewModel = MigrationLoadWordPressViewModel(actions: actions) - let loadWordPressViewController = MigrationLoadWordPressViewController(viewModel: loadWordPressViewModel) - actions.primary = { + let loadWordPressViewController = MigrationLoadWordPressViewController( + viewModel: loadWordPressViewModel, + tracker: migrationTracker + ) + actions.primary = { [weak self] in + self?.migrationTracker.track(.loadWordPressScreenOpenTapped) UIApplication.shared.open(schemeUrl) } - actions.secondary = { [weak self] in - loadWordPressViewController.dismiss(animated: true) { + actions.secondary = { [weak self, weak loadWordPressViewController] in + self?.migrationTracker.track(.loadWordPressScreenNoThanksTapped) + loadWordPressViewController?.dismiss(animated: true) { self?.showSignInUI() } } diff --git a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationAnalyticsTracker.swift b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationAnalyticsTracker.swift index 1036efb7106e..2ac2f3ddcff5 100644 --- a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationAnalyticsTracker.swift +++ b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationAnalyticsTracker.swift @@ -9,6 +9,22 @@ struct MigrationAnalyticsTracker { WPAnalytics.track(event) } + // MARK: - Content Export + + func trackContentExportEligibility(eligible: Bool) { + let properties = ["eligible": String(eligible)] + self.track(.contentExportEligibility, properties: properties) + } + + func trackContentExportSucceeded() { + self.track(.contentExportSucceeded) + } + + func trackContentExportFailed(reason: String) { + let properties = ["error_type": reason] + self.track(.contentExportFailed, properties: properties) + } + // MARK: - Content Import func trackContentImportEligibility(eligible: Bool) { diff --git a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationEvent.swift b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationEvent.swift index 4767016bcf58..c1de02f1f627 100644 --- a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationEvent.swift +++ b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/Analytics/MigrationEvent.swift @@ -1,6 +1,11 @@ import Foundation enum MigrationEvent: String { + // Content Export + case contentExportEligibility = "migration_content_export_eligibility" + case contentExportSucceeded = "migration_content_export_succeeded" + case contentExportFailed = "migration_content_export_failed" + // Content Import case contentImportEligibility = "migration_content_import_eligibility" case contentImportSucceeded = "migration_content_import_succeeded" @@ -37,6 +42,11 @@ enum MigrationEvent: String { case pleaseDeleteWordPressScreenHelpTapped = "migration_please_delete_wordpress_screen_help_tapped" case pleaseDeleteWordPressScreenCloseTapped = "migration_please_delete_wordpress_screen_close_tapped" - // WordPress Migratable Stat + // Load WordPress + case loadWordPressScreenShown = "migration_load_wordpress_screen_shown" + case loadWordPressScreenOpenTapped = "migration_load_wordpress_screen_open_tapped" + case loadWordPressScreenNoThanksTapped = "migration_load_wordpress_screen_no_thanks_tapped" + + // WordPress Migratable State case wordPressDetected = "migration_wordpressapp_detected" } diff --git a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Load WordPress/MigrationLoadWordPressViewController.swift b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Load WordPress/MigrationLoadWordPressViewController.swift index 259ac3feab50..0fa9c7de23e2 100644 --- a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Load WordPress/MigrationLoadWordPressViewController.swift +++ b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Load WordPress/MigrationLoadWordPressViewController.swift @@ -5,11 +5,13 @@ class MigrationLoadWordPressViewController: UIViewController { // MARK: - Dependencies private let viewModel: MigrationLoadWordPressViewModel + private let tracker: MigrationAnalyticsTracker // MARK: - Init - init(viewModel: MigrationLoadWordPressViewModel) { + init(viewModel: MigrationLoadWordPressViewModel, tracker: MigrationAnalyticsTracker = .init()) { self.viewModel = viewModel + self.tracker = tracker super.init(nibName: nil, bundle: nil) } @@ -32,4 +34,9 @@ class MigrationLoadWordPressViewController: UIViewController { super.viewDidLoad() self.view.backgroundColor = MigrationAppearance.backgroundColor } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + self.tracker.track(.loadWordPressScreenShown) + } }