iOS SDK
Complete reference for the AppRefer iOS SDK. Native Swift, zero external dependencies, actor-based singleton.
Installation#
Xcode (recommended)#
- In Xcode, go to File → Add Package Dependencies...
- Enter the repository URL:
https://github.com/AppAgentic/apprefer-ios-sdk.git - Select Up to Next Major Version and click Add Package
Package.swift#
dependencies: [
.package(
url: "https://github.com/AppAgentic/apprefer-ios-sdk.git",
from: "1.0.0"
)
],
targets: [
.target(
name: "YourApp",
dependencies: [
.product(name: "AppRefer", package: "apprefer-ios-sdk")
]
)
]No extra setup needed
API Reference#
All methods use await, not try await
configure(), methods return silently with no effect.AppRefer.configure(apiKey:userId:debug:logLevel:)#
Initialize the SDK and resolve attribution. Call once at app launch. The SDK uses an actor-based singleton — calling configure() multiple times reuses the existing instance.
| Parameter | Type | Default | Description |
|---|---|---|---|
apiKey | String | required | Your SDK key (pk_live_... or pk_test_...) |
userId | String? | nil | Optional user ID to associate with attribution |
debug | Bool | false | Enable verbose logging to console |
logLevel | LogLevel | .none | Granular log level: .none, .error, .warn, .info, .debug |
| Details | |
|---|---|
| Returns | Attribution? — the resolved attribution, or nil for organic installs |
| Throws | Never |
let attribution = await AppRefer.configure(
apiKey: "pk_live_your_key_here"
)
if let attribution {
print("Network: \(attribution.network ?? "unknown")")
print("Match type: \(attribution.matchType ?? "organic")")
}AppRefer.trackEvent(_:properties:revenue:currency:)#
Send a custom event to AppRefer.
| Parameter | Type | Default | Description |
|---|---|---|---|
name | String | required | Event name (e.g., "signup", "tutorial_complete") |
properties | [String: Any]? | nil | Arbitrary key-value metadata |
revenue | Double? | nil | Revenue amount (e.g., 9.99) |
currency | String? | nil | ISO 4217 currency code (e.g., "USD") |
await AppRefer.trackEvent(
"tutorial_complete",
properties: ["level": 3, "time_spent": 42]
)
// With revenue
await AppRefer.trackEvent(
"purchase",
revenue: 9.99,
currency: "USD"
)AppRefer.setAdvancedMatching(email:phone:firstName:lastName:dateOfBirth:)#
Send hashed PII to improve ad network match rates. All values are SHA256-hashed on the device before being sent to the server.
| Parameter | Type | Default | Description |
|---|---|---|---|
email | String? | nil | User's email address |
phone | String? | nil | Phone number in E.164 format |
firstName | String? | nil | User's first name |
lastName | String? | nil | User's last name |
dateOfBirth | String? | nil | Date of birth (YYYYMMDD) |
await AppRefer.setAdvancedMatching(
email: "user@example.com",
phone: "+15551234567",
firstName: "Jane",
lastName: "Doe"
)AppRefer.setUserId(_:)#
Associate a user ID with the device's attribution. Typically called with the RevenueCat app user ID.
| Details | |
|---|---|
| Signature | static func setUserId(_ userId: String) async |
| Returns | Void |
let customerInfo = try await Purchases.shared.customerInfo()
await AppRefer.setUserId(customerInfo.originalAppUserId)appreferId must be set on RevenueCat FIRST
appreferId subscriber attribute on RevenueCat. This is how AppRefer links RevenueCat webhook events back to the attributed device. Without it, purchase events from RevenueCat cannot be matched to attributions and will not be forwarded to ad networks.// REQUIRED: Set appreferId on RevenueCat immediately after configure()
let attribution = await AppRefer.configure(apiKey: "pk_live_...")
// Link AppRefer device ID to RevenueCat subscriber
if let deviceId = await AppRefer.getDeviceId() {
Purchases.shared.attribution.setAttributes(["appreferId": deviceId])
}AppRefer.getAttribution()#
Returns the cached attribution from the last configure() call. Returns nil if configure() has not been called yet or the device is organic.
| Details | |
|---|---|
| Signature | static func getAttribution() async -> Attribution? |
| Returns | Attribution? — cached attribution result |
AppRefer.getDeviceId()#
Returns the device ID generated by AppRefer. This is a stable UUID stored in the Keychain, persisted across app reinstalls.
| Details | |
|---|---|
| Signature | static func getDeviceId() async -> String? |
| Returns | String? — the device UUID, or nil before configure() |
Keychain persistence
Attribution Model#
The Attribution struct returned by configure() contains the following properties:
| Property | Type | Description |
|---|---|---|
network | String? | Ad network name (e.g., "meta", "google", "tiktok", "apple_search_ads") |
matchType | String? | Confidence level of the attribution match |
campaignName | String? | Campaign name from the tracking link |
adsetName | String? | Ad set / ad group name |
adName | String? | Ad creative name |
fbclid | String? | Facebook click ID |
gclid | String? | Google click ID |
ttclid | String? | TikTok click ID |
clickId | String? | Generic click ID (AppRefer internal) |
deviceId | String? | Device UUID assigned by AppRefer |
createdAt | String? | ISO 8601 timestamp of the attribution |
Full Integration Example#
This example shows a complete integration in a SwiftUI app with RevenueCat:
import SwiftUI
import AppRefer
import RevenueCat
@main
struct MyApp: App {
init() {
// Configure RevenueCat
Purchases.configure(withAPIKey: "your_revenuecat_api_key")
Task {
// 1. Initialize AppRefer and resolve attribution
let attribution = await AppRefer.configure(
apiKey: "pk_live_your_key_here"
)
if let attribution {
print("Attributed to \(attribution.network ?? "organic")")
}
// 2. CRITICAL: Link AppRefer device ID to RevenueCat
// Without this, purchases CANNOT be attributed to ad campaigns
if let deviceId = await AppRefer.getDeviceId() {
Purchases.shared.attribution.setAttributes([
"appreferId": deviceId
])
}
// 3. Link RevenueCat user ID back to AppRefer
if let customerInfo = try? await Purchases.shared.customerInfo() {
await AppRefer.setUserId(customerInfo.originalAppUserId)
}
}
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
// Later, after user signs up...
func onUserSignup(email: String, firstName: String) async {
// 4. Send advanced matching data (hashed on-device)
await AppRefer.setAdvancedMatching(
email: email,
firstName: firstName
)
// 5. Track the signup event
await AppRefer.trackEvent("signup")
}Best Practices#
- Call
configure()in your app'sinit()orapplication(_:didFinishLaunchingWithOptions:). The sooner you call it, the more accurate the attribution window. - Always set
appreferIdon RevenueCat immediately afterconfigure(). This is the most important step for purchase attribution. Without it, RevenueCat webhook events cannot be linked to ad campaigns. - Use
awaitwithouttry. The SDK never throws. Usingtry awaitwill compile but thetryis unnecessary. - Always call
setUserId()with the RevenueCat user ID if you use RevenueCat. This is how purchase webhooks are matched back to attributions. - The device ID is stored in the Keychain, so it persists across app reinstalls. This means attribution survives reinstalls.
- Use
pk_test_keys during development. Sandbox events are completely isolated from production and never forwarded to ad networks.
Requirements#
| Requirement | Minimum Version |
|---|---|
| iOS | 14+ |
| Swift | 5.9+ |
| Xcode | 15+ |
| Dependencies | None (zero external dependencies) |