Skip to content

Commit dfa7a73

Browse files
authored
Merge pull request #8337 from woocommerce/issue/8323-analytics-hub-used-analytics-event
[Analytics Hub] Add interactions to used analytics event
2 parents 3f1de9e + 2df386d commit dfa7a73

File tree

7 files changed

+60
-14
lines changed

7 files changed

+60
-14
lines changed

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsHubView.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ final class AnalyticsHubHostingViewController: UIHostingController<AnalyticsHubV
1515
///
1616
var notice: Notice?
1717

18-
init(siteID: Int64, timeRange: StatsTimeRangeV4, systemNoticePresenter: NoticePresenter = ServiceLocator.noticePresenter) {
19-
let viewModel = AnalyticsHubViewModel(siteID: siteID, statsTimeRange: timeRange)
18+
init(siteID: Int64,
19+
timeRange: StatsTimeRangeV4,
20+
systemNoticePresenter: NoticePresenter = ServiceLocator.noticePresenter,
21+
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter) {
22+
let viewModel = AnalyticsHubViewModel(siteID: siteID, statsTimeRange: timeRange, usageTracksEventEmitter: usageTracksEventEmitter)
2023
self.systemNoticePresenter = systemNoticePresenter
2124
super.init(rootView: AnalyticsHubView(viewModel: viewModel))
2225

@@ -56,6 +59,7 @@ struct AnalyticsHubView: View {
5659

5760
var body: some View {
5861
RefreshablePlainList(action: {
62+
viewModel.trackAnalyticsInteraction()
5963
await viewModel.updateData()
6064
}) {
6165
VStack(alignment: .leading, spacing: Layout.verticalSpacing) {
@@ -114,6 +118,12 @@ struct AnalyticsHubView: View {
114118
guard let notice else { return }
115119
dismissWithNotice(notice)
116120
}
121+
.gesture(
122+
// Detects when scrolling begins so it can be tracked.
123+
DragGesture().onChanged({ _ in
124+
viewModel.trackAnalyticsInteraction()
125+
})
126+
)
117127
}
118128
}
119129

@@ -135,7 +145,9 @@ private extension AnalyticsHubView {
135145
struct AnalyticsHubPreview: PreviewProvider {
136146
static var previews: some View {
137147
NavigationView {
138-
AnalyticsHubView(viewModel: AnalyticsHubViewModel(siteID: 123, statsTimeRange: .thisYear))
148+
AnalyticsHubView(viewModel: AnalyticsHubViewModel(siteID: 123,
149+
statsTimeRange: .thisYear,
150+
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter()))
139151
}
140152
}
141153
}

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsHubViewModel.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ final class AnalyticsHubViewModel: ObservableObject {
1212

1313
private var subscriptions = Set<AnyCancellable>()
1414

15+
/// Analytics Usage Tracks Event Emitter
16+
///
17+
private let usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter
18+
1519
init(siteID: Int64,
1620
statsTimeRange: StatsTimeRangeV4,
21+
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter,
1722
stores: StoresManager = ServiceLocator.stores) {
1823
let selectedType = AnalyticsHubTimeRangeSelection.SelectionType(statsTimeRange)
1924
let timeRangeSelection = AnalyticsHubTimeRangeSelection(selectionType: selectedType)
@@ -22,7 +27,8 @@ final class AnalyticsHubViewModel: ObservableObject {
2227
self.stores = stores
2328
self.timeRangeSelectionType = selectedType
2429
self.timeRangeSelection = timeRangeSelection
25-
self.timeRangeCard = AnalyticsHubViewModel.timeRangeCard(timeRangeSelection: timeRangeSelection)
30+
self.timeRangeCard = AnalyticsHubViewModel.timeRangeCard(timeRangeSelection: timeRangeSelection, usageTracksEventEmitter: usageTracksEventEmitter)
31+
self.usageTracksEventEmitter = usageTracksEventEmitter
2632

2733
bindViewModelsWithData()
2834
}
@@ -84,6 +90,12 @@ final class AnalyticsHubViewModel: ObservableObject {
8490
DDLogWarn("⚠️ Error fetching analytics data: \(error)")
8591
}
8692
}
93+
94+
/// Tracks interactions for analytics usage event
95+
///
96+
func trackAnalyticsInteraction() {
97+
usageTracksEventEmitter.interacted()
98+
}
8799
}
88100

89101
// MARK: Networking
@@ -189,7 +201,8 @@ private extension AnalyticsHubViewModel {
189201
.sink { [weak self] newSelectionType in
190202
guard let self else { return }
191203
self.timeRangeSelection = AnalyticsHubTimeRangeSelection(selectionType: newSelectionType)
192-
self.timeRangeCard = AnalyticsHubViewModel.timeRangeCard(timeRangeSelection: self.timeRangeSelection)
204+
self.timeRangeCard = AnalyticsHubViewModel.timeRangeCard(timeRangeSelection: self.timeRangeSelection,
205+
usageTracksEventEmitter: self.usageTracksEventEmitter)
193206
Task.init {
194207
await self.updateData()
195208
}
@@ -266,10 +279,12 @@ private extension AnalyticsHubViewModel {
266279
}
267280
}
268281

269-
static func timeRangeCard(timeRangeSelection: AnalyticsHubTimeRangeSelection) -> AnalyticsTimeRangeCardViewModel {
282+
static func timeRangeCard(timeRangeSelection: AnalyticsHubTimeRangeSelection,
283+
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter) -> AnalyticsTimeRangeCardViewModel {
270284
return AnalyticsTimeRangeCardViewModel(selectedRangeTitle: timeRangeSelection.rangeSelectionDescription,
271285
currentRangeSubtitle: timeRangeSelection.currentRangeDescription,
272-
previousRangeSubtitle: timeRangeSelection.previousRangeDescription)
286+
previousRangeSubtitle: timeRangeSelection.previousRangeDescription,
287+
usageTracksEventEmitter: usageTracksEventEmitter)
273288
}
274289
}
275290

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsTimeRangeCard.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ struct AnalyticsTimeRangeCard: View {
1111

1212
@State private var showTimeRangeSelectionView: Bool = false
1313

14+
private let usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter
15+
1416
init(viewModel: AnalyticsTimeRangeCardViewModel, selectionType: Binding<AnalyticsHubTimeRangeSelection.SelectionType>) {
1517
self.timeRangeTitle = viewModel.selectedRangeTitle
1618
self.currentRangeDescription = viewModel.currentRangeSubtitle
1719
self.previousRangeDescription = viewModel.previousRangeSubtitle
20+
self.usageTracksEventEmitter = viewModel.usageTracksEventEmitter
1821
self._selectionType = selectionType
1922
}
2023

@@ -25,6 +28,7 @@ struct AnalyticsTimeRangeCard: View {
2528
items: AnalyticsHubTimeRangeSelection.SelectionType.allCases,
2629
contentKeyPath: \.description,
2730
selected: $selectionType) { selection in
31+
usageTracksEventEmitter.interacted()
2832
ServiceLocator.analytics.track(event: .AnalyticsHub.dateRangeOptionSelected(selection.rawValue))
2933
}
3034
}
@@ -33,6 +37,7 @@ struct AnalyticsTimeRangeCard: View {
3337
private func createTimeRangeContent() -> some View {
3438
VStack(alignment: .leading, spacing: Layout.verticalSpacing) {
3539
Button(action: {
40+
usageTracksEventEmitter.interacted()
3641
ServiceLocator.analytics.track(event: .AnalyticsHub.dateRangeButtonTapped())
3742
showTimeRangeSelectionView.toggle()
3843
}, label: {
@@ -104,7 +109,8 @@ struct TimeRangeCard_Previews: PreviewProvider {
104109
static var previews: some View {
105110
let viewModel = AnalyticsTimeRangeCardViewModel(selectedRangeTitle: "Month to Date",
106111
currentRangeSubtitle: "Nov 1 - 23, 2022",
107-
previousRangeSubtitle: "Oct 1 - 23, 2022")
112+
previousRangeSubtitle: "Oct 1 - 23, 2022",
113+
usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter())
108114
AnalyticsTimeRangeCard(viewModel: viewModel, selectionType: .constant(.monthToDate))
109115
}
110116
}

WooCommerce/Classes/ViewRelated/Dashboard/Analytics Hub/AnalyticsTimeRangeCardViewModel.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,8 @@ struct AnalyticsTimeRangeCardViewModel {
1515
/// Previous Range Subtitle.
1616
///
1717
let previousRangeSubtitle: String
18+
19+
/// Analytics Usage Tracks Event Emitter
20+
///
21+
let usageTracksEventEmitter: StoreStatsUsageTracksEventEmitter
1822
}

WooCommerce/Classes/ViewRelated/Dashboard/Stats v4/StoreStatsAndTopPerformersPeriodViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ private extension StoreStatsAndTopPerformersPeriodViewController {
358358

359359
@objc func seeMoreButtonTapped() {
360360
ServiceLocator.analytics.track(event: .AnalyticsHub.seeMoreAnalyticsTapped())
361-
let analyticsHubVC = AnalyticsHubHostingViewController(siteID: siteID, timeRange: timeRange)
361+
let analyticsHubVC = AnalyticsHubHostingViewController(siteID: siteID, timeRange: timeRange, usageTracksEventEmitter: usageTracksEventEmitter)
362362
show(analyticsHubVC, sender: self)
363363
}
364364
}

WooCommerce/Classes/ViewRelated/Dashboard/Stats v4/StoreStatsUsageTracksEventEmitter.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,18 @@ import Foundation
44
/// considered as a _usage_ of the UI.
55
///
66
/// See p91TBi-6Cl-p2 for more information about the algorithm.
7+
/// See pe5pgL-153-p2 for background about adding Analytics Hub interactions to the algorithm.
78
///
89
/// The UI should call `interacted` when these events happen:
910
///
10-
/// - Scrolling
11-
/// - Pull-to-refresh
11+
/// - Scrolling (My Store or Analytics)
12+
/// - Pull-to-refresh (My Store or Analytics)
1213
/// - Tapping on the bars in the chart
1314
/// - Changing the tab
1415
/// - Navigating to the My Store tab
1516
/// - Tapping on a product in the Top Performers list
17+
/// - Tapping on the Analytics date range
18+
/// - Selecting an Analytics date range option
1619
///
1720
/// If we ever change the algorithm in the future, we should probably consider renaming the Tracks event to avoid
1821
/// incorrect comparisons with old events. We should also make sure to change the Android code if we're changing anything
@@ -35,6 +38,8 @@ final class StoreStatsUsageTracksEventEmitter {
3538
/// - Changing the tab
3639
/// - Navigating to the My Store tab
3740
/// - Tapping on a product in the Top Performers list
41+
/// - Tapping on the date range in the Analytics Hub
42+
/// - Selecting a date range option in the Analytics Hub
3843
private let interactionsThreshold = 5
3944

4045
/// The maximum number of seconds in between interactions before we will consider the

WooCommerce/WooCommerceTests/ViewRelated/Dashboard/Analytics Hub/AnalyticsHubViewModelTests.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ import Yosemite
55
final class AnalyticsHubViewModelTests: XCTestCase {
66

77
private var stores: MockStoresManager!
8+
private var eventEmitter: StoreStatsUsageTracksEventEmitter!
89

910
override func setUp() {
1011
stores = MockStoresManager(sessionManager: .makeForTesting())
12+
let analyticsProvider = MockAnalyticsProvider()
13+
let analytics = WooAnalytics(analyticsProvider: analyticsProvider)
14+
eventEmitter = StoreStatsUsageTracksEventEmitter(analytics: analytics)
1115
}
1216

1317
func test_cards_viewmodels_show_correct_data_after_updating_from_network() async {
1418
// Given
15-
let vm = AnalyticsHubViewModel(siteID: 123, statsTimeRange: .thisMonth, stores: stores)
19+
let vm = AnalyticsHubViewModel(siteID: 123, statsTimeRange: .thisMonth, usageTracksEventEmitter: eventEmitter, stores: stores)
1620

1721
stores.whenReceivingAction(ofType: StatsActionV4.self) { action in
1822
switch action {
@@ -43,7 +47,7 @@ final class AnalyticsHubViewModelTests: XCTestCase {
4347

4448
func test_cards_viewmodels_show_sync_error_after_getting_error_from_network() async {
4549
// Given
46-
let vm = AnalyticsHubViewModel(siteID: 123, statsTimeRange: .thisMonth, stores: stores)
50+
let vm = AnalyticsHubViewModel(siteID: 123, statsTimeRange: .thisMonth, usageTracksEventEmitter: eventEmitter, stores: stores)
4751
stores.whenReceivingAction(ofType: StatsActionV4.self) { action in
4852
switch action {
4953
case let .retrieveCustomStats(_, _, _, _, _, _, completion):
@@ -67,7 +71,7 @@ final class AnalyticsHubViewModelTests: XCTestCase {
6771

6872
func test_cards_viewmodels_redacted_while_updating_from_network() async {
6973
// Given
70-
let vm = AnalyticsHubViewModel(siteID: 123, statsTimeRange: .thisMonth, stores: stores)
74+
let vm = AnalyticsHubViewModel(siteID: 123, statsTimeRange: .thisMonth, usageTracksEventEmitter: eventEmitter, stores: stores)
7175
var loadingRevenueCard: AnalyticsReportCardViewModel?
7276
var loadingOrdersCard: AnalyticsReportCardViewModel?
7377
var loadingProductsCard: AnalyticsProductCardViewModel?

0 commit comments

Comments
 (0)