Skip to main content

Interstitial Placement

Interstitial Placement

Interstitial placements display a fullscreen ad that the user can dismiss. Unlike other placement types, an interstitial is loaded in the background and shown at a natural transition point in your app.

info

The direct interstitial integration requires no mediation SDK. If you are using Google Ad Manager or AdMob, see the GMA mediation guide instead.

Configuration

import TeadsSDK

let config = TeadsAdPlacementInterstitialConfig(
articleUrl: URL(string: "https://example.com/article")!,
widgetId: "INT_MW_1", // Your widget ID
installationKey: "NANOWDGT01", // Your installation key
floorPrice: 2 // Optional: minimum bid price in US dollars
)

Loading an Interstitial

Create the placement and load it ahead of the moment you want to show it:

import TeadsSDK

class InterstitialManager: NSObject {

private var placement: TeadsAdPlacementInterstitial?

func load() {
let config = TeadsAdPlacementInterstitialConfig(
articleUrl: URL(string: "https://example.com/article")!,
widgetId: "INT_MW_1",
installationKey: "NANOWDGT01"
)

placement = Teads.createPlacement(with: config, delegate: self)
placement?.loadAd()
}
}

The delegate must conform to TeadsFullScreenEventsDelegate (which extends TeadsAdPlacementEventsDelegate) to receive both ad and fullscreen lifecycle events. Passing a delegate that does not conform to TeadsFullScreenEventsDelegate will result in a warning and no events being delivered.

Presenting the Ad

Check isReady before calling show(from:):

func showAd(from viewController: UIViewController) {
guard let placement, placement.isReady else {
print("Ad not ready")
return
}
placement.show(from: viewController)
}

show(from:) accepts an optional UIViewController. If nil is passed, the SDK falls back to the application's top view controller automatically.

Handling Events

Implement TeadsFullScreenEventsDelegate to respond to ad and lifecycle events:

extension InterstitialManager: TeadsFullScreenEventsDelegate {

// Ad events (load result, viewability, clicks)
func adPlacement(
_ placement: TeadsAdPlacementIdentifiable?,
didEmitEvent event: TeadsAdPlacementEventName,
data: [String: Any]?
) {
switch event {
case .ready:
print("Ad loaded — ready to show")

case .failed:
let reason = data?["reason"] as? String ?? "Unknown"
print("Ad failed: \(reason)")
// reason is "Ad expired" when the cache TTL elapses before show()

case .rendered:
print("Ad appeared on screen")

case .viewed:
print("Viewability threshold reached")

case .clicked:
print("Ad clicked")
// The SDK opens the URL automatically — do not navigate manually

default:
break
}
}

// Fullscreen lifecycle events
func fullScreenPlacement(
_ placement: TeadsAdPlacementIdentifiable?,
didEmitEvent event: TeadsFullScreenEventName,
data: [String: Any]?
) {
switch event {
case .willPresent:
print("Ad about to present — pause audio, suspend timers")

case .presented:
print("Ad is now fullscreen")

case .willDismiss:
print("Ad about to dismiss")

case .dismissed:
print("Ad dismissed — resume app state")
placement?.invalidate()

@unknown default:
break
}
}
}

Ad Cache TTL

Once loaded, the ad must be shown within its cache TTL or it expires. The default TTL is 3600 seconds (1 hour), configurable server-side per widget. When the ad expires, .failed is emitted with reason: "Ad expired" and the placement is automatically cleaned up. Call loadAd() again to fetch a fresh ad.

Cleanup

Call invalidate() when you are done with a placement or want to discard a loaded ad before showing it:

// Discard without showing
placement?.invalidate()

// Or set to nil to let ARC clean up
placement = nil

invalidate() is safe to call multiple times. After invalidation the same placement instance can be reloaded via loadAd().