Skip to content
Documentation

Documentation

iOS (Swift)

Add the SDK, configure it, handle ATT properly, bind purchases, forward universal links.

Requirements

  • The package ships its own privacy manifest (PrivacyInfo.xcprivacy) with the required-reason API declarations, so App Store Connect's ITMS-91053 check passes without work on your side.
  • NSUserTrackingUsageDescription in Info.plist. Without it the ATT prompt cannot appear at all, and without consent there is no advertising id.
  • Your App Privacy answers on App Store Connect should include the SDK's collection: device identifiers (IDFV, and IDFA when authorised), purchase history, product interaction and usage data, used for analytics and, if you push conversions back to ad platforms, third-party advertising. Confirm against your own app's actual usage.

1. Add the dependency

CocoaPods, pinned to a tag. The pod is served from git, not the CocoaPods trunk, so the source must be named:

ruby
pod 'RoasSensor', :git => 'https://github.com/rishabhrk2345/Roas-ios-SDK.git', :tag => '0.1.10'
Copy the exact line from SDK integration in the panel; it pins the current version.

Or Swift Package Manager: add the same repository URL as a package and pin the same version.

2. Configure

The entry point is configure, not initialize -- the Android name does not compile here. Call it once at launch.

swift
import RoasSensor

// AppDelegate.application(_:didFinishLaunchingWithOptions:), or your SwiftUI App's init
Roas.configure(
    publicKey: "YOUR_PUBLIC_KEY",
    requestTrackingAuthorization: false,   // ask later, at a moment of your choosing (§3)
    appSecret: Bundle.main.infoDictionary?["ROAS_APP_SECRET"] as? String,
    baseUrl: "https://api.roassensor.com"
)

baseUrl is printed by the panel and must be passed explicitly, for the same reason as on Android: the default is the production host, and a wrong one fails silently.

3. App Tracking Transparency

Left at its default, the ATT prompt fires about half a second after configure -- a cold-start system alert before the user has seen anything, which is the classic way to depress opt-in. Every denial costs the IDFA, and iOS never asks again.

Pass requestTrackingAuthorization: false and ask at a moment you choose, after onboarding:

swift
Roas.requestTrackingAuthorization {
    // called once the user has answered, either way
}

SKAdNetwork registration happens once, at install, automatically. If you use SKAN conversion values, Roas.updateConversionValue(...) forwards them; it never lowers a value you have already set.

4. The app secret

An .xcconfig that is not committed, surfaced through Info.plist:

text
// Secrets.xcconfig (gitignored)
ROAS_APP_SECRET = your-secret

// Info.plist
<key>ROAS_APP_SECRET</key>
<string>$(ROAS_APP_SECRET)</string>
Then read it as in §2. A missing key reads as nil, which is exactly right: absent must mean absent, never an empty string.

5. Bind purchases to the install

Apple's notification names the transaction, not the buyer. The field that carries our visitor id through a purchase is StoreKit's appAccountToken. It must be a UUID; Roas.appAccountToken() derives one from the visitor id, and the server reverses it.

swift
var options: Set<Product.PurchaseOption> = []
if let token = Roas.appAccountToken() {          // nil before configure() -- never pass an empty token
    options.insert(.appAccountToken(token))
}
let result = try await product.purchase(options: options)

// Optional: report it now instead of waiting for Apple's notification.
if case .success(.verified(let transaction)) = result {
    Roas.verifyPurchase(transactionId: String(transaction.id))
    await transaction.finish()
}

verifyPurchase only ever names a transaction id; we fetch Apple's own signed copy of it and book what Apple says it was worth. It needs an In-App Purchase key on your account, and it dedupes against the notification that follows.

7. Identity and funnel events

swift
Roas.identify(email: user.email)                               // hashed on device
Roas.track(.beginCheckout, properties: [RoasProps.productId: "pro_yearly"])

Same event vocabulary as Android, same rule: productId must equal the App Store product id so the funnel and the sale line up, and nothing sent here is ever revenue.

Check it worked

  1. Run the app on a device once. Roas.setLogLevel(.debug) prints each delivery; a healthy launch shows first-open -> 201.
  2. On the app's Overview tab, an install row appears with your sdk_version and signed = true.
  3. Before submitting: a Release archive contains RoasSensor.bundle/PrivacyInfo.xcprivacy, and Xcode Organizer's Privacy Report lists it.