ReferenceAvo CodegenProgramming languagesSwift

Avo Codegen in Swift

Platforms

Avo can code generate Avo Codegen in Swift targeted at the following platforms

  • iOS
  • macOS

Quickstart

Avo Codegen usage consists of 4 steps.

Step 1. Include the Avo file

Pull the generated code with the Avo CLI

To get the Avo generated Swift file you must be a member of an Avo workspace with a Swift source. Ask for an invite from a colleague or create a new workspace

npm install -g avo
avo login
avo pull --branch my-branch-name

Learn more about the CLI here.

You can also download the file manually from your Avo workspace.

Step 2. Initialize Avo

Initialize Avo by creating an object using constructor from the generated Avo file

val avo = Avo(env: .dev/*, other parameters depending on your tracking plan setup*/)

The actual parameters depend on your tracking plan setup, see the parameters explanation in the reference below.

Step 3. Call Avo Codegen to track your product usage

Every event in your tracking plan, marked with the “Implement with Codegen” checkbox, gets a function in the generated code, named according to the event name, in camelCase.

For example, if you have a “Signup Start” event defined like this in Avo:

Event 'Signup Start' defined in Avo with referral string property and implement with Codegen check You’ll be able to call it like this from the generated code

avo.signupStart(referral: "direct")

Notice, that you are not passing the System property with the call. System properties are defined on the init step and then automatically included with all events. You can update the system properties with setSystemProperties function.

Step 4. Verify the implementation

Use the Implementation status in your Avo workspace and the Avo Inspector to verify that your implementation is correct. If you don’t want to use Avo Inspector you can use the standalone visual debugger.

Step 5. Suppress warnings in the Avo files

Because of the nature of the code generation Avo files can sometimes contain warnings, that do not affect the execution of the code, but may distract you. To avoid it we suggest to disable the warning in the Avo generated files.

To do that:

  1. Select the file you want to suppress warnings for in the Xcode project navigator.
  2. Click on the file to open its details view in the right-hand pane.
  3. In the details view, click on the “Build Phases” tab.
  4. In the “Compile Sources” section, find the file you want to suppress warnings for and click on it to select it.
  5. Click on the “Compiler Flags” column next to the selected file, and add the -w -Xanalyzer -analyzer-disable-all-checks flags to suppress warnings.
  6. Save your changes, restart Xcode and rebuild your project.

Xcode setup screenshot

Reference

Constructor

public init(env: AvoEnv,
    // Other parameters may not be present, depending on your tracking plan
    systemProperty0: Int, systemProperty1: Bool,
    mixpanelDestination: AvoCustomDestination,
    segmentDestination: AvoCustomDestination,
    otherDestination: AvoCustomDestination,
    strict: Bool = true, noop: Bool = false)

Creates the Avo object that will be used to track. This method will call the make(env, apiKey) callback in all the provided destination interfaces. It will also initialize the analytics SDKs of the legacy Avo Managed destinations.

Arguments

env: AvoEnv: Can be set to dev, prod and staging.

systemProperties: a number of parameters equal to the number of system properties defined in your Avo workspace. The parameters are named the same as system properties, in camelCase, and require corresponding types: string, int, long, float, bool, list, object or any.

destination: AvoCustomDestination: object, each destination you are sending events to gets a separate parameter in the init function with callbacks that the Avo generated code will trigger, unless you are using the legacy Avo managed destinations. Each method in the destination interface is directly mapped to the Actions attached to each event in Avo. Learn more about event Actions in this doc.

public protocol AvoCustomDestination {
    func make(env: AvoEnv, apiKey: String) // This method is optional, you can skip it if you've already initialized your Analytics SDK
    func logEvent(eventName: String, eventProperties: [String:Any])
    func logPage(pageName: String, eventProperties: [String:Any])
    func revenue(amount: Double, eventProperties: [String:Any])
    func setUserProperties(userId: String, userProperties: [String:Any])
    func identify(userId: String)
    func unidentify()
}

strict: Bool = true: bool, default value is true, if true, Avo will throw an exception when it detects a tracking problem in development or staging. Note that the strict flag is ignored in production.

noop: Bool = false: bool, default value is false, if true, Avo won’t make any network calls (no tracking) in development and staging environments. Note that the noop flag is ignored in production.

Note that you do not need to pass Avo Inspector instance to the constructor. It will be automatically picked up if you include the library and enable Avo Inspector for your iOS source in the Avo workspace. Read more here.

Destination interface example

Find more examples here: https://github.com/avohq/destination-interface-code-snippets/blob/main/swift/ios/

# Example: Destination interface for the Mixpanel SDK. Replace the Mixpanel implementation with your own tracking SDK methods
class CustomDestination : AvoCustomDestination {
    func make(env: AvoEnv, apiKey: String) {
        Mixpanel.initialize(token: apiKey)
    }
    
    func logEvent(eventName: String, eventProperties: [String : Any]) {
        Mixpanel.mainInstance().track(event: eventName, properties: eventProperties as? Properties)
    }
    
