Owlmetry
SDKsSwift SDK

Screen Tracking

Automatically track screen views with the .owlScreen() SwiftUI view modifier.

The .owlScreen() SwiftUI view modifier automatically tracks screen appearances and time-on-screen with no manual event calls needed.

Usage

Attach .owlScreen() to the outermost view of each screen:

struct HomeView: View {
    var body: some View {
        ScrollView {
            // ...
        }
        .owlScreen("Home")
    }
}

struct SettingsView: View {
    var body: some View {
        Form {
            // ...
        }
        .owlScreen("Settings")
    }
}

What It Emits

EventLevelWhenAttributes
sdk:screen_appeareddebugView appearsscreenName set to the provided name
sdk:screen_disappeareddebugView disappearsscreenName set, _duration_ms with time the screen was visible

Both screen events are debug-level, so they're filtered out of the default production view. Switch to development data (or filter by level) to see screen flow when you need it. The screen_disappeared event carries _duration_ms and is the more useful signal for analytics; screen_appeared is retained so you can detect screens that were opened but never closed (e.g. a crash mid-screen).

Placement Guidelines

Apply .owlScreen() to the outermost container of each distinct screen in your app. Typical attachment points are NavigationStack, Form, ScrollView, or the root VStack:

struct ProfileView: View {
    var body: some View {
        VStack {
            ProfileHeader()
            PostList()
        }
        .owlScreen("Profile")
    }
}

Example with NavigationStack

struct ContentView: View {
    var body: some View {
        NavigationStack {
            List {
                NavigationLink("Profile") {
                    ProfileView()
                }
                NavigationLink("Settings") {
                    SettingsView()
                }
            }
            .navigationTitle("Home")
        }
        .owlScreen("Home")
    }
}

struct ProfileView: View {
    var body: some View {
        VStack {
            Text("Profile content")
        }
        .owlScreen("Profile")
        .navigationTitle("Profile")
    }
}

struct SettingsView: View {
    var body: some View {
        Form {
            Section("General") {
                Toggle("Notifications", isOn: .constant(true))
            }
        }
        .owlScreen("Settings")
        .navigationTitle("Settings")
    }
}

Each navigation destination tracks its own screen view and duration independently.

Naming Conventions

Choose screen names that are short, readable, and consistent across the app:

  • "Home", "Profile", "Settings", "Checkout"
  • For detail screens: "Product Detail", "Order Detail"
  • For flows: "Signup Step 1", "Signup Step 2"

The screenName value is also available as a filter in the events dashboard, so consistent naming makes filtering straightforward.

Screen Tracking vs Manual Events

Use .owlScreen() for tracking when a screen is viewed and how long a user stays. Use manual Owl.info() with the screenName parameter for events that happen within a screen (button taps, state changes, errors):

struct CartView: View {
    var body: some View {
        VStack {
            // ...
            Button("Place Order") {
                Owl.info("Order placed", screenName: "Cart", attributes: ["items": "\(cart.count)"])
            }
        }
        .owlScreen("Cart")
    }
}

The .owlScreen() modifier handles the screen view tracking, while Owl.info() with screenName: "Cart" ties the button tap event to the same screen context.

Ready to get started?

Connect your agent via MCP or CLI and start tracking.