Giter VIP home page Giter VIP logo

umbrella's Introduction

☂️ Umbrella

Swift CocoaPods Build Status Codecov

Analytics abstraction layer for Swift. Inspired by Moya.

Table of Contents

Why?

There are many tools for mobile app analytics such as Firebase, Google Analytics, Fabric Answers, Flurry, Mixpanel, etc. You might use one or more of those in your application. But most of those SDKs have some problems: if you use multiple analytics tools, your code will be messed up. And the SDKs take event name as a string and parameters as a dictionary which is not guaranteed by Swift compiler. It means that if you change the event definition, you should find all related code by your hand. It has an opportunity that cause a human error. Umbrella uses Swift enums and the associated values to solve these problems.

Features

  • 💪 Taking advantages of Swift compiler by using an enum and associated values.
  • 🎯 Logging events to multiple analytics providers at once.
  • 🎨 Creating custom analytics providers.

At a Glance

Before 🤢

FIRAnalytics.logEvent(withName: kFIREventEcommercePurchase, parameters: [
  kFIRParameterCurrency: "USD" as NSObject,
  kFIRParameterValue: 9.99 as NSNumber,
  kFIRParameterTransactionID: "20170709123456" as NSObject,
])
Flurry.logEvent("purchase", withParameters: [
  "Currency": "USD",
  "Price": 9.99,
  "Transaction ID": "20170709123456"
])
MyCustomAnalytics.logEvent("purchase", withParameters: [
  "currency": "USD",
  "price": 9.99,
  "transaction_id": "20170709123456"
])

After 😊

let analytics = Analytics<MyAppEvent>()
analytics.register(provider: FirebaseProvider())
analytics.register(provider: FlurryProvider())
analytics.register(provider: MyCustomProvider())
analytics.log(.purchase(currency: "USD", price: 9.99, transactionID: "20170709123456"))

Getting Started

Defining Events

First of all, you should define all of your events in a single enum. Let's assume that we have three events that have associated parameters.

enum MyAppEvent {
  case signup(username: String)
  case viewContent(productID: Int)
  case purchase(productID: Int, price: Float)
}

Then make the enum to conform the protocol EventType. It requires two functions: name(for:) and parameters(for:).

extension MyAppEvent: EventType {
  /// An event name to be logged
  func name(for provider: ProviderType) -> String? {
    switch self {
    case .signup: return "signup"
    case .viewContent: return "view_content"
    case .purchase: return "purchase"
    }
  }

  /// Parameters to be logged
  func parameters(for provider: ProviderType) -> [String: Any]? {
    switch self {
    case let .signup(username):
      return ["username": username]
    case let .viewContent(productID):
      return ["product_id": productID]
    case let .purchase(productID, price):
      return ["product_id": productID, "price": price]
    }
  }
}

You can even provide different event names and parameters by providers.

Using Analytics

You can define an Analytics instance anywhere but it's recommended to define at a global scope.

let analytics = Analytics<MyAppEvent>()

Then you should register providers. A prodiver is a wrapper for an actual analytics service such as Firebase and Fabric Answers. It's recommended to register providers in application(_:didFinishLaunchingWithOptions:).

analytics.register(provider: AnswersProvider())
analytics.register(provider: FirebaseProvider())
analytics.register(provider: FlurryProvider())
analytics.register(provider: MyAwesomeProvider())

If you finished those steps, you can now log the events 🎉

analytics.log(.signup(username: "devxoul"))

Built-in Providers

There are several built-in providers.

If there's no provider you're looking for, you can create an issue or create custom providers. It's also welcomed to create a pull request for missing services 🎉

Creating Custom Providers

If there's no built-in provider for the serivce you're using, you can also create your own. It's easy to create a provider: just create a class and conform to the protocol ProviderType.

final class MyAwesomeProvider: ProviderType {
  func log(_ eventName: String, parameters: [String: Any]?) {
    AwesomeAnalytics.logEvent(withName: eventName, parameters: parameters)
  }
}

