# iOS (Swift)

Track screens, goals and signed-in users in native iOS apps with the ProductLense Swift package, attributed to the universal link behind each install.

`ProductLense` is a Swift package with no dependencies. It sends screen views, goals and `identify` from your iOS app to ProductLense, needs no device identifiers, and reports app traffic next to your website: the Hostname breakdown shows your bundle id beside your domain.

## 1. Add your app ID

In ProductLense, open **Settings → General → App IDs** and add your bundle identifier, for example `com.example.app`. Events from any other app id are rejected.

## 2. Install

In Xcode, choose **File → Add Package Dependencies**, enter `https://github.com/productlense/productlense-swift`, and add the `ProductLense` library to your app target. With a `Package.swift`:

```swift title="Package.swift"
.package(url: "https://github.com/productlense/productlense-swift", from: "0.1.0"),
```

iOS 15 or later.

## 3. Start ProductLense and track screens

```swift title="ExampleApp.swift" {1,6,14}
import ProductLense
import SwiftUI

@main
struct ExampleApp: App {
    init() { ProductLense.configure(siteId: "YOUR_SITE_ID", appId: Bundle.main.bundleIdentifier!) }

    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { ProductLense.openURL($0) }
        }
    }
}

// in each screen
.onAppear { ProductLense.screen("Settings") }
```

`siteId` is on **Settings → Snippet**. In UIKit, call `ProductLense.configure` in `application(_:didFinishLaunchingWithOptions:)`, `ProductLense.screen` in `viewDidAppear`, and `ProductLense.openURL` from `scene(_:openURLContexts:)` and `scene(_:continue:)`.

ProductLense keeps the install id, the opt-out choice and unsent events in `UserDefaults`, sends them every 10 seconds, and sends what is left when the app goes to the background.

## 4. Goals and users

```swift
ProductLense.track("signup", props: ["plan": "pro"])
ProductLense.identify(user.id, name: user.name, email: user.email)
```

Call `identify` after sign-in with the user id your billing provider stores on the customer, so app visits, web visits and payments join up. See [how payments are attributed](/docs/revenue/attribution).

## In-app purchases

Connect [RevenueCat](/docs/revenue/revenuecat) and pass the install id once after configuring both SDKs:

```swift
Purchases.shared.attribution.setAttributes(await ProductLense.revenueCatAttributes())
```

Each purchase then lands on the channel that brought the install.

## Attribution

- **Universal links and URL schemes**: pass every URL the app opens with to `ProductLense.openURL`. Only `utm_*`, `ref`, `via`, `source` and click ids leave the device; tokens and ids in the link stay on it.
- **App Store**: Apple shares no referrer, so App Store installs count as Direct unless the first screen opens through a tagged link.

## Privacy

- The SDK creates a random install id on first launch. It is not the advertising id (IDFA), so no App Tracking Transparency prompt is needed for ProductLense. ProductLense stores only a hash of it.
- `ProductLense.optOut()` stops collection, deletes unsent events and forgets the install id; `ProductLense.optIn()` resumes with a new one.
- App Store privacy label: **Product Interaction**, used for **Analytics**, **not used for tracking**.

## Verify your installation

1. Run the app on a device or simulator and open a few screens.
2. Open the Live page in the ProductLense dashboard. Your device appears within a few seconds.
3. Open **Events**: each screen is a `pageview` row with your bundle id as the hostname and `iOS app` as the browser.
4. Pass `debug: true` to `ProductLense.configure` to print dropped events and failed sends.

If nothing appears, check the app id in Settings and follow [Verify your installation](/docs/install/verify).
