iOS
Install the SignalSeal iOS SDK in your Swift or Objective-C app.
The SignalSeal iOS SDK reports installs, sends events, and powers in-app attribution.
Requirements
- iOS 15.0 or higher
- Swift 5.9 or higher
- Xcode 14 or higher
Install
Swift Package Manager
Add the SDK to your Package.swift:
.package(url: "https://github.com/signalseal/ios-signalseal-sdk", from: "0.2.5")Then add SignalSealSDK to your target:
.target(
name: "MyApp",
dependencies: [
.product(name: "SignalSealSDK", package: "ios-signalseal-sdk"),
]
)Or in Xcode: File → Add Package Dependencies, paste
https://github.com/signalseal/ios-signalseal-sdk, and add the
SignalSealSDK library to your target.
Initialize
Call configure(...) once on app launch - typically in your
AppDelegate, SceneDelegate, or a SwiftUI @main initializer.
import SignalSealSDK
SignalSealSDK.shared.configure(
apiKey: "ak_ios_..."
)Configuration parameters
public func configure(
apiKey: String,
isDebug: Bool = false,
endpointBaseUrl: String? = nil,
logLevel: LogLevel = .info,
customerUserId: String? = nil,
environment: SignalSealEnvironment? = nil
)| Parameter | Type | Description |
|---|---|---|
apiKey | String | Required. Your iOS SDK key (ak_ios_…) from Settings → SDK. |
isDebug | Bool | Defaults to false. When true, every event is tagged is_debug so it's visible in the Live Feed but not forwarded to ad networks. |
endpointBaseUrl | String? | Override the ingestion URL. Leave unset unless SignalSeal told you to set it. Must end with /. |
logLevel | LogLevel | Defaults to .info. One of .off, .error, .warn, .info, .debug. isDebug: true forces .debug. |
customerUserId | String? | Your app's stable user ID, if you have one. Helpful for cross-device identity. |
environment | SignalSealEnvironment? | Auto-detected (Simulator/TestFlight/debugger → .sandbox, App Store → .production). Pass .sandbox explicitly for ad-hoc or Enterprise QA builds. |
configure(...) is safe to call from any thread and is idempotent -
the second call is logged and ignored.
The SDK fires the INSTALL event automatically the first time
configure(...) runs on a device. Don't send it manually.
Send events
SignalSealSDK.shared.sendEvent(
event: .purchase,
parameters: [
"value": 9.99,
"proceeds": 6.99,
"currency": "USD"
]
)value is the gross amount in the buyer's currency. proceeds is optional -
the net you keep after store commission and tax, in the same currency; pass it
if you know it (e.g. from your receipt-validation backend). currency is the
ISO-4217 code; omit it and value is treated as USD.
The first argument is an EventType - see the full list below. For
events that don't fit any of those, use .custom with a name:
SignalSealSDK.shared.sendEvent(
event: .custom,
name: "onboarding_completed",
parameters: ["steps": 5]
)sendEvent(...) is fire-and-forget. Events queue in memory and flush
in the background.
Event types
public enum EventType: String {
case install = "INSTALL"
case login = "LOGIN"
case signUp = "SIGN_UP"
case register = "REGISTER"
case purchase = "PURCHASE"
case addToCart = "ADD_TO_CART"
case addToWishlist = "ADD_TO_WISHLIST"
case initiateCheckout = "INITIATE_CHECKOUT"
case startTrial = "START_TRIAL"
case subscribe = "SUBSCRIBE"
case levelStart = "LEVEL_START"
case levelComplete = "LEVEL_COMPLETE"
case tutorialComplete = "TUTORIAL_COMPLETE"
case search = "SEARCH"
case viewItem = "VIEW_ITEM"
case viewContent = "VIEW_CONTENT"
case share = "SHARE"
case custom = "CUSTOM"
}Set user attributes
Attach known user data to all subsequent events. Pass only the fields you have - everything is optional.
SignalSealSDK.shared.setUserAttributes(
UserAttributes(
email: "alice@example.com",
firstName: "Alice",
country: "US",
externalId: "user_42"
)
)Available fields:
| Field | Type | Notes |
|---|---|---|
email | String? | |
phone | String? | E.164 format recommended (+14155551234). |
firstName, lastName | String? | |
dob | String? | ISO-8601 (YYYY-MM-DD). |
gender | String? | |
city, state, zip, country | String? | country should be ISO-3166-1 alpha-2. |
externalId | String? | Your app's internal user ID after login. |
Apple Search Ads
To attribute installs from Apple Search Ads, enable ASA tracking after
configure(...):
import SignalSealSDK
SignalSealASAAttribution.shared.enableAppleAdsAttribution()This is a separate call so apps that don't run Apple Search Ads aren't forced to ship the integration.
Automatic purchase tracking
If you're on StoreKit 2 and you want SignalSeal to capture purchases
automatically without you calling sendEvent for each one, enable
purchase tracking after configure(...):
SignalSealSDK.shared.enablePurchaseTracking()The SDK listens to StoreKit.Transaction.updates and emits a
PURCHASE event for each verified transaction. Skip this if you
already log purchases yourself or you process them server-side
through RevenueCat or SuperWall.
Helpers
Get the SignalSeal ID
A stable per-install ID, useful for bridging to RevenueCat, SuperWall, or your own backend.
let id = SignalSealSDK.shared.getSignalSealId()Returns nil until configure(...) has finished setting up.
Get attribution parameters
Returns the install's attribution data - the campaign that drove it, plus raw click IDs for any further server-side correlation.
Task {
if let params = await SignalSealSDK.shared.getAttributionParams() {
// { "signalseal_id": "...", "signalseal_adnetwork": "meta",
// "signalseal_campaign_id": "...", "fbclid": "...", ... }
}
}Organic installs return { "signalseal_id": "..." } only. Attributed
installs add signalseal_* keys plus any raw click IDs the original
ad carried (gclid, fbclid, ttclid, wbraid, etc.).
Flush
Force-flush the in-memory event queue. Useful in tests.
SignalSealSDK.shared.flush()Reset
Wipe all locally-stored SDK state - installation ID, queued events,
cached user data. Use this for "log out" or "forget me" flows. The
SDK re-mints an installation ID and re-fires the INSTALL event on
the next call.
SignalSealSDK.shared.resetData()Debug mode
Pass isDebug: true when configuring during development:
#if DEBUG
SignalSealSDK.shared.configure(
apiKey: "ak_ios_...",
isDebug: true
)
#else
SignalSealSDK.shared.configure(
apiKey: "ak_ios_..."
)
#endifIn debug mode every event is tagged is_debug - events still appear
in the SignalSeal dashboard so you can verify they look right, but
they won't be forwarded to your ad networks.