Skip to content

Commit f71b724

Browse files
authored
Merge pull request #6552 from woocommerce/feat/5984-add-card_reader_model-prop
IPP analytics: add `card_reader_model` property to reader connection and payment collection events
2 parents 0118cee + 1937ccd commit f71b724

File tree

11 files changed

+142
-23
lines changed

11 files changed

+142
-23
lines changed

Hardware/Hardware/CardReader/CardReaderType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public enum CardReaderType {
1414
extension CardReaderType {
1515
/// A human-readable model name for the reader.
1616
///
17-
var model: String {
17+
public var model: String {
1818
/// This should match the Android SDK deviceName, to simplify Analytics use
1919
/// https://stripe.dev/stripe-terminal-android/external/external/com.stripe.stripeterminal.external.models/-device-type/index.html
2020
/// pbUcTB-r9-p2#comment-2164

WooCommerce/Classes/Analytics/WooAnalyticsEvent.swift

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ extension WooAnalyticsEvent {
573573

574574
enum Keys {
575575
static let batteryLevel = "battery_level"
576+
static let cardReaderModel = "card_reader_model"
576577
static let countryCode = "country"
577578
static let gatewayID = "plugin_slug"
578579
static let errorDescription = "error_description"
@@ -609,9 +610,14 @@ extension WooAnalyticsEvent {
609610
/// - forGatewayID: the plugin (e.g. "woocommerce-payments" or "woocommerce-gateway-stripe") to be included in the event properties in Tracks.
610611
/// - batteryLevel: the battery level (if available) to be included in the event properties in Tracks, e.g. 0.75 = 75%.
611612
/// - countryCode: the country code of the store.
613+
/// - cardReaderModel: the model type of the card reader.
612614
///
613-
static func cardReaderConnectionSuccess(forGatewayID: String?, batteryLevel: Float?, countryCode: String) -> WooAnalyticsEvent {
615+
static func cardReaderConnectionSuccess(forGatewayID: String?,
616+
batteryLevel: Float?,
617+
countryCode: String,
618+
cardReaderModel: String) -> WooAnalyticsEvent {
614619
var properties = [
620+
Keys.cardReaderModel: cardReaderModel,
615621
Keys.countryCode: countryCode,
616622
Keys.gatewayID: gatewayID(forGatewayID: forGatewayID)
617623
]
@@ -629,10 +635,12 @@ extension WooAnalyticsEvent {
629635
/// - forGatewayID: the plugin (e.g. "woocommerce-payments" or "woocommerce-gateway-stripe") to be included in the event properties in Tracks.
630636
/// - error: the error to be included in the event properties.
631637
/// - countryCode: the country code of the store.
638+
/// - cardReaderModel: the model type of the card reader.
632639
///
633-
static func cardReaderConnectionFailed(forGatewayID: String?, error: Error, countryCode: String) -> WooAnalyticsEvent {
640+
static func cardReaderConnectionFailed(forGatewayID: String?, error: Error, countryCode: String, cardReaderModel: String) -> WooAnalyticsEvent {
634641
WooAnalyticsEvent(statName: .cardReaderConnectionFailed,
635642
properties: [
643+
Keys.cardReaderModel: cardReaderModel,
636644
Keys.countryCode: countryCode,
637645
Keys.gatewayID: gatewayID(forGatewayID: forGatewayID),
638646
Keys.errorDescription: error.localizedDescription
@@ -646,10 +654,12 @@ extension WooAnalyticsEvent {
646654
/// - Parameters:
647655
/// - forGatewayID: the plugin (e.g. "woocommerce-payments" or "woocommerce-gateway-stripe") to be included in the event properties in Tracks.
648656
/// - countryCode: the country code of the store.
657+
/// - cardReaderModel: the model type of the card reader.
649658
///
650-
static func cardReaderDisconnectTapped(forGatewayID: String?, countryCode: String) -> WooAnalyticsEvent {
659+
static func cardReaderDisconnectTapped(forGatewayID: String?, countryCode: String, cardReaderModel: String) -> WooAnalyticsEvent {
651660
WooAnalyticsEvent(statName: .cardReaderDisconnectTapped,
652661
properties: [
662+
Keys.cardReaderModel: cardReaderModel,
653663
Keys.countryCode: countryCode,
654664
Keys.gatewayID: gatewayID(forGatewayID: forGatewayID)
655665
]
@@ -769,14 +779,15 @@ extension WooAnalyticsEvent {
769779
/// - Parameters:
770780
/// - forGatewayID: the plugin (e.g. "woocommerce-payments" or "woocommerce-gateway-stripe") to be included in the event properties in Tracks.
771781
/// - countryCode: the country code of the store.
782+
/// - cardReaderModel: the model type of the card reader.
772783
///
773-
static func collectPaymentTapped(forGatewayID: String?, countryCode: String) -> WooAnalyticsEvent {
784+
static func collectPaymentTapped(forGatewayID: String?, countryCode: String, cardReaderModel: String) -> WooAnalyticsEvent {
774785
WooAnalyticsEvent(statName: .collectPaymentTapped,
775786
properties: [
787+
Keys.cardReaderModel: cardReaderModel,
776788
Keys.countryCode: countryCode,
777789
Keys.gatewayID: gatewayID(forGatewayID: forGatewayID)
778-
]
779-
)
790+
])
780791
}
781792

782793
/// Tracked when the payment collection fails
@@ -785,8 +796,9 @@ extension WooAnalyticsEvent {
785796
/// - forGatewayID: the plugin (e.g. "woocommerce-payments" or "woocommerce-gateway-stripe") to be included in the event properties in Tracks.
786797
/// - error: the error to be included in the event properties.
787798
/// - countryCode: the country code of the store.
799+
/// - cardReaderModel: the model type of the card reader, if available.
788800
///
789-
static func collectPaymentFailed(forGatewayID: String?, error: Error, countryCode: String) -> WooAnalyticsEvent {
801+
static func collectPaymentFailed(forGatewayID: String?, error: Error, countryCode: String, cardReaderModel: String?) -> WooAnalyticsEvent {
790802
let paymentMethod: PaymentMethod? = {
791803
guard case let CardReaderServiceError.paymentCaptureWithPaymentMethod(_, paymentMethod) = error else {
792804
return nil
@@ -813,6 +825,7 @@ extension WooAnalyticsEvent {
813825
}
814826
}()
815827
let properties: [String: WooAnalyticsEventPropertyType] = [
828+
Keys.cardReaderModel: cardReaderModel,
816829
Keys.countryCode: countryCode,
817830
Keys.gatewayID: gatewayID(forGatewayID: forGatewayID),
818831
Keys.paymentMethodType: paymentMethod?.analyticsValue,
@@ -827,10 +840,12 @@ extension WooAnalyticsEvent {
827840
/// - Parameters:
828841
/// - forGatewayID: the plugin (e.g. "woocommerce-payments" or "woocommerce-gateway-stripe") to be included in the event properties in Tracks.
829842
/// - countryCode: the country code of the store.
843+
/// - cardReaderModel: the model type of the card reader.
830844
///
831-
static func collectPaymentCanceled(forGatewayID: String?, countryCode: String) -> WooAnalyticsEvent {
845+
static func collectPaymentCanceled(forGatewayID: String?, countryCode: String, cardReaderModel: String) -> WooAnalyticsEvent {
832846
WooAnalyticsEvent(statName: .collectPaymentCanceled,
833847
properties: [
848+
Keys.cardReaderModel: cardReaderModel,
834849
Keys.countryCode: countryCode,
835850
Keys.gatewayID: gatewayID(forGatewayID: forGatewayID)
836851
]
@@ -843,10 +858,15 @@ extension WooAnalyticsEvent {
843858
/// - forGatewayID: the plugin (e.g. "woocommerce-payments" or "woocommerce-gateway-stripe") to be included in the event properties in Tracks.
844859
/// - countryCode: the country code of the store.
845860
/// - paymentMethod: the payment method of the captured payment.
861+
/// - cardReaderModel: the model type of the card reader.
846862
///
847-
static func collectPaymentSuccess(forGatewayID: String?, countryCode: String, paymentMethod: PaymentMethod) -> WooAnalyticsEvent {
863+
static func collectPaymentSuccess(forGatewayID: String?,
864+
countryCode: String,
865+
paymentMethod: PaymentMethod,
866+
cardReaderModel: String) -> WooAnalyticsEvent {
848867
WooAnalyticsEvent(statName: .collectPaymentSuccess,
849868
properties: [
869+
Keys.cardReaderModel: cardReaderModel,
850870
Keys.countryCode: countryCode,
851871
Keys.gatewayID: gatewayID(forGatewayID: forGatewayID),
852872
Keys.paymentMethodType: paymentMethod.analyticsValue

WooCommerce/Classes/ViewModels/CardPresentPayments/CardPresentModalReaderIsReady.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,20 @@ final class CardPresentModalReaderIsReady: CardPresentPaymentsModalViewModel {
4343

4444
private let paymentGatewayAccountID: String?
4545
private let countryCode: String
46+
private let cardReaderModel: String
4647
private let analytics: Analytics
4748

48-
init(name: String, amount: String, paymentGatewayAccountID: String?, countryCode: String, analytics: Analytics = ServiceLocator.analytics) {
49+
init(name: String,
50+
amount: String,
51+
paymentGatewayAccountID: String?,
52+
countryCode: String,
53+
cardReaderModel: String,
54+
analytics: Analytics = ServiceLocator.analytics) {
4955
self.name = name
5056
self.amount = amount
5157
self.paymentGatewayAccountID = paymentGatewayAccountID
5258
self.countryCode = countryCode
59+
self.cardReaderModel = cardReaderModel
5360
self.analytics = analytics
5461
}
5562

@@ -60,7 +67,8 @@ final class CardPresentModalReaderIsReady: CardPresentPaymentsModalViewModel {
6067
func didTapSecondaryButton(in viewController: UIViewController?) {
6168
analytics.track(event: WooAnalyticsEvent.InPersonPayments
6269
.collectPaymentCanceled(forGatewayID: paymentGatewayAccountID,
63-
countryCode: countryCode))
70+
countryCode: countryCode,
71+
cardReaderModel: cardReaderModel))
6472

6573
let action = CardPresentPaymentAction.cancelPayment(onCompletion: nil)
6674

WooCommerce/Classes/ViewModels/Order Details/OrderDetailsPaymentAlerts.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ final class OrderDetailsPaymentAlerts {
2626

2727
private let paymentGatewayAccountID: String?
2828
private let countryCode: String
29+
private let cardReaderModel: String
2930

30-
init(presentingController: UIViewController, paymentGatewayAccountID: String?, countryCode: String) {
31+
init(presentingController: UIViewController, paymentGatewayAccountID: String?, countryCode: String, cardReaderModel: String) {
3132
self.presentingController = presentingController
3233
self.paymentGatewayAccountID = paymentGatewayAccountID
3334
self.countryCode = countryCode
35+
self.cardReaderModel = cardReaderModel
3436
}
3537

3638
func presentViewModel(viewModel: CardPresentPaymentsModalViewModel) {
@@ -94,7 +96,11 @@ final class OrderDetailsPaymentAlerts {
9496

9597
private extension OrderDetailsPaymentAlerts {
9698
func readerIsReady() -> CardPresentPaymentsModalViewModel {
97-
CardPresentModalReaderIsReady(name: name, amount: amount, paymentGatewayAccountID: paymentGatewayAccountID, countryCode: countryCode)
99+
CardPresentModalReaderIsReady(name: name,
100+
amount: amount,
101+
paymentGatewayAccountID: paymentGatewayAccountID,
102+
countryCode: countryCode,
103+
cardReaderModel: cardReaderModel)
98104
}
99105

100106
func tapOrInsert(onCancel: @escaping () -> Void) -> CardPresentPaymentsModalViewModel {

WooCommerce/Classes/ViewRelated/CardPresentPayments/CardReaderConnectionController.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,8 @@ private extension CardReaderConnectionController {
577577
event: WooAnalyticsEvent.InPersonPayments
578578
.cardReaderConnectionSuccess(forGatewayID: self.gatewayID,
579579
batteryLevel: reader.batteryLevel,
580-
countryCode: self.configuration.countryCode)
580+
countryCode: self.configuration.countryCode,
581+
cardReaderModel: reader.readerType.model)
581582
)
582583
// If we were installing a software update, introduce a small delay so the user can
583584
// actually see a success message showing the installation was complete
@@ -593,7 +594,8 @@ private extension CardReaderConnectionController {
593594
ServiceLocator.analytics.track(
594595
event: WooAnalyticsEvent.InPersonPayments.cardReaderConnectionFailed(forGatewayID: self.gatewayID,
595596
error: error,
596-
countryCode: self.configuration.countryCode)
597+
countryCode: self.configuration.countryCode,
598+
cardReaderModel: candidateReader.readerType.model)
597599
)
598600
self.state = .connectingFailed(error)
599601
}

WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewController.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ final class CardReaderSettingsConnectedViewController: UIViewController, CardRea
2323
private lazy var paymentAlerts: OrderDetailsPaymentAlerts = {
2424
OrderDetailsPaymentAlerts(presentingController: self,
2525
paymentGatewayAccountID: viewModel?.dataSource.cardPresentPaymentGatewayID(),
26-
countryCode: CardPresentConfigurationLoader().configuration.countryCode)
26+
countryCode: CardPresentConfigurationLoader().configuration.countryCode,
27+
cardReaderModel: viewModel?.connectedReaderModel ?? "")
2728
}()
2829

2930
private let settingsAlerts = CardReaderSettingsAlerts()

WooCommerce/Classes/ViewRelated/Dashboard/Settings/CardReadersV2/CardReaderSettingsConnectedViewModel.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie
2828
var connectedReaderID: String?
2929
var connectedReaderBatteryLevel: String?
3030
var connectedReaderSoftwareVersion: String?
31+
var connectedReaderModel: String? {
32+
connectedReaders.first?.readerType.model
33+
}
3134

3235
/// The connected gateway ID (plugin slug) - useful for the view controller's tracks events
3336
var connectedGatewayID: String?
@@ -247,7 +250,9 @@ final class CardReaderSettingsConnectedViewModel: CardReaderSettingsPresentedVie
247250
func disconnectReader() {
248251
ServiceLocator.analytics.track(
249252
event: WooAnalyticsEvent.InPersonPayments.cardReaderDisconnectTapped(
250-
forGatewayID: connectedGatewayID, countryCode: configuration.countryCode
253+
forGatewayID: connectedGatewayID,
254+
countryCode: configuration.countryCode,
255+
cardReaderModel: connectedReaderModel ?? ""
251256
)
252257
)
253258

0 commit comments

Comments
 (0)