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. To receive Apple's postbacks, add both copy keys to Info.plist with the domain shown on the app's SKAdNetwork tab. Apple keeps only the domain and posts to its own /.well-known/ path on it:

xml
<key>NSAdvertisingAttributionReportEndpoint</key>
<string>https://roassensor.com</string>
<key>AdAttributionKit</key>
<dict>
    <key>AttributionCopyEndpoint</key>
    <string>https://roassensor.com</string>
</dict>

Report conversion values on key events with Roas.updateConversionValue(_:coarse:), and always send the coarse value: below Apple's privacy threshold it is the only one that survives. Within each of Apple's three windows (days 0–2, 3–7 and 8–35) a value only ever rises, so reporting engaged after purchase never erases the purchase. Pass allowDecrease: true only if your schema deliberately re-encodes. What each value means is set on the app's SKAdNetwork tab, and changing it re-reads every postback already received.

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. Website visitors (optional, 0.1.14+)

The App Store passes nothing from a tap on your website to the app it installs. So when an iPhone visitor taps your smart banner or one of your hosted "Download the app" links, the snippet copies that link, with a one-time code, to the clipboard. Read it back on first open and the install takes that exact tap's source: the banner, or the Google or Meta ad that brought the visitor to your website.

swift
// once, early in the first session, after Roas.configure(...)
Roas.claimPastedClick { result in
    if result.matched { print("came from", result.channel) }
}

It first checks, without any prompt, whether the clipboard holds a web link at all, and only reads it when it does. It asks at most once per install.

See Web to app for what the website side does.

8. 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 Testing tab, an install row appears with your SDK version and signed.
  3. Before submitting: a Release archive contains RoasSensor.bundle/PrivacyInfo.xcprivacy, and Xcode Organizer's Privacy Report lists it.