Skip to content

Instantly share code, notes, and snippets.

@hyperspacemark
Last active May 5, 2023 02:51
Show Gist options
  • Save hyperspacemark/93716aedcf40948a62d039d444c86326 to your computer and use it in GitHub Desktop.
Save hyperspacemark/93716aedcf40948a62d039d444c86326 to your computer and use it in GitHub Desktop.
iOS Analytics State of the Union

Analytics

Old School Event Tracking

Until recently we've only needed to report analytics events for Venmo, to Amplitude, via mParticle.

To that end, iOS uses the following abstraction for tracking analytics events in feature code.

protocol AnalyticsEventTracker {
    func track(_ event: some AnalyticsEvent)
}

Analytics events are defined as having a name, an entity (which is used for general categorization), and a collection of properties with string keys and scalar values.

public protocol AnalyticsEvent {
    var name: String { get }
    var entity: String { get }
    var properties: [AnalyticsEventProperty] { get }
}

Supporting Sending Events to PayPal's FPTI

Sending events to PayPal requires more data than our AnalyticsEvent protocol allows. Specifically, PayPal tracks the type of the event. One of the following values:

  • activity - "ac"
  • click - "cl"
  • impression - "im"
  • redirect - "rd"
  • userAction - "ua"

To represent events going to PayPal, we refined the AnalyticsEvent protocol with the additional event type requirement.

public enum PayPalAnalyticsEventType: String {
    case activity = "ac"
    case click = "cl"
    case impression = "im"
    case redirect = "rd"
    case userAction = "ua"
}

protocol PayPalAnalyticsEvent: AnalyticsEvent {
    var eventType: PayPalAnalyticsEventType { get }
}

And added a new tracker protocol for PayPal events.

protocol PayPalAnalyticsEventTracker {
    func track(_ event: some PayPalAnalyticsEvent)
}

Supporting Sending Events to Venmo and PayPal

Some features want the ability to send the same event instance to both PayPal and Venmo. PayPal event trackers can be combined with Venmo event trackers to create instances that dispatch to both locations.

let payPalTracker: PayPalAnalyticsEventTracker
let venmoTracker: AnalyticsEventTracker
let combinedTracker = payPalTracker.combined(with: venmoTracker)

A Post-Amplitude World

Ideally we'd go back to having just one event tracker protocol. For that we should move the eventType requirement from PayPalAnalyticsEvent up into AnalyticsEvent. PayPalAnalyticsEvent and PayPalAnalyticsEventTracker should be deprecated.

protocol AnalyticsEventType {
    case activity = "ac"
    case click = "cl"
    case impression = "im"
    case redirect = "rd"
    case userAction = "ua"
}

protocol AnalyticsEvent {
    var name: String { get }
    var category: String { get }
    var eventType: AnalyticsEventType { get }
    var properties: [AnalyticsEventProperty] { get }
}

Backwards Compatibility

Making this change alone would be API breaking for hundreds of events defined across modules. To prevent this, we should provide a default implementation of eventType that returns a reasonable value until events can be manually audited for the correct type.

extension AnalyticsEvent {
    var eventType: AnalyticsEventType {
        .userAction // Or something better?
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment