Skip to content

Commit 101a1c6

Browse files
authored
Merge pull request #6055 from woocommerce/issue/5717-analytics
2 parents 876ef79 + 2346e2d commit 101a1c6

File tree

5 files changed

+140
-2
lines changed

5 files changed

+140
-2
lines changed

WooCommerce/Classes/Analytics/WooAnalyticsEvent.swift

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,76 @@ extension WooAnalyticsEvent {
322322
}
323323
}
324324

325+
// MARK: - Order General
326+
//
327+
extension WooAnalyticsEvent {
328+
// Namespace
329+
enum Orders {
330+
/// Possible Order Flows
331+
///
332+
enum Flow: String {
333+
case creation
334+
case editing
335+
}
336+
337+
private enum Keys {
338+
static let flow = "flow"
339+
static let hasDifferentShippingDetails = "has_different_shipping_details"
340+
static let orderStatus = "order_status"
341+
static let productCount = "product_count"
342+
static let hasCustomerDetails = "has_customer_details"
343+
static let errorContext = "error_context"
344+
static let errorDescription = "error_description"
345+
static let to = "to"
346+
static let from = "from"
347+
}
348+
349+
static func orderAddNew() -> WooAnalyticsEvent {
350+
WooAnalyticsEvent(statName: .orderAddNew, properties: [:])
351+
}
352+
353+
static func orderProductAdd(flow: Flow) -> WooAnalyticsEvent {
354+
WooAnalyticsEvent(statName: .orderProductAdd, properties: [Keys.flow: flow.rawValue])
355+
}
356+
357+
static func orderCustomerAdd(flow: Flow, hasDifferentShippingDetails: Bool) -> WooAnalyticsEvent {
358+
WooAnalyticsEvent(statName: .orderCustomerAdd, properties: [
359+
Keys.flow: flow.rawValue,
360+
Keys.hasDifferentShippingDetails: hasDifferentShippingDetails
361+
])
362+
}
363+
364+
static func orderStatusChange(flow: Flow, from oldStatus: OrderStatusEnum, to newStatus: OrderStatusEnum) -> WooAnalyticsEvent {
365+
WooAnalyticsEvent(statName: .orderStatusChange, properties: [
366+
Keys.flow: flow.rawValue,
367+
Keys.from: oldStatus.rawValue,
368+
Keys.to: newStatus.rawValue
369+
])
370+
}
371+
372+
static func orderCreateButtonTapped(status: OrderStatusEnum,
373+
productCount: Int,
374+
hasCustomerDetails: Bool) -> WooAnalyticsEvent {
375+
WooAnalyticsEvent(statName: .orderCreateButtonTapped, properties: [
376+
Keys.orderStatus: status.rawValue,
377+
Keys.productCount: Int64(productCount),
378+
Keys.hasCustomerDetails: hasCustomerDetails
379+
])
380+
}
381+
382+
static func orderCreationSuccess() -> WooAnalyticsEvent {
383+
WooAnalyticsEvent(statName: .orderCreationSuccess, properties: [:])
384+
}
385+
386+
static func orderCreationFailed(errorContext: String, errorDescription: String) -> WooAnalyticsEvent {
387+
WooAnalyticsEvent(statName: .orderCreationFailed, properties: [
388+
Keys.errorContext: errorContext,
389+
Keys.errorDescription: errorDescription
390+
])
391+
}
392+
}
393+
}
394+
325395
// MARK: - Order Details Edit
326396
//
327397
extension WooAnalyticsEvent {

WooCommerce/Classes/Analytics/WooAnalyticsStat.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,13 +208,19 @@ public enum WooAnalyticsStat: String {
208208
// MARK: Order Data/Action Events
209209
//
210210
case orderOpen = "order_open"
211+
case orderAddNew = "orders_add_new"
211212
case orderNotesLoaded = "order_notes_loaded"
212213
case orderNoteAdd = "order_note_add"
213214
case orderNoteAddSuccess = "order_note_add_success"
214215
case orderNoteAddFailed = "order_note_add_failed"
216+
case orderCreateButtonTapped = "order_create_button_tapped"
217+
case orderCreationSuccess = "order_creation_success"
218+
case orderCreationFailed = "order_creation_failed"
215219
case orderContactAction = "order_contact_action"
220+
case orderCustomerAdd = "order_customer_add"
216221
case ordersListFilterOrSearch = "orders_list_filter"
217222
case ordersListLoaded = "orders_list_loaded"
223+
case orderProductAdd = "order_product_add"
218224
case orderStatusChange = "order_status_change"
219225
case orderStatusChangeSuccess = "order_status_change_success"
220226
case orderStatusChangeFailed = "order_status_change_failed"

WooCommerce/Classes/ViewRelated/Orders/Order Creation/FlowCoordinator/AddOrderCoordinator.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,7 @@ private extension AddOrderCoordinator {
8282
let viewController = NewOrderHostingController(viewModel: viewModel)
8383
viewController.hidesBottomBarWhenPushed = true
8484
navigationController.pushViewController(viewController, animated: true)
85+
86+
ServiceLocator.analytics.track(event: WooAnalyticsEvent.Orders.orderAddNew())
8587
}
8688
}

WooCommerce/Classes/ViewRelated/Orders/Order Creation/NewOrderViewModel.swift

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,20 @@ final class NewOrderViewModel: ObservableObject {
131131
///
132132
@Published private(set) var paymentDataViewModel = PaymentDataViewModel()
133133

134+
/// Analytics engine.
135+
///
136+
private let analytics: Analytics
137+
134138
init(siteID: Int64,
135139
stores: StoresManager = ServiceLocator.stores,
136140
storageManager: StorageManagerType = ServiceLocator.storageManager,
137-
currencySettings: CurrencySettings = ServiceLocator.currencySettings) {
141+
currencySettings: CurrencySettings = ServiceLocator.currencySettings,
142+
analytics: Analytics = ServiceLocator.analytics) {
138143
self.siteID = siteID
139144
self.stores = stores
140145
self.storageManager = storageManager
141146
self.currencyFormatter = CurrencyFormatter(currencySettings: currencySettings)
147+
self.analytics = analytics
142148

143149
configureNavigationTrailingItem()
144150
configureStatusBadgeViewModel()
@@ -195,6 +201,7 @@ final class NewOrderViewModel: ObservableObject {
195201
onAddressUpdate: { [weak self] updatedAddressData in
196202
self?.orderDetails.billingAddress = updatedAddressData.billingAddress
197203
self?.orderDetails.shippingAddress = updatedAddressData.shippingAddress
204+
self?.trackCustomerDetailsAdded()
198205
})
199206
}
200207

@@ -211,17 +218,28 @@ final class NewOrderViewModel: ObservableObject {
211218
switch result {
212219
case .success(let newOrder):
213220
self.onOrderCreated(newOrder)
221+
self.trackCreateOrderSuccess()
214222
case .failure(let error):
215223
self.notice = NoticeFactory.createOrderCreationErrorNotice()
224+
self.trackCreateOrderFailure(error: error)
216225
DDLogError("⛔️ Error creating new order: \(error)")
217226
}
218227
}
219228
stores.dispatch(action)
229+
trackCreateButtonTapped()
220230
}
221231

222232
/// Assign this closure to be notified when a new order is created
223233
///
224234
var onOrderCreated: (Order) -> Void = { _ in }
235+
236+
/// Updates the order status & tracks its event
237+
///
238+
func updateOrderStatus(newStatus: OrderStatusEnum) {
239+
let oldStatus = orderDetails.status
240+
orderDetails.status = newStatus
241+
analytics.track(event: WooAnalyticsEvent.Orders.orderStatusChange(flow: .creation, from: oldStatus, to: newStatus))
242+
}
225243
}
226244

