Setting up Ads with the iOS Player

Bitmovin Player is capable of serving Ads out of the box. This guide will help you get started with configuring Ads for your integration.


  • Basic understanding of iOS development with Swift
  • Bitmovin Player iOS SDK added to your project (see Getting Started guide)
  • (optional) If you want to use IMA ( i.e.AdSourceType.ima) for ad handling, additional project setup is needed as shown here


The Bitmovin Player provides several ways of serving client side (linear) Ads. This guide will show you how to get started and configure your ad playback.

There are three types of Ad handling in the Bitmovin Player:

  • Bitmovin Advertising - Built-in VAST ad handling
  • IMA - Integration of the Google IMA SDK
  • Progressive - Built-in support for playing an asset as ad

All of them use the same API surface. Besides IMA, none of these require additional setup.

The central component of advertising is the AdItem. It represents a specific time slot within the streamed content dedicated to ads playback. An AdItem is configured with one or more AdSource and a position. The first adSource is used as the main ad. Subsequent adSources act as a fallback (waterfalling), meaning that if the main ad source does not provide a valid response the subsequent adSources will be utilized one after another.

AdSources describe the source of an ad, e.g. the VAST URL, and how it should be handled by the player i.e. the AdSourceType.

Whenever the position of an AdItem is reached, the player pauses the main content and starts ad playback. Ads that are part of one AdItem are accompanied by enclosing AdBreakStarted and AdBreakFinished events, to signal the transition. During ad playback most of the player API relates to the specific ad playback e.g. play/pause will pause the ad and currentTime returns the position within the ad.

Configuration on the general ad behaviour as well as type specific handling can be found in the AdvertisingConfig


Step 1: Create an AdSource

As previously mentioned, the AdSource represents the ad source and its handling type. It is the first thing that should be created:

// This snipped contains IMA Sample Tags from

guard let adUrl = URL(string: "") else {

// Example 1: Using Bitmovin Advertising
let adSource = AdSource(tag: adUrl, ofType: .bitmovin)
// Example 2: Using IMA
let adSource = AdSource(tag: adUrl, ofType: .ima)
// Example 3: Using Progressive
let adSource = AdSource(tag: adUrl, ofType: .progressive)

Step 2: Create an AdItem

An AdItem further associates AdSources, a position and potentially more configuration options:

// Example 1: Set up a pre-roll ad
let preRollAd = AdItem(adSources: [adSource], atPosition: "pre")

// Example 2: Set up a mid-roll ad with waterfalling at 10% of the content duration
let midRollAd = AdItem(adSources: [adSource, adSource2], atPosition: "10%")

// Example 3: Set up a post-roll ad
let postRollAd = AdItem(adSources: [adSource], atPosition: "post")

All possible values for AdItem positions can be found in the API reference, the default value is "pre".

The difference between pre-roll, mid-roll and post-roll ads is:

  • Pre-roll Ads: These are video ads that play before the main content starts. It's the first thing a viewer sees when they click to play a video. Because of their placement, pre-roll ads typically have higher view rates.
    • To prevent flashing the first frame of the main content before the pre-roll ad is played back we recommend setting hideFirstFrame to true (Use the respective UserInterfaceType depending on your UI).
  • Mid-roll Ads: These are video ads that play in the middle of the main content, much like traditional TV commercial breaks. The placement of mid-roll ads varies, but they're usually placed at a natural break point in the content to minimize disruption to the viewer.
  • Post-roll Ads: These are video ads that play after the main content has finished. While they don't interrupt the viewing experience, they often have lower view rates because viewers might leave the page or move on to another video once the main content ends.


Mixing different AdSourceType

It is not recommended to mix AdSources with different AdSourceType within an AdItem. If created and scheduled anyway, it might result in unexpected behaviour.

Step 3: Scheduling Ads

There are two fundamental ways to schedule ads in the Bitmovin Player. A static config per player, or dynamic scheduling at any time.

Static Scheduling

To define a static schedule, a AdvertisingConfig needs to be defined when creating a Player instance and is automatically applied to the first Source being played back after a load call. This means that it is not intended to be used with playlists, but may be useful when reusing the Player and playing different items using the load call. The schedule in the AdvertisingConfig is persisted across load calls.

// Add the AdItems to the AdvertisingConfig
let adConfig = AdvertisingConfig(schedule: [preRollAd, midRollAd, postRollAd])

// Create a new PlayerConfig containing the advertising config.
let playerConfig = PlayerConfig()
playerConfig.advertisingConfig = adConfig
let player = PlayerFactory.createPlayer(playerConfig: playerConfig)

Dynamic Scheduling

It is possible to dynamically schedule AdItems once a Source or playlist is loaded. Those dynamic ads are discarded completely after they have been played back, and do not persist across load calls to the player, but may be used within playlists.

// Dynamically schedule an AdItem
player.scheduleAd(adItem: midRollAd)

Additional functionality

Our API Reference offers detailed information on all configurations and other aspects of the API. Most of the additional features can be configured through the AdvertisingConfig along with ad type specific configurations BitmovinAdvertisingConfig and ImaAdvertisingConfig.

Nevertheless, below is a curated list of particularly useful features:


You can observe the lifecycle of ads using our rich Events API and subscribe to events such as AdBreakStarted, AdBreakFinished, AdStarted, AdClicked, AdScheduled or AdError .

You can find a full list of advertising related events here.
    .sink { adBreakStartedEvent in
        print("The Ad Break started")
    .store(in: &cancellables)

Skipping ads

Some ads can be skipped. When building custom UIs the Player.skipAd method can be used to skip the currently being played ad programmatically. However, this does not apply to IMA ads, as the IMA SDK itself provides the UI and does not allow for programmatic ad skipping.

Discarding ad breaks before they are loaded

Sometimes it might be needed to discard an AdItem before it is loaded. For this case AdvertisingConfig.shouldLoadAdItem is called before an AdItem is loaded and can be used to allow or discard it.



That's it!

Now you have a basic setup for ads using the Bitmovin iOS SDK  🥳

These instructions provide the basics, but the Bitmovin iOS SDK API reference provides more detailed information on how to customise the ad setup to fit your specific needs.