{"id":874,"url":"https://github.com/VojtaStavik/Trackable","last_synced_at":"2025-07-30T19:32:55.402Z","repository":{"id":69193923,"uuid":"47505887","full_name":"VojtaStavik/Trackable","owner":"VojtaStavik","description":"Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing projects.","archived":true,"fork":false,"pushed_at":"2019-04-26T14:52:40.000Z","size":548,"stargazers_count":145,"open_issues_count":3,"forks_count":10,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-08-14T14:05:11.557Z","etag":null,"topics":["analytics","helper","swift"],"latest_commit_sha":null,"homepage":"http://vojtastavik.com/2016/01/07/trackable-swift-app-analytics-using-protocols/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VojtaStavik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-12-06T17:13:25.000Z","updated_at":"2024-01-17T12:59:47.000Z","dependencies_parsed_at":"2023-03-11T05:28:15.451Z","dependency_job_id":null,"html_url":"https://github.com/VojtaStavik/Trackable","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VojtaStavik%2FTrackable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VojtaStavik%2FTrackable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VojtaStavik%2FTrackable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VojtaStavik%2FTrackable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VojtaStavik","download_url":"https://codeload.github.com/VojtaStavik/Trackable/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228178962,"owners_count":17881114,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","helper","swift"],"created_at":"2024-01-05T20:15:33.541Z","updated_at":"2024-12-04T19:32:13.074Z","avatar_url":"https://github.com/VojtaStavik.png","language":"Swift","funding_links":[],"categories":["Code Quality"],"sub_categories":["Other free courses","Getting Started"],"readme":"# Trackable\n[![Build Status](https://travis-ci.org/VojtaStavik/Trackable.svg?branch=master)](https://travis-ci.org/VojtaStavik/Trackable) [![codecov](https://codecov.io/gh/VojtaStavik/Trackable/branch/master/graph/badge.svg)](https://codecov.io/gh/VojtaStavik/Trackable)\n![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-brightgreen.svg)\n[![Swift Version](https://img.shields.io/badge/Swift-3.0.x-F16D39.svg?style=flat)](https://developer.apple.com/swift)\n\n**Trackable** is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing projects.\n\n---\n\n### Main features:\n- [x] Easy integration to existing classes using extensions and protocols\n- [x] Programmatically generated event and property identifiers\n- [x] 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”)*\n\n---\n\n### Instalation\n\n#### CocoaPods\n\n[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:\n\n```bash\n$ gem install cocoapods\n```\n\nTo integrate Trackable into your Xcode project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '9.0'\nuse_frameworks!\n\npod 'Trackable'\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\n#### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.\n\nYou can install Carthage with [Homebrew](http://brew.sh/) using the following command:\n\n```bash\n$ brew update\n$ brew install carthage\n```\n\nTo integrate trackable into your Xcode project using Carthage, specify it in your `Cartfile`:\n\n```ogdl\ngithub \"VojtaStavik/Trackable\"\n```\n\nRun `carthage update` to build the framework and drag the built `Trackable.framework` into your Xcode project.\n\n---\n\n## Usage\n\nIntegration of the **Trackable** library is very easy and straightforward. See **example app** with complete implementation including all features.\n\n### Events and Keys\n\nDefine 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 ```“\u003cModuleName\u003e.Events.App.started”``` string.\n\n```swift\nenum Events {\n    enum User : String, Event {\n        case didSelectBeatle\n        case didSelectAlbum\n        case didRateAlbum\n    }\n\n    enum App : String, Event {\n        case started\n        case didBecomeActive\n        case didEnterBackground\n        case terminated\n    }\n\n    enum AlbumListVC : String, Event {\n        case didAppear\n    }\n}\n\nenum Keys : String, Key {\n    case beatleName\n    case albumName\n    case userLikesAlbum\n    case previousVC\n\n    enum App : String, Key {\n        case uptime\n        case reachabilityStatus\n    }\n}\n```\n\n### Tracking\n\nYou 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\u003cTrackedProperty\u003e)``` if you want to add some specific properties to the tracked event.\n\n```TrackedProperty``` is a struct you can create using a custom infix operator ```~\u003e\u003e``` with ```Key``` and value. Allowed value types are ```String```, ```Double```, ```Int```, ```Bool``` and ```Set\u003cTrackedProperty\u003e```.\n\n```swift\n// Example:\n\nimport UIKit\nimport Trackable\n\nclass AlbumDetailVC: UIViewController {\n\n    var album : Album!\n\n    @IBOutlet weak var yesButton: UIButton!\n    @IBOutlet weak var noButton: UIButton!\n\n    @IBAction func didPressButton(sender: UIButton) {\n        let userLikesAlbum = (sender === yesButton)\n        track(Events.User.didRateAlbum, trackedProperties: [Keys.userLikesAlbum ~\u003e\u003e userLikesAlbum])\n    }\n}\n\nextension AlbumDetailVC : TrackableClass { }\n```\n\n\n### Tracked properties\n\n**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.\n\n#### Level 3  \n-\twhen calling track()function\n-\tproperties on this level will be added only to the currently tracked event\n-\t**Typical usage:** When you want to track properties closely connected to the event.\n\n```swift\n// Example:\ntrack(Events.User.didRateAlbum, trackedProperties: [Keys.userLikesAlbum ~\u003e\u003e userLikesAlbum])\n```\n\n#### Level 2\n-\tinstance properties added by calling ```setupTrackableChain(trackedProperties:)``` on a ```TrackableClass``` instance.\n-\tthese properties will be added to all events tracked on the object\n-\t**Typical usage:** When you want to set properties from the outside of the object (the object doesn’t know about them)\n\n```swift\n// Example:\nimport UIKit\nimport Trackable\n\nclass AlbumListTVC: UITableViewController {\n\t… code …\n\n    // MARK: - Navigation\n    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {\n        let destinationVC = segue.destinationViewController as! AlbumDetailVC\n        destinationVC.setupTrackableChain([Keys.previousVC ~\u003e\u003e \"Album list\"]) // all events tracked on destinationVC will have previousVC property included automatically\n    }\n}\n\nextension AlbumListTVC : TrackableClass { }\n```\n\n\n\n#### Level 1\n-\tcomputed properties added by custom implementation of the ```TrackableClass``` protocol\n-\tthese properties will be added to all events tracked on the object\n-\t**Typical usage:** When you want to add some set of properties to all events tracked on the object.\n\n```swift\n// Example:\nclass AlbumListTVC: UITableViewController {\n    var albums : [Album]!\n\n    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {\n        track(Events.User.didSelectAlbum) // selectedAlbum property will be added automatically\n    }\n\n    var selectedAlbum : Album? {\n        if let indexPath = tableView.indexPathForSelectedRow {\n            return albums[indexPath.row]\n        } else {\n            return nil\n        }\n    }\n}\n\nextension AlbumListTVC : TrackableClass {\n    var trackedProperties : Set\u003cTrackedProperty\u003e {\n        return [Keys.albumName ~\u003e\u003e selectedAlbum?.name ?? \"none\"]\n    }\n}\n```\n\n### Chaining\n**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.\n\n```swift\n// Example:\nimport UIKit\nimport Trackable\n\nclass AlbumListTVC: UITableViewController {\n\n\t… some code here …\n\n    // MARK: - Navigation\n    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {\n        let destinationVC = segue.destinationViewController as! AlbumDetailVC\n        destinationVC.setupTrackableChain([Keys.previousVC ~\u003e\u003e \"Album list\"], parent: self)\n    }\n\n    var selectedAlbum : Album? {\n        if let indexPath = tableView.indexPathForSelectedRow {\n            return albums[indexPath.row]\n        } else {\n            return nil\n        }\n    }\n}\n\nextension AlbumListTVC : TrackableClass {\n    var trackedProperties : Set\u003cTrackedProperty\u003e {\n        return [Keys.albumName ~\u003e\u003e selectedAlbum?.name ?? \"none\"]\n    }\n}\n\n// All events tracked later on destinationVC will automatically have previousVC and albumName properties,\n// without destinationVC even knowing those values exist!\n```\n\n\n### Connecting to Mixpanel (or any other service)\nIn order to perform the actual tracking into an analytics service, you have to provide an implementation for ```Trackable.trackEventToRemoteServiceClosure```.\n\n```swift\n// Example:\nimport Foundation\nimport Mixpanel\nimport Trackable\n\nlet analytics = Analytics() // singleton (yay!)\n\nclass Analytics {\n    let mixpanel = Mixpanel.sharedInstanceWithToken(\"\u003ctoken\u003e\")\n\n    init() {\n        Trackable.trackEventToRemoteServiceClosure = trackEventToMixpanel\n        setupTrackableChain() // allows self to be part of the trackable chain\n    }\n\n    func trackEventToMixpanel(eventName: String, trackedProperties: [String: AnyObject]) {        \n        mixpanel.track(eventName, properties: trackedProperties)\n    }\n}\n\nextension Analytics : TrackableClass { }\n```\n\nMaybe 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:\n\n```swift\nextension Analytics : TrackableClass {\n    var trackedProperties : Set\u003cTrackedProperty\u003e {\n        return [Keys.App.uptime ~\u003e\u003e NSDate().timeIntervalSinceDate(startTime)]\n    }\n}\n```\n and set the analytics object as a parent to all objects without a parent by calling ```setupTrackableChain(parent: analytics)``` on them:\n\n```swift\n// Example:\nimport UIKit\nimport Trackable\n\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n    var window: UIWindow?\n\n    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -\u003e Bool {\n        setupTrackableChain(parent: analytics)\n        return true\n    }\n\n    func applicationDidBecomeActive(application: UIApplication) {\n        track(Events.App.didBecomeActive)\n    }\n\n    func applicationDidEnterBackground(application: UIApplication) {\n        track(Events.App.didEnterBackground)\n    }\n\n    func applicationWillTerminate(application: UIApplication) {\n        track(Events.App.terminated)\n    }\n\n}\n\nextension AppDelegate : TrackableClass { }\n```\n\n\n## License\n\n**Trackable** is released under the MIT license. See LICENSE for details.\n\n\n---\n\n*Readme inspired by [Alamofire](https://github.com/Alamofire/Alamofire)*. Thank you!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FVojtaStavik%2FTrackable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FVojtaStavik%2FTrackable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FVojtaStavik%2FTrackable/lists"}