    func setUserProperties(userId: String, userProperties: [String : Any]) {
        if !userProperties.isEmpty {
            Mixpanel.mainInstance().people.set(properties: userProperties as! Properties)
        }
    }
 
    func logPage(pageName: String, eventProperties: [String:Any]) {
        // Note: Mixpanel does not provide a native method for page or screen tracking, so we send an event instead. Other SDKs may have a dedicated page tracking method.        
        Mixpanel.mainInstance().track(event: "Page Viewed", properties: eventProperties as? Properties)
    }
 
    func revenue(amount: Double, eventProperties: [String:Any]) {
        Mixpanel.mainInstance().people.trackCharge(amount: amount, properties: eventProperties as? Properties)
    }
 
    func identify(userId: String) {
        Mixpanel.mainInstance().identify(distinctId: userId)
    }
    
    func unidentify() {
        Mixpanel.mainInstance().reset()
    }
}

Read more about the destination interface here.

avoLogger

var avoLogger: AvoLogger

where avoLogger conforms to a protocol

public protocol AvoLogger {
    func logDebug(env: AvoEnv, message: String) -> Bool
    func logWarn(env: AvoEnv, message: String) -> Bool
    func logError(env: AvoEnv, message: String) -> Bool
}

Allows you to provide custom implementation of the logger used by Avo Codegen. Can for example be used to disable logs or change which logging method is used.

Find the code snippet here.

setSystemProperties

public func setSystemProperties(systemProperty0: Int, systemProperty1: Bool?, ...)

A method to update system properties after initialization.

Arguments

systemProperties: a number of parameters equal to the number of system properties defined in your Avo workspace. The parameters are named the same as system properties, in camelCase, and require corresponding types: string, int, long, float, bool, list, object or any.

Event tracking functions

public func [yourEventName](eventProperty0: Int, eventProperty1: Double?, ..., userProperty0: Bool?, userProperty1: [Int], ..., userId_: String)

Every event you define in your tracking plan in Avo gets a function named after the event in camelCase. The arguments of the function depend on how it’s defined in your tracking plan

Arguments

eventProperty: type defined in the Avo tracking plan, can be string, int, long, float, bool, list, object and any: Every event property attached to the event in the Avo UI gets a corresponding argument. The argument key is camelCase version of the property name. Pass the value of the property to track here.

userProperty: type defined in the Avo tracking plan as a user property, can be string, int, long, float, bool, list, object and any: Every user property attached to the event in the Avo UI gets a corresponding argument. The argument key is camelCase version of the property name. Pass the value of the property to update here.

userId_: String: used to connect event to specific user. Added if the event has the Identify User action

Snowplow interface

Snowplow SDK’s tracking interface is a little different from the common event tracking libraries and working with Snowplow through Avo is slightly different too.

If you add a snowplow destination to a Swift source you’ll get an additional constructor parameter

snowplowDestination: AvoSnowplowDestination

You’ll implement it like this:

extension SnowplowDestination: AvoSnowplowDestination {
    func make(env: AvoEnv) {
        // Your custom Snowplow initialization, that includes the `createTracker` call
        Snowplow.createTracker(namespace: "appTracker", endpoint: "COLLECTOR_URL", method: .post)
        // Learn more: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/mobile-trackers-v2-0/quick-start-guide/#iOS_Tracker
    }
 
    func trackSelfDescribingEvent(schema: String, data: [String: Any], contexts: [[String: Any]]) {
        let event = SelfDescribing(schema: schema, payload: data)
 
        contexts.forEach { context in
            event.contexts.add(
                SelfDescribingJson(schema: context["schema"],
                    andDictionary: context["data"]))
        }
 
        Snowplow.getDefaultTracker().track(event)
        // Learn more: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/mobile-trackers-v2-0/tracking-events/#Self_Describing
    }
 
    func trackPageView(name: String) {
        Snowplow.getDefaultTracker().track(ScreenView(name: name))
        // Learn more: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/installation-and-set-up/ios-tracker/#setting-up
    }
 
    func identify(userId: String) {
        Snowplow.getDefaultTracker().subject.setUserId(userId)
        // Learn more: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/mobile-trackers-v2-0/introduction/#SubjectConfiguration
    }
 
    func unidentify() {
        Snowplow.getDefaultTracker().subject.setUserId(null)
        // Learn more: https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/mobile-trackers/mobile-trackers-v2-0/introduction/#SubjectConfiguration
    }
}
 
let avo = Avo(..., snowplowDestination: SnowplowDestination())

Destinations

You can send your data using the Avo generated Swift code to any data destination that accepts custom events, including:

  • Amplitude
  • FacebookAnalytics
  • FullStory
  • Mixpanel
  • Mixpanel
  • Permutive
  • Segment
  • Snowplow
  • ZendeskConnect
  • Adobe Analytics
  • Apptelemetry
  • RudderStack
  • Freshpaint
  • PostHog
  • Google Analytics 4 / Firebase Analytics
  • Heap
  • Keen
  • Kissmetrics
  • LaunchDarkly Events
  • Pendo
  • Fivetran
  • AppsFlyer
  • Braze
  • Intercom
  • A home made SDK
  • Internal API