Skip to content

Swift / iOS SDK

Native ads, interstitial ads, and rewarded ads for iOS apps using SwiftUI.

New to Simula?

Head to Getting Started first to create your publisher account, get your API key, and set up your first ad unit. Then come back here to integrate the SDK.

Requirements

  • iOS 15.0+
  • Swift 5.9+
  • Xcode 15+

Installation

Add the Simula SDK via Swift Package Manager:

  1. In Xcode, go to File > Add Package Dependencies
  2. Enter the repository URL:
    https://github.com/Simula-AI-SDK/simula-ad-sdk-swift.git
  3. Set the version rule to Up to Next Major from 1.0.1
  4. Add SimulaAdSDK to your app target

Or add it directly to your Package.swift:

swift
dependencies: [
    .package(url: "https://github.com/Simula-AI-SDK/simula-ad-sdk-swift.git", from: "1.0.1"),
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "SimulaAdSDK", package: "simula-ad-sdk-swift"),
        ]
    ),
]

SPM and CocoaPods

The Swift SDK is distributed via Swift Package Manager and CocoaPods. Carthage is not supported.

Provider Setup (SwiftUI)

Wrap your app content with SimulaProviderView to initialize the SDK and supply configuration to all child views:

swift
import SimulaAdSDK

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            SimulaProviderView(
                apiKey: "YOUR_API_KEY",
                devMode: false,
                primaryUserID: "hashed_user_id"
            ) {
                ContentView()
            }
        }
    }
}

Child views access the provider via @EnvironmentObject:

swift
struct ContentView: View {
    @EnvironmentObject var simula: SimulaProvider

    var body: some View {
        // Your app content
    }
}

Provider Parameters

ParameterTypeDefaultDescription
apiKeyStringrequiredYour Simula API key
devModeBoolfalseEnables development mode — always fills, no billing, excluded from ML targeting, and enables debug console logging. Set to false before shipping
primaryUserIDString?nilHashed user ID for better ad targeting
privacySimulaPrivacyConfig?nilGranular consent configuration. See Privacy
telemetryEnabledBooltrueEnables SDK performance and error telemetry
adContextSimulaAdContext?nilContextual targeting signals attached to every native ad request

Imperative Initialization

For UIKit-based apps or early initialization in AppDelegate:

swift
import SimulaAdSDK

class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        SimulaAds.initialize(
            apiKey: "YOUR_API_KEY",
            devMode: false,
            primaryUserID: "hashed_user_id"
        )
        return true
    }
}

SimulaAds.initialize() is idempotent -- the first call with a valid key wins; subsequent calls are ignored.

Updating the User ID

Update the primary user identifier at runtime after login or logout:

swift
SimulaAds.updatePrimaryUserID("new_hashed_id") // after login
SimulaAds.updatePrimaryUserID(nil)              // after logout

Dev mode

Set devMode to true during development. Every ad request returns a test ad (always fills), no impressions are billed, test traffic is excluded from Simula's ML targeting models, and debug logs are printed to the console. Set to false before releasing to production.

Components

ComponentDescriptionGuide
NativeAdSlotInline native ad card for feedsNativeAdSlot
SimulaInterstitialAdFull-screen interstitial adInterstitialAd
SimulaRewardedAdRewarded ad with play-to-earn gateRewardedAd

Privacy & ATT

The SDK automatically reads IAB CMP consent values from UserDefaults and ATT authorization status from the system — no setup is required for most apps. This entire section is optional. Only configure privacy manually if you need to override the auto-read values or manage consent outside a CMP.

Explicit configuration takes precedence over auto-read values.

swift
// Full replacement
simula.updateConsent(SimulaPrivacyConfig(
    tcString: "...",
    gdprApplies: true,
    coppaApplies: false,
    enableAdvertisingId: true
))

// Partial merge
simula.updateConsent(
    tcString: "...",
    enableAdvertisingId: true
)

// Clear specific signals (fall back to auto-read IAB values)
simula.clearConsent(tcString: true, gppString: true)

