started monetizing your video content with ads.
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 the 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
- CocoaPods (preferred), Swift Package Manager, or a downloaded copy of the IMA SDK for iOS
1. Create a new Xcode project
In Xcode, create a new iOS project using Objective-C or Swift. Use BasicExample as the project name.
2. Add the IMA SDK to the Xcode project
Install the SDK using CocoaPods (recommended)
CocoaPods is a dependency manager for Xcode projects and is the recommended method for installing the IMA SDK. For more information on installing or using CocoaPods, see the CocoaPods documentation. Once you have CocoaPods installed, use the following instructions to install the IMA SDK:
In the same directory as your BasicExample.xcodeproj file, create a text file called Podfile, and add the following configuration:
Objective-C
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '12' target "BasicExample" do pod 'GoogleAds-IMA-iOS-SDK', '~> 3.26.1' end
Swift
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '12' target "BasicExample" do pod 'GoogleAds-IMA-iOS-SDK', '~> 3.26.1' end
From the directory that contains the Podfile, run
pod install --repo-update
.Verify that the installation was successful by opening the BasicExample.xcworkspace file and confirming that it contains two projects: BasicExample and Pods (the dependencies installed by CocoaPods).
Install the SDK using Swift Package Manager
The Interactive Media Ads SDK supports Swift Package Manager starting in version 3.18.4. To import the Swift package, complete the following steps:
In Xcode, install the IMA SDK Swift Package by navigating to File > Add Package Dependencies....
In the prompt, search for the IMA iOS SDK Swift Package GitHub repository:
swift-package-manager-google-interactive-media-ads-ios
.Select the version of the 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.
Manually download and install the SDK
If you don't want to use Swift Package Manager or CocoaPods, you can download the IMA SDK and manually add it to your project.
3. Create a video player
First, implement a video player. Initially, this player does not use the IMA SDK and doesn't contain any method to trigger playback.
Objective-C
Import the player dependencies:
#import "ViewController.h"
@import AVFoundation;
Set up the player variables:
@interface ViewController () <IMAAdsLoaderDelegate, IMAAdsManagerDelegate>
/// Content video player.
@property(nonatomic, strong) AVPlayer *contentPlayer;
/// Play button.
@property(nonatomic, weak) IBOutlet UIButton *playButton;
/// UIView in which we will render our AVPlayer for content.
@property(nonatomic, weak) IBOutlet UIView *videoView;
Initiate the video player when the view loads:
@implementation ViewController
// The content URL to play.
NSString *const kTestAppContentUrl_MP4 =
@"https://storage.googleapis.com/gvabox/media/samples/stock.mp4";
// Ad tag
NSString *const kTestAppAdTagUrl = @"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=";
- (void)viewDidLoad {
[super viewDidLoad];
self.playButton.layer.zPosition = MAXFLOAT;
[self setupAdsLoader];
[self setUpContentPlayer];
}
#pragma mark Content Player Setup
- (void)setUpContentPlayer {
// Load AVPlayer with path to our content.
NSURL *contentURL = [NSURL URLWithString:kTestAppContentUrl_MP4];
self.contentPlayer = [AVPlayer playerWithURL:contentURL];
// Create a player layer for the player.
AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.contentPlayer];
// Size, position, and display the AVPlayer.
playerLayer.frame = self.videoView.layer.bounds;
[self.videoView.layer addSublayer:playerLayer];
// Set up our content playhead and contentComplete callback.
self.contentPlayhead = [[IMAAVPlayerContentPlayhead alloc] initWithAVPlayer:self.contentPlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contentDidFinishPlaying:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.contentPlayer.currentItem];
}
- (IBAction)onPlayButtonTouch:(id)sender {
[self requestAds];
self.playButton.hidden = YES;
}
Swift
Import the player dependencies:
import AVFoundation
Set up the player variables:
class PlayerContainerViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate {
static let contentURL = URL(
string: "https://storage.googleapis.com/gvabox/media/samples/stock.mp4")!
private var contentPlayer = AVPlayer(url: PlayerContainerViewController.contentURL)
private lazy var playerLayer: AVPlayerLayer = {
AVPlayerLayer(player: contentPlayer)
}()
Initiate the video player when the view loads:
private lazy var videoView: UIView = {
let videoView = UIView()
videoView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(videoView)
NSLayoutConstraint.activate([
videoView.bottomAnchor.constraint(
equalTo: view.safeAreaLayoutGuide.bottomAnchor),
videoView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
videoView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
videoView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
])
return videoView
}()
// MARK: - View controller lifecycle methods
override func viewDidLoad() {
super.viewDidLoad()
videoView.layer.addSublayer(playerLayer)
adsLoader.delegate = self
NotificationCenter.default.addObserver(
self,
selector: #selector(contentDidFinishPlaying(_:)),
name: .AVPlayerItemDidPlayToEndTime,
object: contentPlayer.currentItem)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
playerLayer.frame = videoView.layer.bounds
}
override func viewWillTransition(
to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator
) {
coordinator.animate { _ in
// do nothing
} completion: { _ in
self.playerLayer.frame = self.videoView.layer.bounds
}
}
// MARK: - Public methods
func playButtonPressed() {
requestAds()
}
4. Import the IMA SDK
To import the IMA SDK, do the following:
Objective-C
Import the IMA SDK:
@import GoogleInteractiveMediaAds;
Create variables for the
IMAAdsLoader
,IMAAVPlayerContentPlayhead
, andIMAAdsManager
classes used in the app:// SDK /// Entry point for the SDK. Used to make ad requests. @property(nonatomic, strong) IMAAdsLoader *adsLoader; /// Playhead used by the SDK to track content video progress and insert mid-rolls. @property(nonatomic, strong) IMAAVPlayerContentPlayhead *contentPlayhead; /// Main point of interaction with the SDK. Created by the SDK as the result of an ad request. @property(nonatomic, strong) IMAAdsManager *adsManager;
Swift
Import the IMA SDK:
import GoogleInteractiveMediaAds
Create variables for the
IMAAdsLoader
,IMAAVPlayerContentPlayhead
, andIMAAdsManager
classes used in the app: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=" private let adsLoader = IMAAdsLoader() private var adsManager: IMAAdsManager? private lazy var contentPlayhead: IMAAVPlayerContentPlayhead = { IMAAVPlayerContentPlayhead(avPlayer: contentPlayer) }()
5. Implement content playhead tracker and end-of-stream observer
In order to play mid-roll ads, the 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,
the SDK provides the IMAAVPlayerContentPlayhead
class which does this for you.
If you're not using AVPlayer
, you'll need to implement IMAContentPlayhead
on
a class of your own.
You also need to let the SDK know when your content is done playing so it can
display post-roll ads. This is done by calling the
contentComplete
method on the IMAAdsLoader, using AVPlayerItemDidPlayToEndTimeNotification
.
Objective-C
Create the IMAAVPlayerContentPlayhead
instance in the player setup:
// Set up our content playhead and contentComplete callback.
self.contentPlayhead = [[IMAAVPlayerContentPlayhead alloc] initWithAVPlayer:self.contentPlayer];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(contentDidFinishPlaying:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.contentPlayer.currentItem];
Create the contentDidFinishPlaying()
method to call
IMAAdsLoader.contentComplete()
when the content finishes playing:
- (void)contentDidFinishPlaying:(NSNotification *)notification {
// Make sure we don't call contentComplete as a result of an ad completing.
if (notification.object == self.contentPlayer.currentItem) {
[self.adsLoader contentComplete];
}
}
Swift
Create the content ended observer in the player setup:
NotificationCenter.default.addObserver(
self,
selector: #selector(contentDidFinishPlaying(_:)),
name: .AVPlayerItemDidPlayToEndTime,
object: contentPlayer.currentItem)
Create the contentDidFinishPlaying()
method to call
IMAAdsLoader.contentComplete()
when the content finishes playing:
@objc func contentDidFinishPlaying(_ notification: Notification) {
// Make sure we don't call contentComplete as a result of an ad completing.
if notification.object as? AVPlayerItem == contentPlayer.currentItem {
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] initWithSettings:nil];
self.adsLoader.delegate = self;
}
- (void)requestAds {
// Create an ad display container for ad rendering.
IMAAdDisplayContainer *adDisplayContainer =
[[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
viewController:self
companionSlots:nil];
// Create an ad request with our ad tag, display container, and optional user context.
IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:kTestAppAdTagUrl
adDisplayContainer:adDisplayContainer
contentPlayhead:self.contentPlayhead
userContext:nil];
[self.adsLoader requestAdsWithRequest:request];
}
Swift
private func requestAds() {
// Create ad display container for ad rendering.
let adDisplayContainer = IMAAdDisplayContainer(
adContainer: videoView, viewController: self, companionSlots: nil)
// Create an ad request with our ad tag, display container, and optional user context.
let request = IMAAdsRequest(
adTagUrl: PlayerContainerViewController.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 don't load, make sure that media playback continues, without ads, so as to not interfere with the user's experience.
Objective-C
- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
// Grab the instance of the IMAAdsManager and set ourselves as the delegate.
self.adsManager = adsLoadedData.adsManager;
self.adsManager.delegate = self;
// Create ads rendering settings to tell the SDK to use the in-app browser.
IMAAdsRenderingSettings *adsRenderingSettings = [[IMAAdsRenderingSettings alloc] init];
adsRenderingSettings.linkOpenerPresentingController = self;
// Initialize the ads manager.
[self.adsManager initializeWithAdsRenderingSettings:adsRenderingSettings];
}
- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
// Something went wrong loading ads. Log the error and play the content.
NSLog(@"Error loading ads: %@", adErrorData.adError.message);
[self.contentPlayer 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
// Create ads rendering settings and tell the SDK to use the in-app browser.
let adsRenderingSettings = IMAAdsRenderingSettings()
adsRenderingSettings.linkOpenerPresentingController = self
// Initialize the ads manager.
adsManager?.initialize(with: adsRenderingSettings)
}
func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
if let message = adErrorData.adError.message {
print("Error loading ads: \(message)")
}
contentPlayer.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.
Start playback
Listen for the LOADED
event to start playback of content and ads. For more
details, see
didReceiveAdEvent
.
Objective-C
- (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event {
// When the SDK notified us that ads have been loaded, play them.
if (event.type == kIMAAdEvent_LOADED) {
[adsManager start];
}
}
Swift
func adsManager(_ adsManager: IMAAdsManager, didReceive event: IMAAdEvent) {
// When the SDK notifies us the ads have been loaded, play them.
if event.type == IMAAdEventType.LOADED {
adsManager.start()
}
}
Handle 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 {
// Something went wrong with the ads manager after ads were loaded. Log the error and play the
// content.
NSLog(@"AdsManager error: %@", error.message);
[self.contentPlayer play];
}
Swift
func adsManager(_ adsManager: IMAAdsManager, didReceive error: IMAAdError) {
// Something went wrong with the ads manager after ads were loaded.
// Log the error and play the content.
if let message = error.message {
print("AdsManager error: \(message)")
}
contentPlayer.play()
}
Listen for 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 the 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 {
// The SDK is going to play ads, so pause the content.
[self.contentPlayer pause];
}
- (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager {
// The SDK is done playing ads (at least for now), so resume the content.
[self.contentPlayer play];
}
Swift
func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager) {
// The SDK is going to play ads, so pause the content.
contentPlayer.pause()
}
func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager) {
// The SDK is done playing ads (at least for now), so resume the content.
contentPlayer.play()
}
That's it! You're now requesting and displaying ads with the 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 iOS platform, request App Transparency and Tracking permission to use IDFA.