227245
// MARK: - Types
@@ -410,6 +428,8 @@ private extension NewOrderViewModel {
410428
let newOrderItem = NewOrderItem(product: product, quantity: 1)
411429
orderDetails.items.append(newOrderItem)
412430
configureProductRowViewModels()
431+
432+
analytics.track(event: WooAnalyticsEvent.Orders.orderProductAdd(flow: .creation))
413433
}
414434

415435
/// Adds a selected product variation (from the product list) to the order.
@@ -418,6 +438,8 @@ private extension NewOrderViewModel {
418438
let newOrderItem = NewOrderItem(variation: variation, quantity: 1)
419439
orderDetails.items.append(newOrderItem)
420440
configureProductRowViewModels()
441+
442+
analytics.track(event: WooAnalyticsEvent.Orders.orderProductAdd(flow: .creation))
421443
}
422444

423445
/// Configures product row view models for each item in `orderDetails`.
@@ -471,6 +493,44 @@ private extension NewOrderViewModel {
471493
}
472494
.assign(to: &$paymentDataViewModel)
473495
}
496+
497+
/// Tracks when customer details have been added
498+
///
499+
func trackCustomerDetailsAdded() {
500+
let areAddressesDifferent: Bool = {
501+
guard let billingAddress = orderDetails.billingAddress, let shippingAddress = orderDetails.shippingAddress else {
502+
return false
503+
}
504+
return billingAddress != shippingAddress
505+
}()
506+
analytics.track(event: WooAnalyticsEvent.Orders.orderCustomerAdd(flow: .creation, hasDifferentShippingDetails: areAddressesDifferent))
507+
}
508+
509+
/// Tracks when the create order button is tapped.
510+
///
511+
/// Warning: This methods assume that `orderDetails.items.count` is equal to the product count,
512+
/// As the module evolves to handle more types of items, we need to update the property to something like `itemsCount`
513+
/// or figure out a better way to get the product count.
514+
///
515+
func trackCreateButtonTapped() {
516+
let hasCustomerDetails = orderDetails.billingAddress != nil || orderDetails.shippingAddress != nil
517+
analytics.track(event: WooAnalyticsEvent.Orders.orderCreateButtonTapped(status: orderDetails.status,
518+
productCount: orderDetails.items.count,
519+
hasCustomerDetails: hasCustomerDetails))
520+
}
521+
522+
/// Tracks an order creation success
523+
///
524+
func trackCreateOrderSuccess() {
525+
analytics.track(event: WooAnalyticsEvent.Orders.orderCreationSuccess())
526+
}
527+
528+
/// Tracks an order creation failure
529+
///
530+
func trackCreateOrderFailure(error: Error) {
531+
analytics.track(event: WooAnalyticsEvent.Orders.orderCreationFailed(errorContext: String(describing: error),
532+
errorDescription: error.localizedDescription))
533+
}
474534
}
475535

476536
private extension NewOrderViewModel {

WooCommerce/Classes/ViewRelated/Orders/Order Creation/StatusSection/OrderStatusSection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct OrderStatusSection: View {
3434
.padding(.trailing, -Layout.linkButtonTrailingPadding) // remove trailing padding to align button title to the side
3535
.sheet(isPresented: $viewModel.shouldShowOrderStatusList) {
3636
OrderStatusList(siteID: viewModel.siteID, status: viewModel.orderDetails.status) { newStatus in
37-
viewModel.orderDetails.status = newStatus
37+
viewModel.updateOrderStatus(newStatus: newStatus)
3838
}
3939
}
4040
}

0 commit comments

Comments
 (0)