Pause Ads on iOS

Show an ad when the viewer pauses on iOS by triggering an Exposed Ad from your player's pause handler, with a delay to filter accidental pauses.

A pause ad is an ad shown when the viewer pauses playback. On iOS you build one with the Exposed Ads API: detect the pause in your player, then call StreamLayer.showAd(_:) (or showVASTAd(_:vastURL:)) to display the ad unit of your choice.

iOS has no automatic paused-ad delivery. Selecting a StreamLayer-delivered paused-ad source (Studio or Prebid via setPausedAdDelivery) and the ad-break trigger are tvOS-only — see Paused Ads (tvOS). On iOS, your app owns the pause trigger and the ad content, using exposed ads.

This page covers the pause-trigger recipe. For the full catalog of ad units, VAST shapes, configuration types, and Prebid, see Exposed Ads (iOS).

Prerequisites

  1. Complete the iOS Integration Guide.
  2. Create an event session and the StreamLayer Element (the overlay wires the ad display delegate):
StreamLayer.createSession(for: "your-event-id")

let overlayViewController = StreamLayer.createOverlay(
    mainContainerViewController: self,
    overlayDelegate: self,
    overlayDataSource: self
)

Full-screen and transparent ad units are iPad-only on iOS. Promotion units (sidebar, PIP, side-by-side, sponsor frame, overlay) work on iPhone and iPad.

Show an ad on pause

Add a delay so brief or accidental pauses don't trigger an ad — a 3–5 second delay is common. Use a DispatchWorkItem you can cancel if playback resumes first, and dismiss any shown ad with hideAd().

import StreamLayerSDK

private var pauseAdWorkItem: DispatchWorkItem?

func handlePlayingState() {
    pauseAdWorkItem?.cancel()
    pauseAdWorkItem = nil
    StreamLayer.hideAd()
}

func handlePausedState() {
    let workItem = DispatchWorkItem { [weak self] in
        self?.presentPauseAd()
    }
    DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: workItem)
    pauseAdWorkItem = workItem
}

private func presentPauseAd() {
    // Show any exposed ad unit — here, a VAST tag rendered in a sidebar
    StreamLayer.showVASTAd(.sidebar(), vastURL: URL(string: "https://example.com/vast.xml")!)
}

Pick whichever ad unit fits your inventory. For example, a transparent VAST overlay on iPad:

private func presentPauseAd() {
    StreamLayer.showAd(.transparentBackgroundVAST(
        vastTagURL: URL(string: "https://example.com/vast.xml")!,
        resumeButton: .hidden
    ))
}

Resume on dismiss

When the viewer dismisses the ad, the SDK calls streamLayerDelegateAdDidFinish() on your SLROverlayDelegate. Resume playback and cancel any pending pause-ad work there. The optional streamLayerDelegateAdDidStart() fires when the ad begins presenting.

extension YourViewController: SLROverlayDelegate {
    // Optional — a StreamLayer ad began presenting
    func streamLayerDelegateAdDidStart() {}

    func streamLayerDelegateAdDidFinish() {
        player.play()
        pauseAdWorkItem?.cancel()
        pauseAdWorkItem = nil
    }
}

Prefetch for instant display

To show the ad the instant the delay elapses, prefetch it at session start (iPad-only):

StreamLayer.prefetchVASTAd(vastURL: URL(string: "https://example.com/vast.xml")!) { _ in }

See Exposed Ads (iOS) — Prefetching and lifecycle for details.


Related