Installation

Umbrella currently support CocoaPods only.

pod 'Umbrella'
pod 'Umbrella/Firebase' # using with built-in FirebaseProvider
pod 'Umbrella/...'

Contributing

Any discussions and pull requests are welcomed 💖

Generating Xcode Workspace

$ make project

This will automatically generate Umbrella.xcworkspace and perform pod install.

Creating New Provider

For example, imagine that we are going to create a new provider for an analytics service 'Raincoat'.

  1. Add a library and a target definition in Package.swift.

      let package = Package(
        name: "Umbrella",
        products: [
          .library(name: "Umbrella", targets: ["Umbrella"]),
          .library(name: "UmbrellaFirebase", targets: ["UmbrellaFirebase"]),
          .library(name: "UmbrellaMixpanel", targets: ["UmbrellaMixpanel"]),
    +     .library(name: "UmbrellaRaincoat", targets: ["UmbrellaRaincoat"]),
        ],
        targets: [
          .target(name: "Umbrella"),
          .target(name: "UmbrellaFirebase", dependencies: ["Umbrella"]),
          .target(name: "UmbrellaMixpanel", dependencies: ["Umbrella"]),
    +     .target(name: "UmbrellaRaincoat", dependencies: ["Umbrella"]),
          .testTarget(name: "UmbrellaTests", dependencies: ["Umbrella"]),
          .testTarget(name: "UmbrellaFirebaseTests", dependencies: ["UmbrellaFirebase"]),
          .testTarget(name: "UmbrellaMixpanelTests", dependencies: ["UmbrellaMixpanel"]),
    +     .testTarget(name: "UmbrellaRaincoat", dependencies: ["UmbrellaRaincoat"]),
        ]
      )
  2. Add a source file and a test file.

      ...
      ├── Sources
      │   ├── UmbrellaFirebase
      │   │   └── FirebaseProvider.swift
      │   ├── UmbrellaMixpanel
      │   │   └── MixpanelProvider.swift
    + │   ├── UmbrellaRaincoat
    + │   │   └── RaincoatProvider.swift
      |   ...
      ├── Tests
      │   ├── UmbrellaFirebaseTests
      │   │   └── FirebaseProviderTests.swift
      │   ├── UmbrellaMixpanelTests
      │   │   └── MixpanelProviderTests.swift
    + │   ├── UmbrellaRaincoatTests
    + │   │   └── RaincoatProviderTests.swift
      ... ...
  3. Add a CocoaPods dependency in Podfile.

     target 'UmbrellaFirebaseTests' do
       platform :ios, '8.0'
       pod 'Firebase/Analytics'
     end
    
     target 'UmbrellaMixpanelTests' do
       platform :ios, '8.0'
       pod 'Mixpanel'
     end
    
    + target 'UmbrellaRaincoatTests' do
    +   platform :ios, '8.0'
    +   pod 'Raincoat'
    + end
  4. Add a CocoaPods subspec in Umbrella.podspec.

      s.subspec "Firebase" do |ss|
        ss.source_files = "Sources/UmbrellaFirebase/*.swift"
        ss.dependency "Umbrella/Core"
      end
    
      s.subspec "Mixpanel" do |ss|
        ss.source_files = "Sources/UmbrellaMixpanel/*.swift"
        ss.dependency "Umbrella/Core"
      end
    
    + s.subspec "Raincoat" do |ss|
    +   ss.source_files = "Sources/UmbrellaRaincoat/*.swift"
    +   ss.dependency "Umbrella/Core"
    + end
  5. Create a Xcode workspace and run tests. Don't forget to check the code coverage to ensure that tests can cover the new provider.

    $ make project

License

Umbrella is under MIT license. See the LICENSE file for more info.

umbrella's People

Contributors

devxoul avatar murselturk avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.