Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing projects.

Overview

Trackable

Build Status codecov Carthage Compatible Swift Version

Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing projects.


Main features:

  • Easy integration to existing classes using extensions and protocols
  • Programmatically generated event and property identifiers
  • Smart tracking of properties by objects chaining (if object “A” is set to be a parent of object “B”, event tracked on object “B” will also contain tracked properties from “A”)

Instalation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

To integrate Trackable into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!

pod 'Trackable'

Then, run the following command:

$ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate trackable into your Xcode project using Carthage, specify it in your Cartfile:

github "VojtaStavik/Trackable"

Run carthage update to build the framework and drag the built Trackable.framework into your Xcode project.


Usage

Integration of the Trackable library is very easy and straightforward. See example app with complete implementation including all features.

Events and Keys

Define events and keys using enums with String raw representation. These enums have to conform to Event or Key protocols. You can use nesting for better organization. String identifiers are created automatically, and they respect the complete enums structure. Example: Events.App.started will be translated to “<ModuleName>.Events.App.started” string.

enum Events {
    enum User : String, Event {
        case didSelectBeatle
        case didSelectAlbum
        case didRateAlbum
    }

    enum App : String, Event {
        case started
        case didBecomeActive
        case didEnterBackground
        case terminated
    }

    enum AlbumListVC : String, Event {
        case didAppear
    }
}

enum Keys : String, Key {
    case beatleName
    case albumName
    case userLikesAlbum
    case previousVC

    enum App : String, Key {
        case uptime
        case reachabilityStatus
    }
}

Tracking

You can track events on any class conforming to the TrackableClass protocol by calling self.track(event: Event). You can also call self.track(event: Event, trackedProperties: Set<TrackedProperty>) if you want to add some specific properties to the tracked event.

TrackedProperty is a struct you can create using a custom infix operator ~>> with Key and value. Allowed value types are String, Double, Int, Bool and Set<TrackedProperty>.

// Example:

import UIKit
import Trackable

class AlbumDetailVC: UIViewController {

    var album : Album!

    @IBOutlet weak var yesButton: UIButton!
    @IBOutlet weak var noButton: UIButton!

    @IBAction func didPressButton(sender: UIButton) {
        let userLikesAlbum = (sender === yesButton)
        track(Events.User.didRateAlbum, trackedProperties: [Keys.userLikesAlbum ~>> userLikesAlbum])
    }
}

extension AlbumDetailVC : TrackableClass { }

Tracked properties

Trackable is designed to allow you to easily track all properties you need. There are three levels where you can add custom data to tracked events. If you add a property with the same name, it will override the previous value with a lower level.

Level 3

  • when calling track()function
  • properties on this level will be added only to the currently tracked event
  • Typical usage: When you want to track properties closely connected to the event.
// Example:
track(Events.User.didRateAlbum, trackedProperties: [Keys.userLikesAlbum ~>> userLikesAlbum])

Level 2

  • instance properties added by calling setupTrackableChain(trackedProperties:) on a TrackableClass instance.
  • these properties will be added to all events tracked on the object
  • Typical usage: When you want to set properties from the outside of the object (the object doesn’t know about them)
// Example:
import UIKit
import Trackable

class AlbumListTVC: UITableViewController {
	 code 

    // MARK: - Navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let destinationVC = segue.destinationViewController as! AlbumDetailVC
        destinationVC.setupTrackableChain([Keys.previousVC ~>> "Album list"]) // all events tracked on destinationVC will have previousVC property included automatically
    }
}

extension AlbumListTVC : TrackableClass { }

Level 1

  • computed properties added by custom implementation of the TrackableClass protocol
  • these properties will be added to all events tracked on the object
  • Typical usage: When you want to add some set of properties to all events tracked on the object.
// Example:
class AlbumListTVC: UITableViewController {
    var albums : [Album]!

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        track(Events.User.didSelectAlbum) // selectedAlbum property will be added automatically
    }

    var selectedAlbum : Album? {
        if let indexPath = tableView.indexPathForSelectedRow {
            return albums[indexPath.row]
        } else {
            return nil
        }
    }
}

extension AlbumListTVC : TrackableClass {
    var trackedProperties : Set<TrackedProperty> {
        return [Keys.albumName ~>> selectedAlbum?.name ?? "none"]
    }
}

Chaining

The real advantage of Trackable comes with chaining. You can set one object to be a Trackable parent of another object. If class A is a parent of class B, all events tracked on B will also automatically include trackedProperties from A.

// Example:
import UIKit
import Trackable

class AlbumListTVC: UITableViewController {

	 some code here 

    // MARK: - Navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        let destinationVC = segue.destinationViewController as! AlbumDetailVC
        destinationVC.setupTrackableChain([Keys.previousVC ~>> "Album list"], parent: self)
    }

    var selectedAlbum : Album? {
        if let indexPath = tableView.indexPathForSelectedRow {
            return albums[indexPath.row]
        } else {
            return nil
        }
    }
}

extension AlbumListTVC : TrackableClass {
    var trackedProperties : Set<TrackedProperty> {
        return [Keys.albumName ~>> selectedAlbum?.name ?? "none"]
    }
}

