Page Summary
-
IMA SDKs enable easy integration of multimedia ads into websites and apps, supporting VAST-compliant ad servers and managing ad playback while you control content video.
-
Implementing IMA client-side primarily involves four SDK components: IMAAdDisplayContainer, IMAAdsLoader, IMAAdsRequest, and IMAAdsManager.
-
Prerequisites for integrating the IMA SDK include Xcode 13 or later and a dependency manager like CocoaPods, Swift Package Manager, or a manual download of the SDK.
-
The integration process involves creating a simple video player, importing the IMA SDK, implementing content playhead tracking, initializing the ads loader, making an ads request, and setting up delegates for both the ads loader and ads manager.
IMA SDKs make it easy to integrate multimedia ads into your websites and apps. IMA SDKs can request ads from any VAST-compliant ad server and manage ad playback in your apps. With IMA client-side SDKs, you maintain control of content video playback, while the SDK handles ad playback. Ads play in a separate video player positioned on top of the app's content video player.
This guide demonstrates how to integrate IMA SDK into a video player app. If you would like to view or follow along with a completed sample integration, download the BasicExample from GitHub.
IMA client-side overview
Implementing IMA client-side involves four main SDK components, which are demonstrated in this guide:
-
IMAAdDisplayContainer: A container object that specifies where IMA renders ad UI elements and measures viewability, including Active View and Open Measurement . -
IMAAdsLoader: An object that requests ads and handles events from ads request responses. You should only instantiate one ads loader, which can be reused throughout the life of the application. -
IMAAdsRequest: An object that defines an ads request. Ads requests specify the URL for the VAST ad tag, as well as additional parameters, such as ad dimensions. -
IMAAdsManager: An object that contains the response to the ads request, controls ad playback, and listens for ad events fired by the SDK.
Prerequisites
Before you begin, you need the following:
- Xcode 13 or later
- Swift Package Manager, CocoaPods , or a downloaded copy of IMA SDK for tvOS
1. Create a new Xcode project
In Xcode, create a new tvOS project using Objective-C or Swift. Use BasicExampleas the project name.
2. Add IMA SDK to the Xcode project
Install IMA SDK using Swift Package Manager
Interactive Media Ads SDK supports Swift Package Manager starting in version 4.8.2. Follow the following steps to import the Swift package.
-
In Xcode, install IMA SDK Swift Package by navigating to File > Add Packages....
-
In the prompt that appears, search for IMA SDK Swift Package GitHub repository:
https://github.com/googleads/swift-package-manager-google-interactive-media-ads-tvos -
Select the version of IMA SDK Swift Package you want to use. For new projects, we recommend using the Up to Next Major Version.
Once you're finished, Xcode resolves your package dependencies and downloads them in the background. For more details on how to add package dependencies, see Apple's article .
Install IMA SDK using CocoaPods
To install IMA SDK, use CocoaPods. For more information on installing or using CocoaPods, see CocoaPods documentation . After you install CocoaPods, do the following:
-
In the same directory as your BasicExample.xcodeprojfile, create a text file called Podfile, and add the following configuration:
source 'https://github.com/CocoaPods/Specs.git' platform :tvos , '15' target "BasicExample" do pod 'GoogleAds-IMA-tvOS-SDK' , '~> 4.16.0' end -
From the directory that contains the Podfile, run
pod install --repo-update -
Verify that the installation was successful by opening the BasicExample.xcworkspacefile and confirming that it contains two projects: BasicExampleand Pods(the dependencies installed by CocoaPods).
Manually downloading and installing IMA SDK
If you don't want to use CocoaPods, you can download IMA SDK and manually add it to your project.
3. Import IMA SDK
Add IMA framework using an import statement.
Objective-C
#import "ViewController.h"
#import <AVKit/AVKit.h>
@import
GoogleInteractiveMediaAds
;
Swift
import
AVFoundation
import
GoogleInteractiveMediaAds
import
UIKit
4. Create a video player and integrate IMA SDK
The following example initializes IMA SDK:
Objective-C
NSString
*
const
kContentURLString
=
@"https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"
;
NSString
*
const
kAdTagURLString
=
@"https://pubads.g.doubleclick.net/gampad/ads?"
@"iu=/21775744923/external/vmap_ad_samples&sz=640x480&"
@"cust_params=sample_ar%3Dpremidpostlongpod&ciu_szs=300x250&gdfp_req=1&ad_rule=1&"
@"output=vmap&unviewed_position_start=1&env=vp&cmsid=496&vid=short_onecue&correlator="
;
@interface
ViewController
()
< IMAAdsLoaderDelegate
,
IMAAdsManagerDelegate
> @property
(
nonatomic
)
IMAAdsLoader
*
adsLoader
;
@property
(
nonatomic
)
IMAAdDisplayContainer
*
adDisplayContainer
;
@property
(
nonatomic
)
IMAAdsManager
*
adsManager
;
@property
(
nonatomic
)
IMAAVPlayerContentPlayhead
*
contentPlayhead
;
@property
(
nonatomic
)
AVPlayerViewController
*
contentPlayerViewController
;
@property
(
nonatomic
,
getter
=
isAdBreakActive
)
BOOL
adBreakActive
;
@end
@implementation
ViewController
-
(
void
)
viewDidLoad
{
[
super
viewDidLoad
];
self
.
view
.
backgroundColor
=
[
UIColor
blackColor
];
[
self
setupAdsLoader
];
[
self
setupContentPlayer
];
}
-
(
void
)
viewDidAppear:
(
BOOL
)
animated
{
[
super
viewDidAppear
:
animated
];
[
self
requestAds
];
}
// Add the content video player as a child view controller.
-
(
void
)
showContentPlayer
{
[
self
addChildViewController
:
self
.
contentPlayerViewController
];
self
.
contentPlayerViewController
.
view
.
frame
=
self
.
view
.
bounds
;
[
self
.
view
insertSubview
:
self
.
contentPlayerViewController
.
view
atIndex
:
0
];
[
self
.
contentPlayerViewController
didMoveToParentViewController
:
self
];
}
// Remove and detach the content video player.
-
(
void
)
hideContentPlayer
{
// The whole controller needs to be detached so that it doesn't capture resume events from the
// remote and play content underneath the ad.
[
self
.
contentPlayerViewController
willMoveToParentViewController
:
nil
];
[
self
.
contentPlayerViewController
.
view
removeFromSuperview
];
[
self
.
contentPlayerViewController
removeFromParentViewController
];
}
Swift
class
ViewController
:
UIViewController
,
IMAAdsLoaderDelegate
,
IMAAdsManagerDelegate
{
static
let
contentURLString
=
"https://devstreaming-cdn.apple.com/videos/streaming/examples/"
+
"img_bipbop_adv_example_fmp4/master.m3u8"
static
let
adTagURLString
=
"https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_ad_samples&"
+
"sz=640x480&cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&"
+
"unviewed_position_start=1&env=vp&correlator="
var
adsLoader
:
IMAAdsLoader
!
var
adDisplayContainer
:
IMAAdDisplayContainer
!
var
adsManager
:
IMAAdsManager
!
var
contentPlayhead
:
IMAAVPlayerContentPlayhead
?
var
playerViewController
:
AVPlayerViewController
!
var
adBreakActive
=
false
deinit
{
NotificationCenter
.
default
.
removeObserver
(
self
)
}
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
self
.
view
.
backgroundColor
=
UIColor
.
black
setUpContentPlayer
()
setUpAdsLoader
()
}
override
func
viewDidAppear
(
_
animated
:
Bool
)
{
super
.
viewDidAppear
(
animated
)
requestAds
()
}
In this example, viewDidLoad()
initializes the IMAAdsLoader
, and viewDidAppear()
requests ads once the view is visible. Helper methods showContentPlayer()
and hideContentPlayer()
toggle content visibility during
ad playback.
This example uses the adTagURLString
constant variable to define the VAST ad
tag for the ad request, and the following components to manage IMA SDK:
-
adsLoader: Handles ad requests and responses. We recommend using a single instance for the app's lifecycle. -
adDisplayContainer: Specifies the view for rendering ads. -
adsManager: Manages ad playback and listens for ad events. -
contentPlayhead: Tracks content progress to trigger mid-roll ad breaks. -
adBreakActive: Indicates if an ad break is playing to prevent seeking over ads.
5. Implement content playhead tracker and end-of-stream observer
In order to play mid-roll ads, IMA SDK needs to track the current position
of your video content. To do this, create a class that implements IMAContentPlayhead
. If you're using an AVPlayer
, as shown in this example,
SDK provides the IMAAVPlayerContentPlayhead
class which does this for you.
If you're not using AVPlayer
, you need to implement IMAContentPlayhead
on
a class of your own.
Objective-C
-
(
void
)
setupContentPlayer
{
// Create a content video player. Create a playhead to track content progress so the SDK knows
// when to play ads in a VMAP playlist.
NSURL
*
contentURL
=
[
NSURL
URLWithString
:
kContentURLString
];
AVPlayer
*
player
=
[
AVPlayer
playerWithURL
:
contentURL
];
self
.
contentPlayerViewController
=
[[
AVPlayerViewController
alloc
]
init
];
self
.
contentPlayerViewController
.
player
=
player
;
self
.
contentPlayerViewController
.
view
.
frame
=
self
.
view
.
bounds
;
self
.
contentPlayhead
=
[[
IMAAVPlayerContentPlayhead
alloc
]
initWithAVPlayer
:
self
.
contentPlayerViewController
.
player
];
// Track end of content.
AVPlayerItem
*
contentPlayerItem
=
self
.
contentPlayerViewController
.
player
.
currentItem
;
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
contentDidFinishPlaying
:
)
name
:
AVPlayerItemDidPlayToEndTimeNotification
object
:
contentPlayerItem
];
// Attach content video player to view hierarchy.
[
self
showContentPlayer
];
}
Swift
func
setUpContentPlayer
()
{
// Load AVPlayer with path to our content.
let
contentURL
=
URL
(
string
:
ViewController
.
contentURLString
)
!
let
player
=
AVPlayer
(
url
:
contentURL
)
playerViewController
=
AVPlayerViewController
()
playerViewController
.
player
=
player
// Set up our content playhead and contentComplete callback.
contentPlayhead
=
IMAAVPlayerContentPlayhead
(
avPlayer
:
player
)
NotificationCenter
.
default
.
addObserver
(
self
,
selector
:
#selector
(
ViewController
.
contentDidFinishPlaying
(
_
:)),
name
:
NSNotification
.
Name
.
AVPlayerItemDidPlayToEndTime
,
object
:
player
.
currentItem
)
showContentPlayer
()
}
You also need to let SDK know when your content is done playing so it can
display post-roll ads. This is done by calling contentComplete
on the IMAAdsLoader
, using AVPlayerItemDidPlayToEndTimeNotification
.
Objective-C
-
(
void
)
contentDidFinishPlaying:
(
NSNotification
*
)
notification
{
// Notify the SDK that the postrolls should be played.
[
self
.
adsLoader
contentComplete
];
}
-
(
void
)
dealloc
{
[[
NSNotificationCenter
defaultCenter
]
removeObserver
:
self
];
}
Swift
@objc
func
contentDidFinishPlaying
(
_
notification
:
Notification
)
{
adsLoader
.
contentComplete
()
}
6. Initialize the ads loader and make an ads request
In order to request a set of ads, you need to create an IMAAdsLoader
instance.
This loader can be used to process IMAAdsRequest
objects associated with a
specified ad tag URL.
As a best practice, only maintain one instance of IMAAdsLoader
for the entire
lifecycle of your app. To make additional ad requests, create a new IMAAdsRequest
object, but re-use the same IMAAdsLoader
. For more
information, see the IMA SDK FAQ
.
Objective-C
-
(
void
)
setupAdsLoader
{
self
.
adsLoader
=
[[
IMAAdsLoader
alloc
]
init
];
self
.
adsLoader
.
delegate
=
self
;
}
-
(
void
)
requestAds
{
// Pass the main view as the container for ad display.
self
.
adDisplayContainer
=
[[
IMAAdDisplayContainer
alloc
]
initWithAdContainer
:
self
.
view
viewController
:
self
];
IMAAdsRequest
*
request
=
[[
IMAAdsRequest
alloc
]
initWithAdTagUrl
:
kAdTagURLString
adDisplayContainer
:
self
.
adDisplayContainer
contentPlayhead
:
self
.
contentPlayhead
userContext
:
nil
];
[
self
.
adsLoader
requestAdsWithRequest
:
request
];
}
Swift
func
setUpAdsLoader
()
{
adsLoader
=
IMAAdsLoader
(
settings
:
nil
)
adsLoader
.
delegate
=
self
}
func
requestAds
()
{
// Create ad display container for ad rendering.
adDisplayContainer
=
IMAAdDisplayContainer
(
adContainer
:
self
.
view
,
viewController
:
self
)
// Create an ad request with our ad tag, display container, and optional user context.
let
request
=
IMAAdsRequest
(
adTagUrl
:
ViewController
.
adTagURLString
,
adDisplayContainer
:
adDisplayContainer
,
contentPlayhead
:
contentPlayhead
,
userContext
:
nil
)
adsLoader
.
requestAds
(
with
:
request
)
}
7. Set up an ads loader delegate
On a successful load event, the IMAAdsLoader
calls the adsLoadedWithData
method of its assigned delegate, passing it an instance of IMAAdsManager
. You
can then initialize the ads manager, which loads the individual ads, as defined
by the response to the ad tag URL.
In addition, be sure to handle any errors that may occur during the loading process. If ads do not load, make sure that media playback continues, without ads, so as to not interfere with the user's experience.
Objective-C
#pragma mark - IMAAdsLoaderDelegate
-
(
void
)
adsLoader:
(
IMAAdsLoader
*
)
loader
adsLoadedWithData:
(
IMAAdsLoadedData
*
)
adsLoadedData
{
// Initialize and listen to the ads manager loaded for this request.
self
.
adsManager
=
adsLoadedData
.
adsManager
;
self
.
adsManager
.
delegate
=
self
;
[
self
.
adsManager
initializeWithAdsRenderingSettings
:
nil
];
}
-
(
void
)
adsLoader:
(
IMAAdsLoader
*
)
loader
failedWithErrorData:
(
IMAAdLoadingErrorData
*
)
adErrorData
{
// Fall back to playing content.
NSLog
(
@"Error loading ads: %@"
,
adErrorData
.
adError
.
message
);
[
self
.
contentPlayerViewController
.
player
play
];
}
Swift
func
adsLoader
(
_
loader
:
IMAAdsLoader
,
adsLoadedWith
adsLoadedData
:
IMAAdsLoadedData
)
{
// Grab the instance of the IMAAdsManager and set ourselves as the delegate.
adsManager
=
adsLoadedData
.
adsManager
adsManager
.
delegate
=
self
adsManager
.
initialize
(
with
:
nil
)
}
func
adsLoader
(
_
loader
:
IMAAdsLoader
,
failedWith
adErrorData
:
IMAAdLoadingErrorData
)
{
print
(
"Error loading ads:
\(
adErrorData
.
adError
.
message
??
"No error message available."
)
"
)
showContentPlayer
()
playerViewController
.
player
?.
play
()
}
8. Set up an ads manager delegate
Lastly, to manage events and state changes, the ads manager needs a delegate of
its own. The IMAAdManagerDelegate
has methods to handle ad events and errors,
as well as methods to trigger play and pause on your video content.
Starting playback
There are many events that the didReceiveAdEvent
method can be used to handle.
For this basic example, listen for the LOADED
event to tell the ads
manager to start playback of content and ads. The IMA SDK triggers the ICON_FALLBACK_IMAGE_CLOSED
event when the user closes an icon fallback
dialog after tapping an icon. After this action, ad playback resumes.
Objective-C
#pragma mark - IMAAdsManagerDelegate
-
(
void
)
adsManager:
(
IMAAdsManager
*
)
adsManager
didReceiveAdEvent:
(
IMAAdEvent
*
)
event
{
switch
(
event
.
type
)
{
case
kIMAAdEvent_LOADED
:
{
// Play each ad once it has loaded.
[
adsManager
start
];
break
;
}
case
kIMAAdEvent_ICON_FALLBACK_IMAGE_CLOSED
:
{
// Resume ad after user has closed dialog.
[
adsManager
resume
];
break
;
}
default
:
break
;
}
}
Swift
func
adsManager
(
_
adsManager
:
IMAAdsManager
,
didReceive
event
:
IMAAdEvent
)
{
switch
event
.
type
{
case
IMAAdEventType
.
LOADED
:
// Play each ad once it has been loaded.
adsManager
.
start
()
case
IMAAdEventType
.
ICON_FALLBACK_IMAGE_CLOSED
:
// Resume playback after the user has closed the dialog.
adsManager
.
resume
()
default
:
break
}
}
Handling errors
Add a handler for ad errors as well. If an error occurs, like in the previous step, resume content playback.
Objective-C
-
(
void
)
adsManager:
(
IMAAdsManager
*
)
adsManager
didReceiveAdError:
(
IMAAdError
*
)
error
{
// Fall back to playing content.
NSLog
(
@"AdsManager error: %@"
,
error
.
message
);
[
self
showContentPlayer
];
[
self
.
contentPlayerViewController
.
player
play
];
}
Swift
func
adsManager
(
_
adsManager
:
IMAAdsManager
,
didReceive
error
:
IMAAdError
)
{
// Fall back to playing content
print
(
"AdsManager error:
\(
error
.
message
??
"No error message available."
)
"
)
showContentPlayer
()
playerViewController
.
player
?.
play
()
}
Triggering play and pause events
The last two delegate methods you need to implement are used to trigger play and pause events on the underlying video content, when requested by IMA SDK. Triggering pause and play when requested prevents the user from missing portions of the video content when ads are displayed.
Objective-C
-
(
void
)
adsManagerDidRequestContentPause:
(
IMAAdsManager
*
)
adsManager
{
// Pause the content for the SDK to play ads.
[
self
.
contentPlayerViewController
.
player
pause
];
[
self
hideContentPlayer
];
// Trigger an update to send focus to the ad display container.
self
.
adBreakActive
=
YES
;
[
self
setNeedsFocusUpdate
];
}
-
(
void
)
adsManagerDidRequestContentResume:
(
IMAAdsManager
*
)
adsManager
{
// Resume the content since the SDK is done playing ads (at least for now).
[
self
showContentPlayer
];
[
self
.
contentPlayerViewController
.
player
play
];
// Trigger an update to send focus to the content player.
self
.
adBreakActive
=
NO
;
[
self
setNeedsFocusUpdate
];
}
Swift
func
adsManagerDidRequestContentPause
(
_
adsManager
:
IMAAdsManager
)
{
// Pause the content for the SDK to play ads.
playerViewController
.
player
?.
pause
()
hideContentPlayer
()
// Trigger an update to send focus to the ad display container.
adBreakActive
=
true
setNeedsFocusUpdate
()
}
func
adsManagerDidRequestContentResume
(
_
adsManager
:
IMAAdsManager
)
{
// Resume the content since the SDK is done playing ads (at least for now).
showContentPlayer
()
playerViewController
.
player
?.
play
()
// Trigger an update to send focus to the content player.
adBreakActive
=
false
setNeedsFocusUpdate
()
}
That's it! You're now requesting and displaying ads with IMA SDK. To learn about additional SDK features, see the other guides or the samples on GitHub .
Next Steps
To maximize ad revenue on the tvOS platform, request App Transparency and Tracking permission to use IDFA .



