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
| Event | Level | When | Attributes |
|---|---|---|---|
sdk:screen_appeared | debug | View appears | screenName set to the provided name |
sdk:screen_disappeared | debug | View disappears | screenName 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.
