IMA SDK を使用すると、マルチメディア広告をウェブサイトやアプリに簡単に統合できます。IMA SDK では、 VAST 準拠の広告サーバーから広告をリクエストし、アプリ内での広告再生を管理できます。IMA クライアントサイド SDK を使用すると、SDK が広告再生を処理する一方で、コンテンツの動画再生のコントロールを維持できます。広告は、アプリのコンテンツ動画プレーヤーの上部にある別の動画プレーヤー内で再生されます。
このガイドでは、IMA SDK をシンプルな動画プレーヤー アプリに統合する方法について説明します。統合のサンプルを確認する場合は、GitHub から BasicExample をダウンロードしてください。
IMA クライアントサイドの概要
IMA クライアントサイドの実装には、次の 4 つの主要な SDK コンポーネントが必要です。このガイドでは、これらのコンポーネントについて解説します。
IMAAdDisplayContainer
: 広告がレンダリングされるコンテナ オブジェクト。IMAAdsLoader
: 広告をリクエストし、広告リクエスト レスポンスからのイベントを処理するオブジェクト。アプリケーションのライフサイクル全体で再利用できる広告ローダーは 1 つのみインスタンス化する必要があります。IMAAdsRequest
: 広告リクエストを定義するオブジェクト。広告リクエストでは、VAST 広告タグの URL に加え、広告サイズなどの追加のパラメータも指定します。IMAAdsManager
: 広告リクエストへのレスポンスを格納し、広告の再生を制御し、SDK によって発生した広告イベントをリッスンするオブジェクト。
前提条件
始める前に、次のものが必要になります。
- Xcode 13 以降
- CocoaPods(推奨)、Swift Package Manager、IMA SDK for iOS のダウンロード コピー
1. 新しい Xcode プロジェクトを作成する
Xcode で、Objective-C または Swift を使用して新しい iOS プロジェクトを作成します。プロジェクト名として BasicExample を使用します。
2. IMA SDK を Xcode プロジェクトに追加する
CocoaPods を使用して SDK をインストールする(推奨)
CocoaPods は Xcode プロジェクトの依存関係マネージャーであり、IMA SDK のインストールにはおすすめの方法です。CocoaPods のインストールと使用について詳しくは、CocoaPods のドキュメントをご覧ください。CocoaPods をインストールしたら、次の手順で IMA SDK をインストールします。
BasicExample.xcodeproj ファイルと同じディレクトリに Podfile という名前のテキスト ファイルを作成し、次の構成を追加します。
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '14' target "BasicExample" do pod 'GoogleAds-IMA-iOS-SDK', '~> 3.19.1' end
Podfile を含むディレクトリから
pod install --repo-update
を実行します。インストールが正常に完了したことを確認します。BasicExample.xcworkspace ファイルを開き、BasicExample と Pods(CocoaPods によってインストールされる依存関係)の 2 つのプロジェクトが含まれていることを確認します。
Swift Package Manager を使用して SDK をインストールする
Interactive Media Ads SDK は、バージョン 3.18.4 以降、Swift Package Manager をサポートしています。Swift パッケージをインポートする手順は次のとおりです。
Xcode で [File] > [Add Packages...] の順に移動して、IMA SDK Swift パッケージをインストールします。
表示されるプロンプトで、IMA SDK Swift パッケージ GitHub リポジトリを検索します。
https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
使用する IMA SDK Swift パッケージのバージョンを選択します。 新しいプロジェクトの場合は、[Up to Next メジャー バージョン] を使用することをおすすめします。
作業が完了すると、Xcode はパッケージの依存関係を解決し、それらをバックグラウンドでダウンロードします。パッケージの依存関係を追加する方法について詳しくは、Apple の記事をご覧ください。
SDK を手動でダウンロードしてインストールする
Swift Package Manager や CocoaPods を使用しない場合は、IMA SDK をダウンロードして手動でプロジェクトに追加できます。
3. シンプルな動画プレーヤーを作成する
まず、基本的な動画プレーヤーを実装します。当初は、このプレーヤーは IMA SDK を使用しておらず、再生をトリガーするメソッドをまだ含んでいません。
ViewController.m
Objective-C
#import "ViewController.h" #import <AVKit/AVKit.h> NSString *const kContentURLString = @"https://storage.googleapis.com/interactive-media-ads/media/bipbop.m3u8"; @interface ViewController () @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.blackColor; [self setupContentPlayer]; } - (void)setupContentPlayer { // Create a content video player. 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; // Attach content video player to view hierarchy. [self showContentPlayer]; } // 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 events from the remote. [self.contentPlayerViewController willMoveToParentViewController:nil]; [self.contentPlayerViewController.view removeFromSuperview]; [self.contentPlayerViewController removeFromParentViewController]; } @end
Swift
import AVFoundation import UIKit class ViewController: UIViewController { static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/bipbop.m3u8" var playerViewController: AVPlayerViewController! override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.black; setUpContentPlayer() } func setUpContentPlayer() { // Load AVPlayer with path to your content. let contentURL! = URL(string: ViewController.ContentURLString) let player = AVPlayer(url: contentURL) playerViewController = AVPlayerViewController() playerViewController.player = player showContentPlayer() } func showContentPlayer() { self.addChild(playerViewController) playerViewController.view.frame = self.view.bounds self.view.insertSubview(playerViewController.view, at: 0) playerViewController.didMove(toParent:self) } func hideContentPlayer() { // The whole controller needs to be detached so that it doesn't capture // events from the remote. playerViewController.willMove(toParent:nil) playerViewController.view.removeFromSuperview() playerViewController.removeFromParent() } }
4. IMA SDK をインポートする
次に、既存のインポートの下に import ステートメントを使用して、IMA フレームワークを追加します。
ViewController.m
Objective-C
#import "ViewController.h" #import <AVKit/AVKit.h> #import <GoogleInteractiveMediaAds/GoogleInteractiveMediaAds.h> NSString *const kContentURLString = @"https://storage.googleapis.com/interactive-media-ads/media/bipbop.m3u8";
Swift
import AVFoundation import GoogleInteractiveMediaAds import UIKit class ViewController: UIViewController { static let ContentURLString = "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8"
5. コンテンツ プレイヘッド トラッカーとストリーム終了オブザーバーを実装する
ミッドロール広告を再生するには、IMA SDK が動画コンテンツの現在の位置をトラッキングする必要があります。そのためには、IMAContentPlayhead
を実装するクラスを作成します。AVPlayer
を使用している場合は、次の例に示すように、SDK に用意されている IMAAVPlayerContentPlayhead
クラスが代行されます。AVPlayer
を使用していない場合は、独自のクラスに IMAContentPlayhead
を実装する必要があります。
また、コンテンツの再生が完了したら SDK に通知し、ポストロール広告を表示できるようにする必要があります。これを行うには、AVPlayerItemDidPlayToEndTimeNotification
を使用して、IMAAdsLoader
で contentComplete
を呼び出します。
ViewController.m
Objective-C
... @interface ViewController () @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end ... - (void)setupContentPlayer { // Create a content video player. 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]; } ... - (void)contentDidFinishPlaying:(NSNotification *)notification {} - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; } @end
Swift
... class ViewController: UIViewController { static let ContentURLString = "https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8" var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! deinit { NotificationCenter.default.removeObserver(self) } ... func setUpContentPlayer() { // Load AVPlayer with path to your content. let contentURL! = URL(string: ViewController.ContentURLString) let player = AVPlayer(url: contentURL) playerViewController = AVPlayerViewController() playerViewController.player = player // Set up your 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() } ... @objc func contentDidFinishPlaying(_ notification: Notification) { adsLoader.contentComplete() } }
6. 広告ローダーを初期化して広告リクエストを行う
一連の広告をリクエストするには、IMAAdsLoader
インスタンスを作成する必要があります。このローダは、指定した広告タグ URL に関連付けられている IMAAdsRequest
オブジェクトの処理に使用できます。
IMAAdsLoader
のインスタンスは、アプリのライフサイクル全体で 1 つだけ維持することをおすすめします。広告リクエストを追加するには、新しい IMAAdsRequest
オブジェクトを作成し、同じ IMAAdsLoader
を再利用します。詳しくは、IMA SDK に関するよくある質問をご覧ください。
ViewController.m
Objective-C
... NSString *const kContentURLString = @"https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/" @"master.m3u8"; 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&impl=s&cmsid=496&vid=short_onecue&correlator="; @interface ViewController () @property(nonatomic) IMAAdsLoader *adsLoader; @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = UIColor.blackColor; [self setupContentPlayer]; [self setupAdsLoader]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self requestAds]; } - (void)setupAdsLoader { self.adsLoader = [[IMAAdsLoader alloc] init]; } - (void)requestAds { // Pass the main view as the container for ad display. IMAAdDisplayContainer *adDisplayContainer = [[IMAAdDisplayContainer alloc] initWithAdContainer:self.view]; IMAAdsRequest *request = [[IMAAdsRequest alloc] initWithAdTagUrl:kAdTagURLString adDisplayContainer:adDisplayContainer contentPlayhead:self.contentPlayhead userContext:nil]; [self.adsLoader requestAdsWithRequest:request]; } ... - (void)contentDidFinishPlaying:(NSNotification *)notification { // Notify the SDK that the postrolls should be played. [self.adsLoader contentComplete]; } ... @end
Swift
... class ViewController: UIViewController { 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&impl=s&correlator=" var adsLoader: IMAAdsLoader! var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! ... override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.black; setUpContentPlayer() setUpAdsLoader() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated); requestAds() } ... func setUpAdsLoader() { adsLoader = IMAAdsLoader(settings: nil) } func requestAds() { // Create ad display container for ad rendering. let adDisplayContainer = IMAAdDisplayContainer(adContainer: self.view) // 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) } @objc func contentDidFinishPlaying(_ notification: Notification) { adsLoader.contentComplete() } }
7. 広告ローダのデリゲートを設定する
読み込みイベントが成功すると、IMAAdsLoader
は割り当てられたデリゲートの adsLoadedWithData
メソッドを呼び出し、IMAAdsManager
のインスタンスを渡します。その後、広告マネージャーを初期化します。これにより、広告タグ URL へのレスポンスで定義されているとおりに、個々の広告が読み込まれます。
また、読み込み中に発生する可能性のあるすべてのエラーを必ず処理してください。広告が読み込まれない場合は、ユーザー エクスペリエンスを妨げないように、広告なしでメディアの再生を続行してください。
ViewController.m
Objective-C
... @interface ViewController () <IMAAdsLoaderDelegate> @property(nonatomic) IMAAdsLoader *adsLoader; @property(nonatomic) IMAAdsManager *adsManager; @property(nonatomic) IMAAVPlayerContentPlayhead *contentPlayhead; @property(nonatomic) AVPlayerViewController *contentPlayerViewController; @end @implementation ViewController ... - (void)setupAdsLoader { self.adsLoader = [[IMAAdsLoader alloc] init]; self.adsLoader.delegate = self; } ... #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 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]; } @end
Swift
... class ViewController: UIViewController, IMAAdsLoaderDelegate { ... var adsLoader: IMAAdsLoader! var adsManager: IMAAdsManager! var contentPlayhead: IMAAVPlayerContentPlayhead? var playerViewController: AVPlayerViewController! ... func setUpAdsLoader() { adsLoader = IMAAdsLoader(settings: nil) adsLoader.delegate = self } ... // MARK: - IMAAdsLoaderDelegate func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) { adsManager = adsLoadedData.adsManager adsManager.initialize(with: nil) } func adsLoader(_ loader: IMAAdsLoader!, failedWith adErrorData: IMAAdLoadingErrorData!) { print("Error loading ads: " + adErrorData.adError.message) showContentPlayer() playerViewController.player?.play() } }
8. 広告マネージャー デリゲートを設定する
最後に、イベントと状態の変更を管理するには、広告マネージャーが自身のデリゲートを必要とします。IMAAdManagerDelegate
には、広告イベントとエラーを処理するメソッドと、動画コンテンツの再生と一時停止をトリガーするメソッドがあります。
再生を開始する
didReceiveAdEvent
メソッドで処理できるイベントは多数ありますが、この基本的な例では、LOADED
イベントをリッスンして、コンテンツと広告の再生を開始するよう広告マネージャーに指示しています。
ViewController.m
Objective-C
@interface ViewController () <IMAAdsLoaderDelegate, IMAAdsManagerDelegate> ... - (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]; } ... #pragma mark - IMAAdsManagerDelegate - (void)adsManager:(IMAAdsManager *)adsManager didReceiveAdEvent:(IMAAdEvent *)event { // Play each ad once it has loaded. if (event.type == kIMAAdEvent_LOADED) { [adsManager start]; } } ...
Swift
... class ViewController: UIViewController, IMAAdsLoaderDelegate, IMAAdsManagerDelegate { ... func adsLoader(_ loader: IMAAdsLoader!, adsLoadedWith adsLoadedData: IMAAdsLoadedData!) { // Grab the instance of the IMAAdsManager and set yourself as the delegate. adsManager = adsLoadedData.adsManager adsManager.delegate = self adsManager.initialize(with: nil) } ... // MARK: - IMAAdsManagerDelegate func adsManager(_ adsManager: IMAAdsManager!, didReceive event: IMAAdEvent!) { // Play each ad once it has been loaded if event.type == IMAAdEventType.LOADED { adsManager.start() } } ...
エラー処理
広告エラーのハンドラも追加します。前の手順のようなエラーが発生した場合は、コンテンツの再生を再開します。
ViewController.m
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]; } @end
Swift
... func adsManager(_ adsManager: IMAAdsManager!, didReceive error: IMAAdError!) { // Fall back to playing content print("AdsManager error: " + error.message) showContentPlayer() playerViewController.player?.play() }
再生イベントと一時停止イベントのトリガー
実装する必要がある最後の 2 つのデリゲート メソッドは、IMA SDK からリクエストされた場合に、ベースとなる動画コンテンツの再生イベントと一時停止イベントをトリガーするために使用されます。リクエストされたときに一時停止と再生をトリガーすると、広告の表示時にユーザーが動画コンテンツの一部を見落とすことがなくなります。
ViewController.m
Objective-C
... - (void)adsManagerDidRequestContentPause:(IMAAdsManager *)adsManager { // Pause the content for the SDK to play ads. [self.contentPlayerViewController.player pause]; [self hideContentPlayer]; } - (void)adsManagerDidRequestContentResume:(IMAAdsManager *)adsManager { // Resume the content since the SDK is done playing ads (at least for now). [self showContentPlayer]; [self.contentPlayerViewController.player play]; } @end
Swift
... func adsManagerDidRequestContentPause(_ adsManager: IMAAdsManager!) { // Pause the content for the SDK to play ads. playerViewController.player?.pause() hideContentPlayer() } func adsManagerDidRequestContentResume(_ adsManager: IMAAdsManager!) { // Resume the content since the SDK is done playing ads (at least for now). showContentPlayer() playerViewController.player?.play() } }
これで完了です。これで、IMA SDK を使用して広告をリクエストし、表示できます。その他の SDK 機能については、他のガイドや GitHub のサンプルをご覧ください。
次のステップ
iOS プラットフォームで広告収益を最大化するには、IDFA の使用について「App Transparency とトラッキング」権限をリクエストしてください。