// All events tracked later on destinationVC will automatically have previousVC and albumName properties,
// without destinationVC even knowing those values exist!

Connecting to Mixpanel (or any other service)

In order to perform the actual tracking into an analytics service, you have to provide an implementation for Trackable.trackEventToRemoteServiceClosure.

// Example:
import Foundation
import Mixpanel
import Trackable

let analytics = Analytics() // singleton (yay!)

class Analytics {
    let mixpanel = Mixpanel.sharedInstanceWithToken("<token>")

    init() {
        Trackable.trackEventToRemoteServiceClosure = trackEventToMixpanel
        setupTrackableChain() // allows self to be part of the trackable chain
    }

    func trackEventToMixpanel(eventName: String, trackedProperties: [String: AnyObject]) {        
        mixpanel.track(eventName, properties: trackedProperties)
    }
}

extension Analytics : TrackableClass { }

Maybe you want to add some properties to all events tracked in your app. It’s similar to Mixpanel super properties but with dynamic content! You need to provide a custom implementation of the TrackableClass protocol:

extension Analytics : TrackableClass {
    var trackedProperties : Set<TrackedProperty> {
        return [Keys.App.uptime ~>> NSDate().timeIntervalSinceDate(startTime)]
    }
}

and set the analytics object as a parent to all objects without a parent by calling setupTrackableChain(parent: analytics) on them:

// Example:
import UIKit
import Trackable

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
        setupTrackableChain(parent: analytics)
        return true
    }

    func applicationDidBecomeActive(application: UIApplication) {
        track(Events.App.didBecomeActive)
    }

    func applicationDidEnterBackground(application: UIApplication) {
        track(Events.App.didEnterBackground)
    }

    func applicationWillTerminate(application: UIApplication) {
        track(Events.App.terminated)
    }

}

extension AppDelegate : TrackableClass { }

License

Trackable is released under the MIT license. See LICENSE for details.


Readme inspired by Alamofire. Thank you!

You might also like...
Cross-platform static analyzer and linter for Swift.
Cross-platform static analyzer and linter for Swift.

Wiki • Installation • Usage • Features • Developers • License Tailor is a cross-platform static analysis and lint tool for source code written in Appl

Type-safe observable values and collections in Swift

GlueKit ⚠️ WARNING ⚠️ This project is in a prerelease state. There is active work going on that will result in API changes that can/will break code wh

Makes it easier to support older versions of iOS by fixing things and adding missing methods

PSTModernizer PSTModernizer carefully applies patches to UIKit and related Apple frameworks to fix known radars with the least impact. The current set

Find common xib and storyboard-related problems without running your app or writing unit tests.
Find common xib and storyboard-related problems without running your app or writing unit tests.

IBAnalyzer Find common xib and storyboard-related problems without running your app or writing unit tests. Usage Pass a path to your project to ibanal

Skredvarsel app - an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API
Skredvarsel app - an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Skredvarsel (Avalanche warning) app is an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Exclude files and folders from Alfred’s search results
Exclude files and folders from Alfred’s search results

Ignore in Alfred Alfred Workflow Exclude files and folders from Alfred’s search results ⤓ Download Workflow About The macOS metadata search API only a

Google Analytics tracker for Apple tvOS provides an easy integration of Google Analytics’ measurement protocol for Apple TV.

Google Analytics tracker for Apple tvOS by Adswerve About Google Analytics tracker for Apple tvOS provides an easy integration of Google Analytics’ me

Analytics layer abstraction, abstract analytics reporters and collect domain-driven analytic events.

🐙 Tentacles Current State: Work in Progress Documentation & Tests(100% completed, but needs refactoring and structuring) started but not done yet, im

AlertTransition is a extensible library for making view controller transitions, especially for alert transitions.
AlertTransition is a extensible library for making view controller transitions, especially for alert transitions.

AlertTransition AlertTransition is a extensible library for making view controller transitions, especially for alert transitions. Overview AlertTransi

Gumlet analytics integration with AVPlayer for iOS native applications.

gumlet-Insights-avplayer Gumlet Insights integration with AVPlayer for iOS native applications. This Insights enables you to get useful data about vid

Build a viable browser extension Ethereum wallet for Safari on macOS and especially iOS

Safari Wallet This is an experiment to see whether we can build a viable browser extension Ethereum wallet for Safari on macOS and especially iOS. Ove

NextLevel is a Swift camera system designed for easy integration, customized media capture, and image streaming in iOS
NextLevel is a Swift camera system designed for easy integration, customized media capture, and image streaming in iOS

NextLevel is a Swift camera system designed for easy integration, customized media capture, and image streaming in iOS. Integration can optionally leverage AVFoundation or ARKit.

iOS helper library that contains commonly used code in Uptech iOS projects

iOS helper library that contains commonly used code in Uptech iOS projects.

BottomSheet makes it easy to take advantage of the new UISheetPresentationController in SwiftUI with a simple .bottomSheet modifier on existing views.
BottomSheet makes it easy to take advantage of the new UISheetPresentationController in SwiftUI with a simple .bottomSheet modifier on existing views.

