Skip to content

Commit 848f8a7

Browse files
Merge pull request #8170 from woocommerce/feat/8166-native-jetpack-installation-ab-testing
Native Jetpack Installation: Apply A/B test
2 parents 6d8fb05 + f61ea32 commit 848f8a7

File tree

8 files changed

+24
-43
lines changed

8 files changed

+24
-43
lines changed

Experiments/Experiments/ABTest.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ public enum ABTest: String, CaseIterable {
1616
///
1717
case abTestLoginWithWPComOnly = "woocommerceios_login_wpcom_only"
1818

19+
/// A/B test to measure the sign-in success rate when native Jetpack installation experience is enabled
20+
/// Experiment ref: pbxNRc-29W-p2
21+
///
22+
case nativeJetpackSetupFlow = "woocommerceios_login_jetpack_setup_flow"
23+
1924
/// A/B test for the Products Onboarding banner on the My Store dashboard.
2025
/// Experiment ref: pbxNRc-26F-p2
2126
case productsOnboardingBanner = "woocommerceios_products_onboarding_first_product_banner"
@@ -34,7 +39,7 @@ public enum ABTest: String, CaseIterable {
3439
/// When adding a new experiment, add it to the appropriate case depending on its context (logged-in or logged-out experience).
3540
public var context: ExperimentContext {
3641
switch self {
37-
case .productsOnboardingBanner, .productsOnboardingTemplateProducts:
42+
case .productsOnboardingBanner, .productsOnboardingTemplateProducts, .nativeJetpackSetupFlow:
3843
return .loggedIn
3944
case .aaTestLoggedOut, .abTestLoginWithWPComOnly:
4045
return .loggedOut
@@ -47,6 +52,7 @@ public enum ABTest: String, CaseIterable {
4752
public extension ABTest {
4853
/// Start the AB Testing platform if any experiment exists for the provided context
4954
///
55+
@MainActor
5056
static func start(for context: ExperimentContext) async {
5157
let experiments = ABTest.allCases.filter { $0.context == context }
5258

Experiments/Experiments/DefaultFeatureFlagService.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ public struct DefaultFeatureFlagService: FeatureFlagService {
5151
.performanceMonitoringUserInteraction:
5252
// Disabled by default to avoid costs spikes, unless in internal testing builds.
5353
return buildConfig == .alpha
54-
case .nativeJetpackSetupFlow:
55-
return buildConfig == .localDeveloper || buildConfig == .alpha
5654
case .analyticsHub:
5755
return buildConfig == .localDeveloper || buildConfig == .alpha
5856
case .tapToPayOnIPhone:

Experiments/Experiments/FeatureFlag.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,6 @@ public enum FeatureFlag: Int {
130130
/// - Note: The app will ignore this if `performanceMonitoring` is `false`.
131131
case performanceMonitoringViewController
132132

133-
/// Temporary feature flag for the native Jetpack setup flow.
134-
/// TODO-8075: replace this with A/B test.
135-
///
136-
case nativeJetpackSetupFlow
137-
138133
/// Temporary feature flag for the native Jetpack setup flow.
139134
///
140135
case analyticsHub

WooCommerce/Classes/Analytics/WooAnalytics.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Experiments
12
import Foundation
23
import UIKit
34
import WordPressShared
@@ -60,6 +61,15 @@ public extension WooAnalytics {
6061
}
6162

6263
analyticsProvider.refreshUserData()
64+
65+
// Refreshes A/B experiments since `ExPlat.shared` is reset after each `TracksProvider.refreshUserData` call
66+
// and any A/B test assignments that come back after the shared instance is reset won't be saved for later
67+
// access.
68+
let context: ExperimentContext = ServiceLocator.stores.isAuthenticated ?
69+
.loggedIn: .loggedOut
70+
Task { @MainActor in
71+
await ABTest.start(for: context)
72+
}
6373
}
6474

6575
/// Track a spcific event without any associated properties

WooCommerce/Classes/AppDelegate.swift

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,12 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
7373
// ever new source code is injected into our application.
7474
Inject.animation = .interactiveSpring()
7575

76-
Task { @MainActor in
77-
await startABTesting()
78-
79-
// Upgrade check...
80-
// This has to be called after A/B testing setup in `startABTesting` if any of the Tracks events
81-
// in `checkForUpgrades` is used as an exposure event for an experiment.
82-
// For example, `application_installed` could be the exposure event for logged-out experiments.
83-
checkForUpgrades()
84-
}
76+
// Upgrade check...
77+
// This has to be called after A/B testing setup in `setupAnalytics` (which calls
78+
// `WooAnalytics.refreshUserData`) if any of the Tracks events in `checkForUpgrades` is
79+
// used as an exposure event for an experiment.
80+
// For example, `application_installed` could be the exposure event for logged-out experiments.
81+
checkForUpgrades()
8582

8683
return true
8784
}
@@ -372,13 +369,6 @@ private extension AppDelegate {
372369
}
373370
}
374371

375-
/// Starts the AB testing platform and fetches test assignments for the current context
376-
///
377-
func startABTesting() async {
378-
let context: ExperimentContext = ServiceLocator.stores.isAuthenticated ? .loggedIn : .loggedOut
379-
await ABTest.start(for: context)
380-
}
381-
382372
/// Tracks if the application was opened via a widget tap.
383373
///
384374
func trackWidgetTappedIfNeeded(userActivity: NSUserActivity) {

WooCommerce/Classes/Authentication/AuthenticationManager.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,8 +761,7 @@ private extension AuthenticationManager {
761761
}
762762

763763
// Shows the native Jetpack flow during the site discovery flow.
764-
// TODO-8075: replace feature flag with A/B testing
765-
if featureFlagService.isFeatureFlagEnabled(.nativeJetpackSetupFlow) {
764+
if ABTest.nativeJetpackSetupFlow.variation != .control {
766765
return jetpackSetupUI(for: site.url,
767766
connectionMissingOnly: site.hasJetpack && site.isJetpackActive,
768767
in: navigationController)

WooCommerce/Classes/Authentication/Epilogue/StorePickerViewController.swift

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ final class StorePickerViewController: UIViewController {
201201
switch configuration {
202202
case .login:
203203
startListeningToNotifications()
204-
startABTesting()
205204
case .switchingStores:
206205
secondaryActionButton.isHidden = true
207206
default:
@@ -574,17 +573,6 @@ private extension StorePickerViewController {
574573
fancyAlert.transitioningDelegate = AppDelegate.shared.tabBarController
575574
present(fancyAlert, animated: true)
576575
}
577-
578-
/// Refreshes the AB testing assignments (refresh is needed after a user logs in)
579-
///
580-
func startABTesting() {
581-
guard ServiceLocator.stores.isAuthenticated else {
582-
return
583-
}
584-
Task { @MainActor in
585-
await ABTest.start(for: .loggedIn)
586-
}
587-
}
588576
}
589577

590578
// MARK: Transition Controller Delegate

WooCommerce/Classes/Yosemite/DefaultStoresManager.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,6 @@ class DefaultStoresManager: StoresManager {
178178

179179
updateAndReloadWidgetInformation(with: nil)
180180

181-
// Refresh the A/B test assignments for the logged-out context
182-
Task { @MainActor in
183-
await ABTest.start(for: .loggedOut)
184-
}
185-
186181
NotificationCenter.default.post(name: .logOutEventReceived, object: nil)
187182

188183
return self

0 commit comments

Comments
 (0)