Phase
Get Started

Swift

llms.txt

Installation

Add Swift Package

Add Phase Analytics to your project using Swift Package Manager:

  1. In Xcode, go to File → Add Package Dependencies
  2. Enter the repository URL:

    https://github.com/Phase-Analytics/Phase-Swift

  3. Select the latest version
  4. Add to your target

Or add to Package.swift:

Swift
Package.swift
dependencies: [
    .package(url: "https://github.com/Phase-Analytics/Phase-Swift", from: "0.1.3")
]

Requirements:

  • iOS 15.0+ or macOS 12.0+
  • Swift 6.0+

Get Your API Key

  1. Sign in to Phase Dashboard
  2. Create a new project or select an existing one
  3. Open API Keys tab
  4. Copy your API Key (starts with phase_)

Setup

SwiftUI

Wrap your app with the Phase view to initialize the SDK:

Swift
MyApp.swift
import SwiftUI
import PhaseAnalytics

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            Phase(apiKey: "phase_xxx") {
                ContentView()
            }
        }
    }
}

UIKit

Initialize the SDK in your AppDelegate:

Swift
AppDelegate.swift
import UIKit
import PhaseAnalytics

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        Task {
            try await PhaseSDK.shared.initialize(apiKey: "phase_xxx")
        }
        return true
    }
}

The SDK initialization is asynchronous. You must call identify() before tracking events.

Configuration

The Phase view and initialize() method accept the following parameters:

Prop

Type

Usage

Identify User

Required: Call identify() before using any other methods. This registers the device and starts a session.

Swift
ContentView.swift
import SwiftUI
import PhaseAnalytics

struct ContentView: View {
    var body: some View {
        Text("Hello, World!")
            .onAppear {
                Task {
                    // Initialize analytics - no PII collected by default
                    await PhaseSDK.shared.identify()
                }
            }
    }
}

Privacy by default:

  • No personal data is collected without explicit properties
  • Device ID is auto-generated and stored locally
  • Only technical metadata is collected (OS version, platform, locale)

Adding custom properties:

You can optionally attach user properties. Important: If you add PII (personally identifiable information), ensure you have proper user consent:

// After user login and consent
await PhaseSDK.shared.identify([
    "user_id": "123",
    "plan": "premium",
    "beta_tester": true
])

// ⚠️ If adding PII, get consent first
let hasConsent = await customGetUserConsent()
if hasConsent {
    await PhaseSDK.shared.identify([
        "email": "[email protected]",
        "name": "John Doe"
    ])
}

Properties must be primitives: String, Int, Double, Bool, or nil.

Track Events

Track custom events with optional parameters. Note: identify() must be called first.

// Event without parameters
track("app_opened")

// Event with parameters
track("purchase_completed", [
    "amount": 99.99,
    "currency": "USD",
    "product_id": "premium_plan"
])

// Using instance method
PhaseSDK.shared.track("button_clicked", params: ["button_id": "submit"])

Event naming rules:

  • Alphanumeric characters, underscores (_), hyphens (-), periods (.), and forward slashes (/)
  • 1-256 characters
  • Examples: purchase, user.signup, payment/success

Event parameters:

  • Must be primitives: String, Int, Double, Bool, or nil

Screen Tracking

Use the .phaseScreen() modifier to automatically track screen views:

Swift
ProfileView.swift
import SwiftUI
import PhaseAnalytics

struct ProfileView: View {
    let userID: String

    var body: some View {
        VStack {
            Text("Profile")
        }
        .phaseScreen("ProfileView", params: ["user_id": userID])
    }
}

How it works:

Tracks screen view when the view first appears. Screen names are normalized automatically (e.g., "ProfileView""/profile-view") with CamelCase converted to kebab-case. Supports optional parameters.

Manually track screens using trackScreen():

// Using global function
trackScreen("/profile", ["user_id": "123"])

// Using instance method
PhaseSDK.shared.trackScreen("/settings", params: nil)

Type Reference

DeviceProperties

Custom user/device attributes passed to identify():

Prop

Type

EventParams

Event parameters passed to track():

Prop

Type

How It Works

Offline Support

Events are queued locally using UserDefaults when offline. The queue automatically syncs when connection is restored.

Privacy

  • No personal data is collected by default
  • Device IDs are generated locally and stored persistently
  • Geolocation is resolved server-side from IP address (disable with properties)
  • All data collection is optional via configuration

Performance

  • Offline events are batched and sent asynchronously
  • Network state is monitored automatically
  • Failed requests retry with exponential backoff
  • Maximum batch size: 1000 events
  • Thread-safe with Swift 6 concurrency