SDKsiOS

Use Cases

Patterns for displaying Koah ads on iOS.

Prefetching for feeds

Feed-style hosts often need to know whether an ad will fill before committing layout — see prefetch for the shared model. Koah.shared.requestAd returns a one-shot KoahAdResult you can drive layout from:

struct FeedRow: View {
    let item: FeedItem
    @State private var result: KoahAdResult?

    var body: some View {
        Group {
            if case .filled = result {
                KoahCard(
                    adContext: .feed(text: item.text, source: item.source),
                    cacheKey: item.id
                )
            } else if result == nil {
                ReservedSlot()                          // loading
            }
            // .noFill / .error: collapse (EmptyView)
        }
        .task(id: item.id) {
            result = await Koah.shared.requestAd(
                adContext: .feed(text: item.text, source: item.source),
                cacheKey: item.id
            )
        }
    }
}

If you don't need explicit reserve/collapse layout — just "show an ad if one's available, otherwise nothing" — skip the requestAd step entirely and call prefetchAd on first appear to warm the cache. KoahCard will render nothing on no-fill:

.task(id: item.id) {
    Koah.shared.prefetchAd(
        adContext: .feed(text: item.text, source: item.source),
        cacheKey: item.id
    )
}
APIUse
Koah.shared.requestAd(adContext:dimensions:cacheKey:)Ask for an ad and wait for the answer. Use this when your layout depends on whether an ad fills — reserve height while it resolves, then either render the card or collapse the slot. Suspends, then returns a KoahAdResult: .filled(fromCache:), .noFill(fromCache:), or .error(message:fromCache:).
Koah.shared.prefetchAd(adContext:dimensions:cacheKey:)Warm the cache for a slot the user is about to see. Returns immediately with a Task<Void, Never>; the network call runs in the background. No impression fires until the ad is actually rendered. Concurrent calls for the same cacheKey share one in-flight fetch.
Koah.shared.cancelPrefetchAd(cacheKey:)Cancel an in-flight prefetch. Cached results are untouched.
KoahCard(adContext:cacheKey:)Render. Reads from the warmed cache on hit; renders nothing on no-fill.

Impressions fire only once the rendered ad is actually displayed on screen, never during prefetch — see impressions.

Slots

Tag an ad request with a slot to break down your dashboard reporting by where the ad renders — a feed card, an in-article unit, a chat sidebar. Register your slots in the dashboard first, then pass a registered name as slot on requestAd or prefetchAd:

let result = await Koah.shared.requestAd(
    adContext: .feed(text: item.text, source: item.source),
    cacheKey: item.id,
    slot: "in-article"
)
Was this helpful?