Pause Ads
The Bitmovin Player iOS SDK can show pause ads: static image ads that appear on top of the paused content and go away when playback resumes. The SDK resolves the VAST tag, renders the creative and fires the VAST tracking. Your app schedules the ad.
Pause ad support is experimental, and the API may change in a future version. In Swift, opt in with @_spi(ExperimentalApi) import BitmovinPlayerCore. Pause ads are available on iOS and tvOS, not on visionOS.
Scheduling a pause ad
Create an AdItem with the .pause trigger and a Bitmovin ad source. Schedule it upfront through AdvertisingConfig:
@_spi(ExperimentalApi) import BitmovinPlayerCore
let pauseAd = AdItem(
adSources: [AdSource(tag: pauseAdTagUrl, ofType: .bitmovin)],
trigger: .pause
)
let playerConfig = PlayerConfig()
playerConfig.advertisingConfig = AdvertisingConfig(schedule: [pauseAd])Or at runtime, for example when your app decides which pause ad fits the current content:
player.ads.schedule(adItem: pauseAd)In Objective-C, create the item with [BMPAdItem pauseAdWithAdSources:].
The VAST response must contain a NonLinear creative with a PNG or JPEG StaticResource. Other ad source types and resource types are not supported.
Suppressing a pause ad
AdvertisingConfig.shouldLoadAdItem is called before the tag is requested, and shouldPlayAdItem before the creative is shown. Returning false from either one removes that pause ad from the schedule, and the next scheduled pause ad is tried. To show it later, schedule it again.
advertisingConfig.shouldLoadAdItem = { adItem in
adItem.trigger != .pause || shouldShowPauseAds()
}shouldPlaySeekedOverAdItems is not called for pause ads.
When a pause ad is shown
- A pause ad becomes eligible one second after content playback pauses
- Pausing before playback has started never shows a pause ad
- Seeking or time shifting restarts the delay, and dismisses a visible pause ad
- At most one pause ad is shown per pause. Others wait for a later pause, in scheduling order
- Each scheduled pause ad is shown once, then removed
- The tag is requested only when a pause becomes eligible, and nothing is cached
- Pending pause ads are cleared when the active source changes, including the ones from
AdvertisingConfig
Pause ads are not shown, and stay scheduled for a later pause, in these cases:
| Condition | A pause ad that is already visible |
|---|---|
| A linear ad starts | Ends |
| Casting or AirPlay starts | Ends |
Picture-in-Picture managed by PlayerView starts | Ends |
| The System Player UI enters AVKit fullscreen | Ends |
| The app becomes inactive | Stays |
| The ad container is not on screen | Stays |
If your app manages Picture-in-Picture itself, it must prevent pause ads during it.
Ad container and controls
PlayerView provides a default ad container above the video and below the player UI. To place the ad somewhere else, for example next to the video, register your own container with player.ads.register(adContainer:) after setting up the PlayerView. Register it again if you recreate or reattach the PlayerView. The SDK only adds and removes its own overlay; the container's layout and visibility are up to your app.
The Bitmovin Player UI and the System Player UI provide resume and close controls. With a custom UI, make sure a resume control is always reachable, and call player.ads.skip() from your close control. Closing removes the ad and keeps the content paused.
On iOS, tapping a creative that has a VAST click-through URL opens the URL. tvOS has no click-through.
Events
NonLinearAdStartedEvent: the pause ad is visibleNonLinearAdSkippedEvent: the pause ad was closed, through the UI orplayer.ads.skip()NonLinearAdFinishedEvent: the pause ad ended in any other way, for example because playback resumedAdClickedEvent: the creative was tappedAdErrorEvent: the pause ad could not be loaded or shown
Every NonLinearAdStartedEvent is followed by exactly one NonLinearAdSkippedEvent or NonLinearAdFinishedEvent.
A pause ad is not an ad break. Existing linear ad APIs ignore it, so current integrations keep working: player.isAd stays false, player.ads.activeAd does not return it, it is not in the ad schedule, and no ad break or linear ad events are emitted.
Tracking
The SDK fires the VAST impression, creativeView, click, close, overlayViewDuration, notUsed and error tracking, including Wrapper tracking. Resuming playback ends the ad without firing close; only closing it does. See Pause Ads for the full tracking table.
Troubleshooting
If a pause ad fails to load or be shown, AdErrorEvent is emitted and that ad item is removed. If another pause ad is scheduled, it is tried during the same pause.
If the ad container is registered but not on screen when the ad is about to be shown, for example because it is hidden, transparent or not in a window, the loaded creative is discarded and reported as notUsed, and no error is emitted. The pause ad stays scheduled, and its tag is requested again on the next pause. If no container is registered or it has a zero size, the ad fails like any other error.
If no pause ad appears at all, check that the Swift file imports the SPI, the ad source type is .bitmovin, the VAST response has a PNG or JPEG static resource, content was playing before the pause, and the ad container is on screen.
Creatives are downloaded through the player's networking, so network configuration hooks apply.
Limitations
- Only Bitmovin ad sources and static PNG or JPEG creatives are supported. IMA, HTML, SIMID and VPAID creatives are not
- Only the first ad of a VAST ad pod is used. A failed creative does not fall back to another creative in the same VAST response
- The activation delay cannot be configured
- Preloading is not supported
- The SDK renders the creative. You can move it with a custom container, but not draw it yourself
- Not supported on visionOS. Pause ads scheduled there are ignored
- App activity is app-wide. In apps with multiple scenes, a pause ad can be shown for a player whose scene is in the background while another scene is active
Updated about 1 hour ago