Skip to content

hectr/swift-event-tracker

Repository files navigation

SwiftEventTracker

SwiftEventTracker is a simple, yet flexible, event tracking library for Swift. It enables developers to track analytics events across multiple analytics service providers using a unified, declarative API. With SwiftEventTracker, you can easily integrate with various analytics platforms without coupling your code to any specific SDK.

Getting Started

Adding the Dependency

To use SwiftEventTracker in your project, add the following dependency to your Package.swift:

.package(url: "https://github.com/hectr/swift-event-tracker", from: "2.0.0"),

Then, add Tracker to your target's dependencies:

.target(name: "YourAppTarget", dependencies: [
    .product(name: "Tracker", package: "swift-event-tracker")
]),

Basic Usage

Importing the Library

Start by importing the Tracker module:

import Tracker

Setting Up Event Tracking

1. Define Your Events and Screens:

Create your events and screens using the Event and Screen protocols or the provided conforming structs.

let loginEvent = ParameterizedEvent(name: "login", parameters: ["method": "email"])
let homeScreen = NamedScreen(name: "HomeScreen")

2. Configure Service Providers:

Initialize the EventTracker with the service providers you want to use. Each service provider must conform to the Service protocol.

let printProvider = PrintServiceProvider()

var tracker = EventTracker(serviceProviders: [printProvider])

3. Track Events and Screens:

Use the trackEvent and trackScreen methods to track events and screen views.

tracker.trackEvent(loginEvent)
tracker.trackScreen(homeScreen)

Advanced Usage

Conditional Tracking

Given Conditions

You can conditionally track events based on custom logic:

tracker.trackEvent(loginEvent, given: { user.isLoggedIn })
Tags

Conditional tracking can also be achieved by using the Tag structure. See Custom Events and Screens, Properties and User Identifier sections.

Custom Events and Screens

Events

You can create custom events by conforming to the Event protocol. This allows you to define events with specific behavior, including setting excludedTags and requiredTags, which control whether the event should be tracked based on the tags supported by the service providers.

Here’s an example:

import Tracker

struct PurchaseEvent: Event {
    let name: String = "purchase"
    let parameters: [String: String]
    let date: Date
    
    var excludedTags: [Tag] {
        return [.debugging] // Exclude this event from providers tagged with `.crashReporting`
    }
    
    var requiredTags: [Tag] {
        return [.analytics] // Only track this event with providers tagged with `.analytics`
    }
    
    init(itemID: String, price: String) {
        self.parameters = ["item_id": itemID, "price": price]
        self.date = Date()
    }
}

// Usage
let purchaseEvent = PurchaseEvent(itemID: "12345", price: "19.99")
tracker.trackEvent(purchaseEvent)

This event is compatible with any service provider. But only a provider with built-in support for it will handle the custom date property.

Screens

Similarly, you can define custom screens by conforming to the Screen protocol. This is useful for tracking screen views with custom logic, including the use of excludedTags and requiredTags.

Here’s an example:

import Tracker

struct ProductScreen: Screen {
    let name: String = "ProductScreen"
    let productID: String
    
    var excludedTags: [Tag] {
        return [.debugging] // Exclude this screen from providers tagged with `.debugging`
    }
    
    var requiredTags: [Tag] {
        return [.analytics] // Only track this screen with providers tagged with `.analytics`
    }
    
    init(productID: String) {
        self.productID = productID
    }
}

// Usage
let productScreen = ProductScreen(productID: "67890")
tracker.trackScreen(productScreen)

Again, only service providers with built-in support for this screen will handle the custom productID property.

See more examples in [./Sources/Tracker/events/vendor/](./Sources/Tracker/events/vendor/).

Properties and User Identifier

EventTracker allows you to define properties and a user identifier that can be included in all tracked events. These attributes can be applied globally or selectively, depending on the tags associated with each service provider.

Setting Properties

You can set global properties that will be sent with every event:

// Global property applied to all providers
tracker.setProperty("user_type", value: "premium")

// Property applied only to providers tagged with `.crashReporting`
tracker.setProperty("app_version", value: "1.2.3", forTags: [.crashReporting])
Resetting Properties

If needed, you can reset properties either globally or for specific tags:

// Reset properties only for providers tagged with `.debugging`
tracker.resetProperties(forTags: [.debugging])

// Reset all properties for all providers
tracker.resetProperties()
Setting a User Identifier

The user identifier is another key property that can be set globally or for specific service providers:

// Global user identifier applied to all providers
tracker.setUserId("user_12345")

// User identifier applied only to providers tagged with `.analytics`
tracker.setUserId("user_12345", forTags: [.analytics])
Resetting the User Identifier

Similar to properties, the user identifier can also be reset globally or selectively:

// Reset user identifier for all providers
tracker.resetUserId()

// Reset user identifier only for providers tagged with `.logging` and `.crashReporting`
tracker.resetUserId(forTags: [.logging, .crashReporting])

Switching Service Providers at Runtime

You can dynamically update the list of service providers:

let appCenterProvider = AppCenterAnalyticsServiceProvider(adapter: Analytics.self) 
let adjustProvider = AdjustServiceProvider(adapter: Adjust.self)
let taplyticsProvider = TaplyticsServiceProvider(adapter: Taplytics.self)
let instabugProvider = InstabugServiceAdapter(adapter: Instabug.self)

tracker.setServiceProviders([appCenterProvider, adjustProvider, taplyticsProvider, instabugProvider])

Adding Custom Service Providers

SwiftEventTracker supports a wide range of analytics service providers, including Firebase, Amplitude, Mixpanel, and more. To add support for a new provider, you need to implement the Service protocol and provide an adapter that conforms to the corresponding adapter protocol.

Here’s a simplified example:

import Tracker

class CustomAnalyticsProvider: Service, AbstractProvider {
    let supportedTags: [Tag] = [.analytics]

    func trackEvent(_ event: Event) {
        // Implement custom event tracking logic here
    }
}

For further customization, you can implement the methods trackScreen(_:), setUserId(_:), resetUserId(), setProperty(_:value:), resetProperties(), and disableTracking(_:).

Available Service Providers

SwiftEventTracker ships with multiple analytics providers:

Implementing an Adapter

The adapter implementation for each provider is left to the consumer. Below is an example of an adapter for Firebase:

import FirebaseAnalytics
import Tracker

extension Analytics: FirebaseAnalyticsServiceAdapter {}

// Usage
let firebaseProvider = FirebaseAnalyticsServiceProvider(adapter: Analytics.self)
var tracker = EventTracker(serviceProviders: [firebaseProvider])

This allows SwiftEventTracker to leverage Firebase's capabilities without directly depending on its SDK. Be aware that your application still needs to handle Firebase configuration and initialization.

You can find examples for the rest of supported services in the Examples package.

License

SwiftEventTracker is available under the MIT license. See the LICENSE file for more information.

Contributing

Contributions are welcome! If you have ideas, suggestions, or would like to contribute to the codebase, feel free to open an issue or submit a pull request.

Alternatives