@MainActor. Times are seconds; prices are CPM.
KontextVideo
The entry point, one instance: KontextVideo.shared.
method
Starts the SDK: stores the configuration and calls the server in the background. Call it once, at app launch; later calls are ignored.
completion runs on the main thread once the server answered or failed.async method
The same for
async code; returns the resulting State: .enabled, .disabled(reason:) (the server switched the SDK off for this launch) or .failed (the server could not be reached; every ads request retries first).User?
What you know about the viewer. Set it whenever you learn it; the next ads request carries it.
Regulatory?
Privacy and consent signals. The SDK reads TCF values from your consent platform’s shared storage; set here what it did not write (COPPA always comes from you).
String?
Selects which type of ad to render, for A/B tests agreed with Kontext.
String
The SDK’s version, as sent with every request. For your logs and crash reports.
KontextVideo.Configuration
String
required
Identifies the publisher. Not a secret. You get a
{publisher}-dev token for testing and a production one.Bool
Whether the SDK shows the App Tracking Transparency dialog itself, before its first ads request. Defaults to
false: the app decides when the dialog appears.LogLevel
How much the SDK prints to the console:
.none, .error, .warning (default), .info, .debug.KontextVideo.Content
The video the ads are for. Everything beyond id and language is contextual signal.
String
required
Your own id of the video, any scheme.
String
required
BCP-47, for example
"en" or "pt-BR".Rating?
.safe or .explicit. Leave unset when you don’t know; explicit content gets no ads that require safe content.URL?
The episode’s public page.
String?
[String]?
IAB Content Taxonomy 3.0 ids.
String?
TimeInterval?
Seconds.
Int?
[String]?
String?
For example
"romance".Series?
KontextVideo.User
String?
Your own unique identifier of the viewer.
String?
Plain email address, when consent allows it. The server hashes it on arrival and never stores the plain address.
String?
SHA-256 of the normalized address (trimmed, lowercased, UTF-8), 64 lowercase hex characters.
[String]?
The viewer’s interests, in your own words.
KontextVideo.Regulatory
Bool?
Whether the request is subject to GDPR.
String?
IAB TCF v2 consent string.
Bool?
Whether the request is subject to COPPA. Cannot be read from the device.
String?
IAB Global Privacy Platform string.
[Int]?
GPP section ids that apply.
String?
Legacy IAB US Privacy (CCPA) string.
AdFormat
.overlay, .pause, .linear.
VideoAds
The ads of one video. Create one per episode; creating it sends nothing. Any number can be alive at once.
initializer
async throwing method
The ad for one format: the same
VideoAd as last time while it is unshown and valid, a new one otherwise. A failed request returns the held ad when it is still valid.Throws noFill(reason:), request(_:), destroyed, disabled(reason:), notInitialized, initializationFailed, or CancellationError when your task is cancelled (the request itself continues).method
Reads the content playhead from this
AVPlayer whenever the SDK needs one. Held weakly; no observer is attached. Call it when this episode starts playing in the player.(() -> TimeInterval)?
Where the SDK reads the content playhead, in seconds, for any player.
trackPlayhead(of:) sets it for you. Nothing set: 0, what a prefetch should send.method
Releases the video’s ads. Every held ad is dropped and the advertiser told it was not used; the ad on screen ends with
didEnd(.destroyed); a format() or load() in flight throws destroyed. Idempotent. Releasing the object does the same, best effort.Content
What it was created with.
Bool
true after destroy().VideoAd
One ad, from the server’s answer to the end of its presentation. Look at its facts, then load() or reject(), then show(), then exactly one didEnd. Shown at most once.
Facts
String
AdFormat
Price
TimeInterval?
Overlay: how long the SDK keeps it on screen,
nil when it stays until ended. Linear: the video’s length. Always nil for a pause ad.State
Bool
load() finished.Bool
Loaded, not shown, not rejected, not expired:
show() can be tried. A hint, not a guarantee; show() still measures the view.InvalidationReason?
Why the ad ended before it was shown, once it did:
.expired, .rejected, .destroyed, .creativeFailed(code:).Bool
true from a successful show() on.Bool
true once the ad began to end. didEnd follows at once for an overlay or pause ad, and once the dismissal finished for a linear ad.Bool
Whether the creative ran to its end: a video reached complete, an overlay’s duration elapsed. Separate from how it left the screen.
VideoAdDelegate?
Receives the ad’s moments. Held weakly.
Methods
async throwing method
Renders the creative off screen and returns once the page reports it ready, so
show() is instant. Throws creativeFailed(code:), invalidated(_:), destroyed, disabled(reason:).throwing method
You won’t use the ad; the server tells the advertiser.
.notUsed (default) or .outbid(winningPrice:winner:). Works until show(), loaded or not. Throws alreadyShown after it, or the invalidation if the ad already ended.throwing method
Shows an overlay or pause ad inside
view, the one the content plays in. Succeeds once the ad is on screen. Throws, with nothing shown: notLoaded, alreadyShown, anotherAdShowing, invalidated(_:), destroyed, disabled(reason:), presenterUnavailable (the view is not on screen) and containerTooSmall(minimum:) (the ad stays ready in both), wrongPresentation (a linear ad).throwing method
Presents a linear ad full screen: from the given view controller, or with
nil (the default) from the key window’s top view controller. Throws, with nothing shown: the errors above plus presenterUnavailable (the ad stays ready), wrongPresentation (an overlay or pause ad).throwing method
Ends an overlay or pause ad because you say so;
didEnd(.dismissed) follows, synchronously. Before show() and after didEnd it does nothing. Throws wrongPresentation for a linear ad, which only the SDK dismisses.VideoAdDelegate
Delivered on the main actor. Every method has an empty default; implement the ones you need. Nothing is delivered before show().
method
The impression was counted: at
show() for an image, at the first frame for a video. At most once; may not come at all.method
The viewer tapped the ad; the SDK opened
click.url, or for an app-install ad the App Store product sheet inside your app. click.area is .creative, .endCard or .other(String). Once per tap.method
The creative failed or stalled after presentation began.
didEnd(.failed) follows right away.method
Presentation is over. Exactly once per successful
show(), always last. Resume your content here, whatever the reason.