概要

IMA SDK を使用すると、マルチメディア広告をウェブサイトやアプリに簡単に統合できます。IMA SDK は、 VAST 準拠の任意の広告サーバーから広告をリクエストし、アプリ内の広告再生を管理できます。IMA クライアントサイド SDK を使用すると、コンテンツ動画の再生は引き続き管理できますが、広告の再生は SDK が処理します。広告は、アプリのコンテンツ動画プレーヤーの上に配置された別の動画プレーヤーで再生されます。

このガイドでは、IMA SDK をシンプルな動画プレーヤー アプリに統合する方法について説明します。統合済みのサンプルを表示または確認するには、GitHub から BasicExample をダウンロードしてください。

IMA クライアントサイドの概要

IMA クライアントサイドの実装には、次の 4 つの主要な SDK コンポーネントが関与します。このガイドでは、それらのコンポーネントについて説明します。

  • IMAAdDisplayContainer: 広告がレンダリングされるコンテナ オブジェクト。
  • IMAAdsLoader: 広告をリクエストし、広告リクエスト レスポンスからのイベントを処理するオブジェクト。インスタンス化すべき広告ローダは 1 つだけです。この広告ローダは、アプリの存続期間全体で再利用できます。
  • IMAAdsRequest: 広告リクエストを定義するオブジェクト。Google 広告リクエストでは、VAST 広告タグの URL と、広告のサイズなどの追加パラメータを指定します。
  • IMAAdsManager: 広告リクエストへのレスポンスを含むオブジェクト。広告の再生を制御し、SDK によって発生した広告イベントをリッスンします。

前提条件

始める前に、次のものが必要になります。

  • Xcode 13 以降
  • CocoaPods(推奨)、Swift パッケージ マネージャー、または IMA SDK for iOS のダウンロード コピー

1. 新しい Xcode プロジェクトを作成する

Xcode で、Objective-C または Swift を使用して新しい iOS プロジェクトを作成します。プロジェクト名として BasicExample を使用します。

2. IMA SDK を Xcode プロジェクトに追加する

CocoaPods は Xcode プロジェクトの依存関係マネージャーであり、IMA SDK のインストールに推奨される方法です。CocoaPods のインストールまたは使用の詳細については、CocoaPods のドキュメントをご覧ください。CocoaPods をインストールしたら、次の手順で IMA SDK をインストールします。

  1. BasicExample.xcodeproj ファイルと同じディレクトリに Podfile というテキスト ファイルを作成し、次の構成を追加します。

    source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, '14'
    target "BasicExample" do
      pod 'GoogleAds-IMA-iOS-SDK', '~> 3.23.0'
    end
    
  2. Podfile が含まれているディレクトリから pod install --repo-update を実行します。

  3. BasicExample.xcworkspace ファイルを開き、BasicExamplePods(CocoaPods によってインストールされた依存関係)の 2 つのプロジェクトが含まれていることを確認して、インストールが正常に完了したことを確認します。

Swift Package Manager を使用して SDK をインストールする

Interactive Media Ads SDK はバージョン 3.18.4 以降で Swift Package Manager に対応しています。Swift パッケージをインポートする手順は次のとおりです。

  1. Xcode で File > Add Packages... を開き、IMA SDK の Swift パッケージをインストールします。

  2. 表示されたプロンプトで、IMA SDK Swift パッケージの GitHub リポジトリ(下記)を検索します。

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
    
  3. 使用する IMA SDK Swift パッケージのバージョンを選択します。新しいプロジェクトの場合は [Up to Next Major Version] を選択することをおすすめします。

完了すると、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/stock.mp4";

@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/stock.mp4"

  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 をインポートする

次に、既存のインポートの下にインポート ステートメントを使用して 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/stock.mp4";
      

Swift

import AVFoundation
import GoogleInteractiveMediaAds
import UIKit

class ViewController: UIViewController {
  static let ContentURLString = "https://storage.googleapis.com/interactive-media-ads/media/stock.mp4"
      

5. コンテンツの再生ヘッド トラッカーとストリーミング終了オブザーバーを実装する

ミッドロール広告を再生するには、IMA SDK が動画コンテンツの現在の位置をトラッキングする必要があります。そのためには、IMAContentPlayhead を実装するクラスを作成します。この例のように AVPlayer を使用している場合、SDK にはこの処理を行う IMAAVPlayerContentPlayhead クラスが用意されています。AVPlayer を使用していない場合は、独自のクラスに IMAContentPlayhead を実装する必要があります。

また、コンテンツの再生が終了したことを SDK に通知して、ポストロール広告を表示できるようにする必要があります。これを行うには、AVPlayerItemDidPlayToEndTimeNotification を使用して IMAAdsLoadercontentComplete を呼び出します。

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://storage.googleapis.com/interactive-media-ads/media/stock.mp4"

  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://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&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://storage.googleapis.com/interactive-media-ads/media/stock.mp4"
  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 とトラッキング許可をリクエストします。