BottomSheet makes it easy to take advantage of the new UISheetPresentationController in SwiftUI with a simple .bottomSheet modifier on existing views.

Kanvas is an open-source iOS library for adding effects, drawings, text, stickers, and making GIFs from existing media or the camera.
Kanvas is an open-source iOS library for adding effects, drawings, text, stickers, and making GIFs from existing media or the camera.

Kanvas Kanvas is an open-source iOS library for adding effects, drawings, text, stickers, and making GIFs from existing media or the camera.

Virgil Core SDK allows developers to get up and running with Virgil Cards Service API quickly and add end-to-end security to their new or existing digital solutions to become HIPAA and GDPR compliant and more.
Virgil Core SDK allows developers to get up and running with Virgil Cards Service API quickly and add end-to-end security to their new or existing digital solutions to become HIPAA and GDPR compliant and more.

Virgil Core SDK Objective-C/Swift Introduction | SDK Features | Installation | Configure SDK | Usage Examples | Docs | Support Introduction Virgil Sec

Provides some Apple Wallet functionality, like adding passes, removing passes and checking passises for existing.
Provides some Apple Wallet functionality, like adding passes, removing passes and checking passises for existing.

react-native-wallet-manager Provides some Apple Wallet's functionality, like adding passes, removing passes and checking passises for existing. Instal

An easy to integrate Model Based Google Maps Helper (SVHTTPClient, AFNetworking) That lets you Geo Code , Reverse Geocode, Get Directions , Places Autocomplete.

GoogleMapsHelper Read Me in Russian : http://gargo.of.by/googlemapshelper/ A GOOGLE MAPS Helper that help you do multiple tasks like HOW TO USE // usi

Comments
  • Correct the spelling of CocoaPods in README

    Correct the spelling of CocoaPods in README

    This pull requests corrects the spelling of CocoaPods 🤓 https://github.com/CocoaPods/shared_resources/tree/master/media

    Created with cocoapods-readme.

    opened by ReadmeCritic 1
  • Compatibility with Mixpanel-swift

    Compatibility with Mixpanel-swift

    Mixpanel-swift uses a protocol called MixpanelType for the values in the properties dictionary. This doesn't work with Trackable's trackEventToRemoteServiceClosure since that expects AnyObject as it's value.

    I have yet to find a workaround that doesn't involve modifying the Trackable library, so in the meantime Trackable is only useable with the Mixpanel's Objective-C library (as far as I know).

    opened by timgcarlson 0
  • Remove global values

    Remove global values

    Unit testing with the current situation is quite hard because Trackable is using global values for basic settings, so dependency injection is very difficult. It would be great to support the possibility of running multiple instances at the same time.

    opened by VojtaStavik 0
Releases(0.8)
Simple iOS app blackbox assessment tool. Powered by frida.re and vuejs.

Discontinued Project This project has been discontinued. Please use the new Grapefruit #74 frida@14 compatibility issues frida@14 introduces lots of b

Chaitin Tech 1.6k Dec 16, 2022
SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations.

SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations. Objective Build a stan

Andres Canal 542 Sep 17, 2022
iOS library to help detecting retain cycles in runtime.

FBRetainCycleDetector An iOS library that finds retain cycles using runtime analysis. About Retain cycles are one of the most common ways of creating

Facebook 4.1k Dec 26, 2022
A dynamic library for Cornerstone macOS.

Cornerstone-Hook A dynamic library for Cornerstone macOS. Screenshot Overview Quick Start sudo ./install.sh Install or Upgrade CornerstoneStart.app su

ivar 3 Oct 8, 2022
A library that enables dynamically rebinding symbols in Mach-O binaries running on iOS.

fishhook fishhook is a very simple library that enables dynamically rebinding symbols in Mach-O binaries running on iOS in the simulator and on device

Meta 4.9k Jan 8, 2023
A static source code analysis tool to improve quality and reduce defects for C, C++ and Objective-C

OCLint - https://oclint.org OCLint is a static code analysis tool for improving quality and reducing defects by inspecting C, C++ and Objective-C code

The OCLint Static Code Analysis Tool 3.6k Dec 29, 2022
Measure Swift code metrics and get reports in Xcode, Jenkins and other CI platforms.

Taylor ⚠️ Taylor is DEPRECATED. Use SwiftLint instead. A tool aimed to increase Swift code quality, by checking for conformance to code metrics. Taylo

YOPESO 301 Dec 24, 2022
A tool for Swift code modification intermediating between code generation and formatting.

swift-mod A tool for Swift code modification intermediating between code generation and formatting. Overview swift-mod is a tool for Swift code modifi

Ryo Aoyama 95 Nov 3, 2022
A command-line tool and Xcode Extension for formatting Swift code

Table of Contents What? Why? How? Command-line tool Xcode source editor extension Xcode build phase Via Applescript VSCode plugin Sublime Text plugin

Nick Lockwood 6.3k Jan 8, 2023
A tool to enforce Swift style and conventions.

SwiftLint A tool to enforce Swift style and conventions, loosely based on the now archived GitHub Swift Style Guide. SwiftLint enforces the style guid

Realm 16.9k Jan 9, 2023