Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Domain Purchasing] Add A/B Experiment #20590

5 changes: 4 additions & 1 deletion WordPress/Classes/Services/SiteAddressService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ final class DomainsServiceAdapter: SiteAddressService {

// MARK: Properties

private let domainPurchasingEnabled = FeatureFlag.siteCreationDomainPurchasing.enabled
/// Checks if the Domain Purchasing Feature Flag and AB Experiment are enabled
private var domainPurchasingEnabled: Bool {
FeatureFlag.siteCreationDomainPurchasing.enabled && ABTest.siteCreationDomainPurchasing.isTreatmentVariation
}

/**
Corresponds to:
Expand Down
22 changes: 16 additions & 6 deletions WordPress/Classes/Utility/AB Testing/ABTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,35 @@ import AutomatticTracks
// Jetpack is not supported
enum ABTest: String, CaseIterable {
case unknown = "unknown"
case siteCreationDomainPurchasing = "jpios_site_creation_domain_purchasing_v1"

/// Returns a variation for the given experiment
var variation: Variation {
return ExPlat.shared?.experiment(self.rawValue) ?? .control
}

/// Flag indicating whether the experiment's variation is treament or not.
var isTreatmentVariation: Bool {
switch variation {
case .treatment, .customTreatment: return true
case .control: return false
}
}
}

extension ABTest {
/// Start the AB Testing platform if any experiment exists
///
static func start() {
guard ABTest.allCases.count > 1, AccountHelper.isLoggedIn,
AppConfiguration.isWordPress else {
guard ABTest.allCases.count > 1,
AccountHelper.isLoggedIn,
AppConfiguration.isJetpack,
let exPlat = ExPlat.shared
else {
return
}

let experimentNames = ABTest.allCases.filter { $0 != .unknown }.map { $0.rawValue }
ExPlat.shared?.register(experiments: experimentNames)

ExPlat.shared?.refresh()
Comment on lines -24 to -26
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you moved these to the guard 👍

exPlat.register(experiments: experimentNames)
exPlat.refresh()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import Foundation

extension WPAnalytics {

/// Checks if the Domain Purchasing Feature Flag and AB Experiment are enabled
private static var domainPurchasingEnabled: Bool {
FeatureFlag.siteCreationDomainPurchasing.enabled && ABTest.siteCreationDomainPurchasing.isTreatmentVariation
}

static func domainsProperties(for blog: Blog) -> [AnyHashable: Any] {
// For now we do not have the `siteCreation` route implemented so hardcoding `menu`
domainsProperties(usingCredit: blog.canRegisterDomainWithPaidPlan, origin: .menu)
Expand All @@ -11,7 +17,7 @@ extension WPAnalytics {
origin: DomainPurchaseWebViewViewOrigin?
) -> [AnyHashable: Any] {
var dict: [AnyHashable: Any] = ["using_credit": usingCredit.stringLiteral]
if FeatureFlag.siteCreationDomainPurchasing.enabled,
if Self.domainPurchasingEnabled,
let origin = origin {
dict["origin"] = origin.rawValue
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extension BlogListViewController {
return
}
self.present(wizard, animated: true)
WPAnalytics.track(.enhancedSiteCreationAccessed, withProperties: ["source": source])
SiteCreationAnalyticsHelper.trackSiteCreationAccessed(source: source)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ class MySiteViewController: UIViewController, NoResultsViewHost {
return
}
self.present(wizard, animated: true)
WPAnalytics.track(.enhancedSiteCreationAccessed, withProperties: ["source": source])
SiteCreationAnalyticsHelper.trackSiteCreationAccessed(source: source)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ extension WordPressAuthenticationManager: WordPressAuthenticatorDelegate {
}

navigationController.present(wizard, animated: true)
WPAnalytics.track(.enhancedSiteCreationAccessed, withProperties: ["source": source])
SiteCreationAnalyticsHelper.trackSiteCreationAccessed(source: source)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ final class SiteAssemblyContentView: UIView {
label.font = WPStyleGuide.fontForTextStyle(.title1, fontWeight: .bold)
label.textColor = .text

if FeatureFlag.siteCreationDomainPurchasing.enabled {
if siteCreator.domainPurchasingEnabled {
label.textAlignment = .natural
} else {
label.textAlignment = .center
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Foundation

enum SiteCreationAnalyticsEvent: String {
case domainPurchasingExperiment = "site_creation_domain_purchasing_experiment"
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,25 @@ class SiteCreationAnalyticsHelper {
private static let variationKey = "variation"
private static let siteNameKey = "site_name"
private static let recommendedKey = "recommended"
private static let customTreatmentNameKey = "custom_treatment_variation_name"

// MARK: - Lifecycle
static func trackSiteCreationAccessed(source: String) {
WPAnalytics.track(.enhancedSiteCreationAccessed, withProperties: ["source": source])

if FeatureFlag.siteCreationDomainPurchasing.enabled {
let domainPurchasingExperimentProperties: [String: String] = {
var dict: [String: String] = [Self.variationKey: ABTest.siteCreationDomainPurchasing.variation.tracksProperty]

if case let .customTreatment(name) = ABTest.siteCreationDomainPurchasing.variation {
dict[Self.customTreatmentNameKey] = name
}

return dict
}()
Self.track(.domainPurchasingExperiment, properties: domainPurchasingExperimentProperties)
}
}

// MARK: - Site Intent
static func trackSiteIntentViewed() {
Expand Down Expand Up @@ -137,6 +156,11 @@ class SiteCreationAnalyticsHelper {
}

// MARK: - Common
private static func track(_ event: SiteCreationAnalyticsEvent, properties: [String: String] = [:]) {
let event = AnalyticsEvent(name: event.rawValue, properties: properties)
WPAnalytics.track(event)
}

private static func commonProperties(_ properties: Any?...) -> [AnyHashable: Any] {
var result: [AnyHashable: Any] = [:]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ final class AddressTableViewCell: UITableViewCell {

// MARK: - Dependencies

private let domainPurchasingEnabled = FeatureFlag.siteCreationDomainPurchasing.enabled
private var domainPurchasingEnabled: Bool {
FeatureFlag.siteCreationDomainPurchasing.enabled && ABTest.siteCreationDomainPurchasing.isTreatmentVariation
}

// MARK: - Views

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
return .hidden
}

/// Checks if the Domain Purchasing Feature Flag is enabled
private let domainPurchasingEnabled = FeatureFlag.siteCreationDomainPurchasing.enabled
/// Checks if the Domain Purchasing Feature Flag and AB Experiment are enabled
private var domainPurchasingEnabled: Bool {
return siteCreator.domainPurchasingEnabled
}

/// The creator collects user input as they advance through the wizard flow.
private let siteCreator: SiteCreator
Expand Down Expand Up @@ -146,7 +148,7 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
}

private func configureUIIfNeeded() {
guard FeatureFlag.siteCreationDomainPurchasing.enabled else {
guard domainPurchasingEnabled else {
return
}

Expand All @@ -160,7 +162,7 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {

private func loadHeaderView() {

if FeatureFlag.siteCreationDomainPurchasing.enabled {
if domainPurchasingEnabled {
searchBar.searchBarStyle = UISearchBar.Style.default
searchBar.translatesAutoresizingMaskIntoConstraints = false
WPStyleGuide.configureSearchBar(searchBar, backgroundColor: .clear, returnKeyType: .search)
Expand Down Expand Up @@ -215,9 +217,9 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
updateNoResultsLabelTopInset()

coordinator.animate(alongsideTransition: nil) { [weak self] (_) in
guard let `self` = self else { return }
guard let self else { return }

if FeatureFlag.siteCreationDomainPurchasing.enabled {
if self.domainPurchasingEnabled {
if !self.siteTemplateHostingController.view.isHidden {
self.updateTitleViewVisibility(true)
}
Expand Down Expand Up @@ -332,7 +334,7 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
}

private func restoreSearchIfNeeded() {
if FeatureFlag.siteCreationDomainPurchasing.enabled {
if domainPurchasingEnabled {
search(searchBar.text)
} else {
search(query(from: searchTextField))
Expand Down Expand Up @@ -422,7 +424,7 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
"search_term": lastSearchQuery as AnyObject
]

if FeatureFlag.siteCreationDomainPurchasing.enabled {
if domainPurchasingEnabled {
domainSuggestionProperties["domain_cost"] = domainSuggestion.costString
}

Expand All @@ -447,15 +449,15 @@ final class WebAddressWizardContent: CollapsableHeaderViewController {
// MARK: - Search logic

private func setAddressHintVisibility(isHidden: Bool) {
if FeatureFlag.siteCreationDomainPurchasing.enabled {
if domainPurchasingEnabled {
siteTemplateHostingController.view?.isHidden = isHidden
} else {
sitePromptView.isHidden = isHidden
}
}

private func addAddressHintView() {
if FeatureFlag.siteCreationDomainPurchasing.enabled {
if domainPurchasingEnabled {
guard let siteCreationView = siteTemplateHostingController.view else {
return
}
Expand Down Expand Up @@ -661,7 +663,7 @@ extension WebAddressWizardContent: UITableViewDelegate {
let domainSuggestion = data[indexPath.row]
self.selectedDomain = domainSuggestion

if FeatureFlag.siteCreationDomainPurchasing.enabled {
if domainPurchasingEnabled {
searchBar.resignFirstResponder()
} else {
searchTextField.resignFirstResponder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,14 @@ final class SiteCreator {
information?.title != nil
}

/// Checks if the Domain Purchasing Feature Flag and AB Experiment are enabled
var domainPurchasingEnabled: Bool {
FeatureFlag.siteCreationDomainPurchasing.enabled && ABTest.siteCreationDomainPurchasing.isTreatmentVariation
}

/// Flag indicating whether the domain checkout flow should appear or not.
var shouldShowDomainCheckout: Bool {
return FeatureFlag.siteCreationDomainPurchasing.enabled && !(address?.isFree ?? false)
domainPurchasingEnabled && !(address?.isFree ?? false)
}

/// Returns the domain suggestion if there's one,
Expand Down
6 changes: 6 additions & 0 deletions WordPress/WordPress.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3532,6 +3532,8 @@
F44FB6CB287895AF0001E3CE /* SuggestionsListViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F44FB6CA287895AF0001E3CE /* SuggestionsListViewModelTests.swift */; };
F44FB6CD287897F90001E3CE /* SuggestionsTableViewMockDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F44FB6CC287897F90001E3CE /* SuggestionsTableViewMockDelegate.swift */; };
F44FB6D12878A1020001E3CE /* user-suggestions.json in Resources */ = {isa = PBXBuildFile; fileRef = F44FB6D02878A1020001E3CE /* user-suggestions.json */; };
F45326D829F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45326D729F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift */; };
F45326D929F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45326D729F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift */; };
F4552086299D147B00D9F6A8 /* BlockedSite.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48D44B5298992C30051EAA6 /* BlockedSite.swift */; };
F465976E28E4669200D5F49A /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = F465976928E4669200D5F49A /* [email protected] */; };
F465976F28E4669200D5F49A /* cool-green-icon-app-76.png in Resources */ = {isa = PBXBuildFile; fileRef = F465976A28E4669200D5F49A /* cool-green-icon-app-76.png */; };
Expand Down Expand Up @@ -8890,6 +8892,7 @@
F44FB6CA287895AF0001E3CE /* SuggestionsListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionsListViewModelTests.swift; sourceTree = "<group>"; };
F44FB6CC287897F90001E3CE /* SuggestionsTableViewMockDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionsTableViewMockDelegate.swift; sourceTree = "<group>"; };
F44FB6D02878A1020001E3CE /* user-suggestions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "user-suggestions.json"; sourceTree = "<group>"; };
F45326D729F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteCreationAnalyticsEvent.swift; sourceTree = "<group>"; };
F465976928E4669200D5F49A /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
F465976A28E4669200D5F49A /* cool-green-icon-app-76.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "cool-green-icon-app-76.png"; sourceTree = "<group>"; };
F465976B28E4669200D5F49A /* [email protected] */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "[email protected]"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -12520,6 +12523,7 @@
738B9A5D21B8632E0005062B /* UITableView+Header.swift */,
738B9A5B21B85EB00005062B /* UIView+ContentLayout.swift */,
46D6114E2555DAED00B0B7BB /* SiteCreationAnalyticsHelper.swift */,
F45326D729F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift */,
);
path = Shared;
sourceTree = "<group>";
Expand Down Expand Up @@ -21083,6 +21087,7 @@
80A2154629D15B88002FE8EB /* RemoteConfigOverrideStore.swift in Sources */,
F4DDE2C229C92F0D00C02A76 /* CrashLogging+Singleton.swift in Sources */,
4629E4212440C5B20002E15C /* GutenbergCoverUploadProcessor.swift in Sources */,
F45326D829F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift in Sources */,
FF00889F204E01AE007CCE66 /* MediaQuotaCell.swift in Sources */,
982DDF94263238A6002B3904 /* LikeUserPreferredBlog+CoreDataClass.swift in Sources */,
F5844B6B235EAF3D007C6557 /* PartScreenPresentationController.swift in Sources */,
Expand Down Expand Up @@ -23804,6 +23809,7 @@
8B55F9EE2614D977007D618E /* UnifiedPrologueStatsContentView.swift in Sources */,
FABB21932602FC2C00C8785C /* GutenbergTenorMediaPicker.swift in Sources */,
3F8B45A029283D6C00730FA4 /* DashboardMigrationSuccessCell.swift in Sources */,
F45326D929F6B8A6005F9F31 /* SiteCreationAnalyticsEvent.swift in Sources */,
FA98B61A29A3BF050071AAE8 /* BlazeCardView.swift in Sources */,
FABB21942602FC2C00C8785C /* AztecPostViewController.swift in Sources */,
F1585442267D3BF900A2E966 /* CalendarDayToggleButton.swift in Sources */,
Expand Down