App Tracking Transparency

To collect the IDFA for better ad targeting, prompt the user with ATT:

swift
let status = await simula.requestTrackingAuthorization()
// Returns: "authorized", "denied", "restricted", or "not_determined"

You must add NSUserTrackingUsageDescription to your Info.plist:

xml
<key>NSUserTrackingUsageDescription</key>
<string>This allows us to show you more relevant ads.</string>

SimulaPrivacyConfig

FieldTypeDefaultDescription
tcStringString?nilIAB TCF v2.2 consent string
uspStringString?nilIAB US Privacy (CCPA), e.g. "1YNN"
gppStringString?nilIAB Global Privacy Platform string
gppSidString?nilGPP section IDs, comma-separated
gdprAppliesBool?nilWhether GDPR applies (nil = unknown)
tcfPurpose1ConsentBool?nilExplicit TCF Purpose 1 (storage) consent
coppaAppliesBoolfalseChild-directed treatment (COPPA)
enableAdvertisingIdBoolfalseOpt-in for IDFA collection

Info.plist

KeyValueWhen Required
NSUserTrackingUsageDescriptionYour tracking explanationWhen enableAdvertisingId: true
SKAdNetworkItemsArray of SKAdNetwork identifiersFor privacy-preserving attribution (iOS 14+)

The SDK bundles a PrivacyInfo.xcprivacy manifest that is automatically aggregated by Xcode. No manual privacy manifest configuration is needed.

Ad Context

Pass contextual targeting signals via adContext to improve native ad relevance. The customContext field accepts arbitrary key-values — use it to send platform-specific data like recently interacted characters.

swift
SimulaProviderView(
    apiKey: "YOUR_API_KEY",
    primaryUserID: hashedUserId,
    adContext: SimulaAdContext(
        category: "ai-chat",
        customContext: [
            "recentCharacters": [
                ["id": "reze-01", "name": "Reze", "description": "The Bomb Devil from Chainsaw Man"],
                ["id": "power-02", "name": "Power", "description": "The Blood Fiend from Chainsaw Man"],
            ] as [[String: Any]],
            "preferredGenre": "anime",
        ]
    )
) {
    ContentView()
}

Update context at runtime when the user navigates to a new feed or chat:

swift
SimulaAds.updateContext(SimulaAdContext(
    category: "ai-chat",
    customContext: [
        "recentCharacters": [
            ["id": "reze-01", "name": "Reze", "description": "The Bomb Devil from Chainsaw Man"],
        ] as [[String: Any]],
    ]
))

// Clear context
SimulaAds.updateContext(nil)

Error Types

All ad load and display failures are reported as SimulaAdError:

ErrorDescription
.notInitializedSDK not initialized. Call SimulaAds.initialize() first
.noSessionSession creation failed
.noFillNo ad available for this placement
.notReadyshow() called before ad finished loading
.staleLoaded ad expired (1-hour limit). Call load() again
.duplicateRequest(retryInSeconds:)load() called while a request is already in flight
.alreadyShowingshow() called while an ad is already on screen
.noPresentationContextNo window scene available to present the ad
.unsupportedPlatformFeature not available on this platform (e.g. imperative ads on macOS)
.network(SimulaAPIError)Network connectivity error

AdValue

Revenue data surfaced on DidPay delegate methods and NativeAdSlot.onPaid. All figures are serve-time estimates derived from the backend floor CPM.

swift
public struct AdValue: Sendable, Equatable {
    public let valueMicros: Int64
    public let currencyCode: String
    public let precisionType: PrecisionType
    public let expectedCpm: Double
    public let expectedRevenue: Double
}
FieldTypeDescription
valueMicrosInt64Per-impression revenue in micros (5000 = $0.005)
currencyCodeStringISO-4217 currency code, e.g. "USD"
precisionTypePrecisionTypeEstimate quality — currently always .estimated
expectedCpmDoubleEstimated CPM (valueMicros / 1_000)
expectedRevenueDoubleEstimated per-impression revenue (valueMicros / 1_000_000)