ตั้งค่า IMA SDK สําหรับ DAI

เลือกแพลตฟอร์ม: HTML5 Android iOS tvOS Cast Roku

IMA SDK ช่วยให้ผสานรวมโฆษณามัลติมีเดียเข้ากับเว็บไซต์และแอปได้อย่างง่ายดาย IMA SDK สามารถ ขอโฆษณาจากเซิร์ฟเวอร์โฆษณา ที่รองรับ VAST และจัดการการเล่นโฆษณาในแอปของคุณ เมื่อใช้ IMA DAI SDK แอปจะส่ง คำขอสตรีมสำหรับโฆษณาและเนื้อหาวิดีโอ ไม่ว่าจะเป็นเนื้อหา VOD หรือเนื้อหาแบบสด จากนั้น SDK จะแสดงสตรีมวิดีโอที่รวมกัน เพื่อให้คุณไม่ต้องจัดการการสลับระหว่างโฆษณาและวิดีโอเนื้อหาภายในแอป

เลือกโซลูชัน DAI ที่คุณสนใจ

DAI แบบบริการเต็มรูปแบบ

คู่มือนี้ครอบคลุมการผสานรวม IMA DAI SDK เข้ากับแอปวิดีโอเพลเยอร์ หากต้องการดูหรือทำตามตัวอย่างการผสานรวมที่เสร็จสมบูรณ์แล้ว ให้ดาวน์โหลด BasicExample จาก GitHub

ภาพรวม IMA DAI

การติดตั้งใช้งาน IMA DAI เกี่ยวข้องกับคอมโพเนนต์ SDK หลัก 4 อย่างตามที่คู่มือนี้ แสดงให้เห็น

  • IMAAdDisplayContainer – ออบเจ็กต์คอนเทนเนอร์ที่อยู่เหนือองค์ประกอบการเล่นวิดีโอและมีองค์ประกอบ UI ของโฆษณา
  • IMAAdsLoader – ออบเจ็กต์ที่ขอสตรีมและจัดการเหตุการณ์ที่ทริกเกอร์โดยออบเจ็กต์การตอบกลับคำขอสตรีม คุณควรสร้างอินสแตนซ์ของ AdsLoader เพียงรายการเดียว ซึ่งสามารถนำกลับมาใช้ใหม่ได้ตลอดอายุการใช้งานของแอปพลิเคชัน
  • IMAStreamRequest – IMAVODStreamRequest หรือ IMALiveStreamRequest ออบเจ็กต์ที่กำหนดคำขอสตรีม คำขอสตรีมอาจเป็นคำขอสำหรับวิดีโอออนดีมานด์หรือไลฟ์สดก็ได้ คำขอไลฟ์สดจะระบุคีย์ชิ้นงาน ส่วนคำขอ VOD จะระบุรหัส CMS และรหัสวิดีโอ คำขอทั้ง 2 ประเภทอาจมีคีย์ API ที่จำเป็นต่อการเข้าถึงสตรีมที่ระบุ และรหัสเครือข่าย Ad Manager ของ Google สำหรับ IMA SDK เพื่อจัดการตัวระบุโฆษณาตามที่ระบุในการตั้งค่า Google Ad Manager
  • IMAStreamManager – ออบเจ็กต์ที่จัดการสตรีมการแทรกโฆษณาแบบไดนามิกและการโต้ตอบกับแบ็กเอนด์ DAI Stream Manager ยังจัดการ Pings การติดตามและส่งต่อเหตุการณ์สตรีมและโฆษณาไปยัง ผู้เผยแพร่โฆษณาด้วย

ข้อกำหนดเบื้องต้น

ก่อนเริ่มต้น คุณต้องมีสิ่งต่อไปนี้

นอกจากนี้ คุณยังต้องใช้พารามิเตอร์เพื่อขอสตรีมจาก IMA SDK ด้วย ดูตัวอย่างพารามิเตอร์คำขอได้ที่ ตัวอย่างสตรีม

พารามิเตอร์ไลฟ์สด
คีย์เนื้อหา คีย์ของชิ้นงาน ระบุไลฟ์สดใน Google Ad Manager
ตัวอย่าง: c-rArva4ShKVIAkNfy6HUQ
พารามิเตอร์สตรีม VOD
รหัสแหล่งที่มาของเนื้อหา รหัสแหล่งที่มาของเนื้อหา จาก Google Ad Manager
ตัวอย่าง: 2548831
รหัสวิดีโอ รหัสวิดีโอจาก Google Ad Manager
ตัวอย่าง: tears-of-steel
พารามิเตอร์ทั่วไป (VOD และไลฟ์สด)
รหัสเครือข่าย รหัสเครือข่าย Ad Manager ของ Google
ตัวอย่าง: 21775744923

สร้างโปรเจ็กต์ Xcode ใหม่

ใน Xcode ให้สร้างโปรเจ็กต์ iOS ใหม่โดยใช้ Objective-C ชื่อ "BasicExample"

เพิ่ม IMA DAI SDK ลงในโปรเจ็กต์ Xcode

หากต้องการติดตั้ง IMA SDK ให้เลือกวิธีที่ต้องการ

แนะนำ: ติดตั้ง SDK โดยใช้ Swift Package Manager

SDK โฆษณาสื่ออินเทอร์แอกทีฟรองรับ Swift Package Manager ตั้งแต่เวอร์ชัน 3.18.4 เป็นต้นไป ทำตาม ขั้นตอนเหล่านี้เพื่อนำเข้าแพ็กเกจ Swift

  1. ใน Xcode ให้ติดตั้งแพ็กเกจ Swift ของ IMA DAI SDK โดยไปที่ ไฟล์ > เพิ่มแพ็กเกจ

  2. ในพรอมต์ที่ปรากฏขึ้น ให้ค้นหาที่เก็บ IMA DAI SDK Swift Package GitHub

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
    
  3. เลือกเวอร์ชันของแพ็กเกจ IMA DAI SDK Swift ที่ต้องการใช้ สำหรับโปรเจ็กต์ใหม่ ให้ใช้อัปเดตเป็นเวอร์ชันหลักถัดไป

เมื่อดำเนินการเสร็จแล้ว Xcode จะแก้ไขการขึ้นต่อกันของแพ็กเกจและดาวน์โหลดไว้ในเบื้องหลัง ดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีเพิ่มการอ้างอิงแพ็กเกจได้ที่บทความของ Apple

ดาวน์โหลดและติดตั้ง SDK ด้วยตนเอง

หากไม่ต้องการใช้ Swift Package Manager ให้ดาวน์โหลดและเพิ่ม IMA SDK ลงในโปรเจ็กต์ด้วยตนเอง

สร้างวิดีโอเพลเยอร์

ใช้วิดีโอเพลเยอร์ในตัวควบคุมมุมมองหลัก และห่อหุ้ม AVPlayer ในมุมมอง UI IMA SDK ใช้มุมมอง UI เพื่อแสดงองค์ประกอบ UI ของโฆษณา

Objective-C

#import "ViewController.h"

#import <AVKit/AVKit.h>

/// Content URL.
static NSString *const kBackupContentUrl =
    @"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8";

@interface ViewController ()
/// Play button.
@property(nonatomic, weak) IBOutlet UIButton *playButton;

@property(nonatomic, weak) IBOutlet UIView *videoView;
/// Video player.
@property(nonatomic, strong) AVPlayer *videoPlayer;
@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.view.backgroundColor = [UIColor blackColor];

  // Load AVPlayer with the path to your content.
  NSURL *contentURL = [NSURL URLWithString:kBackupContentUrl];
  self.videoPlayer = [AVPlayer playerWithURL:contentURL];

  // Create a player layer for the player.
  AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.videoPlayer];

  // Size, position, and display the AVPlayer.
  playerLayer.frame = self.videoView.layer.bounds;
  [self.videoView.layer addSublayer:playerLayer];
}

- (IBAction)onPlayButtonTouch:(id)sender {
  [self.videoPlayer play];
  self.playButton.hidden = YES;
}

@end

Swift

// Copyright 2024 Google LLC. All rights reserved.
//
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License. You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under
// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
// ANY KIND, either express or implied. See the License for the specific language governing
// permissions and limitations under the License.

import AVFoundation
import UIKit

class ViewController: UIViewController {

  /// Content URL.
  static let backupStreamURLString =
    "http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8"

  /// Play button.
  @IBOutlet private weak var playButton: UIButton!

  @IBOutlet private weak var videoView: UIView!
  /// Video player.
  private var videoPlayer: AVPlayer?

  override func viewDidLoad() {
    super.viewDidLoad()

    playButton.layer.zPosition = CGFloat(MAXFLOAT)

    // Load AVPlayer with path to our content.
    // note: this unwrap is safe because the URL is a constant string.
    let contentURL = URL(string: ViewController.backupStreamURLString)!
    videoPlayer = AVPlayer(url: contentURL)

    // Create a player layer for the player.
    let playerLayer = AVPlayerLayer(player: videoPlayer)

    // Size, position, and display the AVPlayer.
    playerLayer.frame = videoView.layer.bounds
    videoView.layer.addSublayer(playerLayer)
  }

  @IBAction func onPlayButtonTouch(_ sender: Any) {
    videoPlayer?.play()
    playButton.isHidden = true
  }
}

เริ่มต้นเครื่องมือโหลดโฆษณา

นำเข้า IMA SDK ไปยังตัวควบคุมมุมมองและใช้โปรโตคอล IMAAdsLoaderDelegate และ IMAStreamManagerDelegate เพื่อจัดการเหตุการณ์ของเครื่องมือโหลดโฆษณาและเครื่องมือจัดการสตรีม

เพิ่มพร็อพเพอร์ตี้ส่วนตัวต่อไปนี้เพื่อจัดเก็บคอมโพเนนต์หลักของ IMA SDK

  • IMAAdsLoader
    • จัดการคำขอสตรีมตลอดอายุการใช้งานของแอป
  • IMAAdDisplayContainer
    • จัดการการแทรกและจัดการองค์ประกอบอินเทอร์เฟซผู้ใช้ของโฆษณา
  • IMAAVPlayerVideoDisplay - สื่อสารระหว่าง IMA SDK กับมีเดียเพลเยอร์และจัดการข้อมูลเมตาที่กำหนดเวลา
  • IMAStreamManager - จัดการการเล่นสตรีมและทริกเกอร์เหตุการณ์ที่เกี่ยวข้องกับโฆษณา

เริ่มต้นตัวโหลดโฆษณา คอนเทนเนอร์ที่แสดงโฆษณา และการแสดงวิดีโอหลังจากที่ โหลดมุมมอง

Objective-C

@import GoogleInteractiveMediaAds;

// ...

@interface ViewController () <IMAAdsLoaderDelegate, IMAStreamManagerDelegate>
/// The entry point for the IMA DAI SDK to make DAI stream requests.
@property(nonatomic, strong) IMAAdsLoader *adsLoader;
/// The container where the SDK renders each ad's user interface elements and companion slots.
@property(nonatomic, strong) IMAAdDisplayContainer *adDisplayContainer;
/// The reference of your video player for the IMA DAI SDK to monitor playback and handle timed
/// metadata.
@property(nonatomic, strong) IMAAVPlayerVideoDisplay *imaVideoDisplay;
/// References the stream manager from the IMA DAI SDK after successful stream loading.
@property(nonatomic, strong) IMAStreamManager *streamManager;

// ...

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  // ...

  self.adsLoader = [[IMAAdsLoader alloc] initWithSettings:nil];
  self.adsLoader.delegate = self;

  // Create an ad display container for rendering each ad's user interface elements and companion
  // slots.
  self.adDisplayContainer =
      [[IMAAdDisplayContainer alloc] initWithAdContainer:self.videoView
                                          viewController:self
                                          companionSlots:nil];

  // Create an IMAAVPlayerVideoDisplay to give the SDK access to your video player.
  self.imaVideoDisplay = [[IMAAVPlayerVideoDisplay alloc] initWithAVPlayer:self.videoPlayer];
}

Swift

import GoogleInteractiveMediaAds
// ...

class ViewController: UIViewController, IMAAdsLoaderDelegate, IMAStreamManagerDelegate {
  // ...

  /// The entry point for the IMA DAI SDK to make DAI stream requests.
  private var adsLoader: IMAAdsLoader?
  /// The container where the SDK renders each ad's user interface elements and companion slots.
  private var adDisplayContainer: IMAAdDisplayContainer?
  /// The reference of your video player for the IMA DAI SDK to monitor playback and handle timed
  /// metadata.
  private var imaVideoDisplay: IMAAVPlayerVideoDisplay!
  /// References the stream manager from the IMA DAI SDK after successfully loading the DAI stream.
  private var streamManager: IMAStreamManager?

  // ...

  override func viewDidLoad() {
    super.viewDidLoad()

    // ...

    adsLoader = IMAAdsLoader(settings: nil)
    adsLoader?.delegate = self

    // Create an ad display container for rendering ad UI elements and the companion ad.
    adDisplayContainer = IMAAdDisplayContainer(
      adContainer: videoView,
      viewController: self,
      companionSlots: nil)

    // Create an IMAAVPlayerVideoDisplay to give the SDK access to your video player.
    imaVideoDisplay = IMAAVPlayerVideoDisplay(avPlayer: videoPlayer)
  }

ส่งคำขอสตรีม

เมื่อผู้ใช้กดปุ่มเล่น ให้ส่งคำขอสตรีมใหม่ ใช้คลาส IMALiveStreamRequest สำหรับไลฟ์สด สำหรับสตรีม VOD ให้ใช้คลาส IMAVODStreamRequest

คำขอสตรีมต้องใช้พารามิเตอร์สตรีม รวมถึงการอ้างอิงถึง คอนเทนเนอร์ที่แสดงโฆษณาและวิดีโอที่แสดง

Objective-C

- (IBAction)onPlayButtonTouch:(id)sender {
  [self requestStream];
  self.playButton.hidden = YES;
}

- (void)requestStream {
  // Create a stream request. Use one of "Live stream request" or "VOD request", depending on your
  // type of stream.
  if (kStreamType == StreamTypeLive) {
    // Live stream request. Replace the asset key with your value.
    IMALiveStreamRequest *request =
        [[IMALiveStreamRequest alloc] initWithAssetKey:kLiveStreamAssetKey
                                           networkCode:kNetworkCode
                                    adDisplayContainer:self.adDisplayContainer
                                          videoDisplay:self.imaVideoDisplay
                                           userContext:nil];
    request.useHLSInterstitials = YES;
    [self.adsLoader requestStreamWithRequest:request];
  } else {
    // VOD request. Replace the content source ID and video ID with your values.
    IMAVODStreamRequest *request =
        [[IMAVODStreamRequest alloc] initWithContentSourceID:kVODContentSourceID
                                                     videoID:kVODVideoID
                                                 networkCode:kNetworkCode
                                          adDisplayContainer:self.adDisplayContainer
                                                videoDisplay:self.imaVideoDisplay
                                                 userContext:nil];
    [self.adsLoader requestStreamWithRequest:request];
  }
}

Swift

@IBAction func onPlayButtonTouch(_ sender: Any) {
  requestStream()
  playButton.isHidden = true
}

func requestStream() {
  // Create a stream request. Use one of "Livestream request" or "VOD request".
  if ViewController.requestType == StreamType.live {
    // Livestream request.
    let request = IMALiveStreamRequest(
      assetKey: ViewController.assetKey,
      networkCode: ViewController.networkCode,
      adDisplayContainer: adDisplayContainer!,
      videoDisplay: imaVideoDisplay,
      userContext: nil)
    request.useHLSInterstitials = true
    adsLoader?.requestStream(with: request)
  } else {
    // VOD stream request.
    let request = IMAVODStreamRequest(
      contentSourceID: ViewController.contentSourceID,
      videoID: ViewController.videoID,
      networkCode: ViewController.networkCode,
      adDisplayContainer: adDisplayContainer!,
      videoDisplay: imaVideoDisplay,
      userContext: nil)
    adsLoader?.requestStream(with: request)
  }
}

รอเหตุการณ์การโหลดสตรีม

คลาส IMAAdsLoader เรียกใช้เมธอด IMAAdsLoaderDelegate เมื่อการเริ่มต้นสำเร็จหรือคำขอสตรีมล้มเหลว

ในเมธอด adsLoadedWithData delegate ให้ตั้งค่า IMAStreamManagerDelegate เริ่มต้นตัวจัดการสตรีม เมื่อเริ่มต้น ตัวจัดการสตรีมจะเริ่ม การเล่น

ในเมธอด failedWithErrorData delegate ให้บันทึกข้อผิดพลาด คุณจะเล่นสตรีมสำรองหรือไม่ก็ได้ ดูแนวทางปฏิบัติแนะนำสำหรับ DAI

Objective-C

- (void)adsLoader:(IMAAdsLoader *)loader adsLoadedWithData:(IMAAdsLoadedData *)adsLoadedData {
  NSLog(@"Stream created with: %@.", adsLoadedData.streamManager.streamId);
  self.streamManager = adsLoadedData.streamManager;
  self.streamManager.delegate = self;
  [self.streamManager initializeWithAdsRenderingSettings:nil];
}

- (void)adsLoader:(IMAAdsLoader *)loader failedWithErrorData:(IMAAdLoadingErrorData *)adErrorData {
  // Log the error and play the content.
  NSLog(@"AdsLoader error, code:%ld, message: %@", adErrorData.adError.code,
        adErrorData.adError.message);
  [self.videoPlayer play];
}

Swift

func adsLoader(_ loader: IMAAdsLoader, adsLoadedWith adsLoadedData: IMAAdsLoadedData) {
  print("DAI stream loaded. Stream session ID: \(adsLoadedData.streamManager!.streamId!)")
  streamManager = adsLoadedData.streamManager!
  streamManager!.delegate = self
  streamManager!.initialize(with: nil)
}

func adsLoader(_ loader: IMAAdsLoader, failedWith adErrorData: IMAAdLoadingErrorData) {
  print("Error loading DAI stream. Error message: \(adErrorData.adError.message!)")
  // Play the backup stream.
  videoPlayer.play()
}

รอเหตุการณ์โฆษณา

IMAStreamManager เรียกใช้เมธอด IMAStreamManagerDelegate เพื่อส่งเหตุการณ์และข้อผิดพลาดของสตรีมไปยังแอปพลิเคชัน

ในตัวอย่างนี้ ให้บันทึกเหตุการณ์โฆษณาหลักไปยังคอนโซล

Objective-C

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdEvent:(IMAAdEvent *)event {
  NSLog(@"Ad event (%@).", event.typeString);
  switch (event.type) {
    case kIMAAdEvent_STARTED: {
      // Log extended data.
      NSString *extendedAdPodInfo = [[NSString alloc]
          initWithFormat:@"Showing ad %ld/%ld, bumper: %@, title: %@, description: %@, contentType:"
                         @"%@, pod index: %ld, time offset: %lf, max duration: %lf.",
                         (long)event.ad.adPodInfo.adPosition, (long)event.ad.adPodInfo.totalAds,
                         event.ad.adPodInfo.isBumper ? @"YES" : @"NO", event.ad.adTitle,
                         event.ad.adDescription, event.ad.contentType,
                         (long)event.ad.adPodInfo.podIndex, event.ad.adPodInfo.timeOffset,
                         event.ad.adPodInfo.maxDuration];

      NSLog(@"%@", extendedAdPodInfo);
      break;
    }
    case kIMAAdEvent_AD_BREAK_STARTED: {
      NSLog(@"Ad break started");
      break;
    }
    case kIMAAdEvent_AD_BREAK_ENDED: {
      NSLog(@"Ad break ended");
      break;
    }
    case kIMAAdEvent_AD_PERIOD_STARTED: {
      NSLog(@"Ad period started");
      break;
    }
    case kIMAAdEvent_AD_PERIOD_ENDED: {
      NSLog(@"Ad period ended");
      break;
    }
    default:
      break;
  }
}

- (void)streamManager:(IMAStreamManager *)streamManager didReceiveAdError:(IMAAdError *)error {
  NSLog(@"StreamManager error with type: %ld\ncode: %ld\nmessage: %@", error.type, error.code,
        error.message);
  [self.videoPlayer play];
}

Swift

func streamManager(_ streamManager: IMAStreamManager, didReceive event: IMAAdEvent) {
  print("Ad event \(event.typeString).")
  switch event.type {
  case IMAAdEventType.STARTED:
    // Log extended data.
    if let ad = event.ad {
      let extendedAdPodInfo = String(
        format: "Showing ad %zd/%zd, bumper: %@, title: %@, "
          + "description: %@, contentType:%@, pod index: %zd, "
          + "time offset: %lf, max duration: %lf.",
        ad.adPodInfo.adPosition,
        ad.adPodInfo.totalAds,
        ad.adPodInfo.isBumper ? "YES" : "NO",
        ad.adTitle,
        ad.adDescription,
        ad.contentType,
        ad.adPodInfo.podIndex,
        ad.adPodInfo.timeOffset,
        ad.adPodInfo.maxDuration)

      print("\(extendedAdPodInfo)")
    }
    break
  case IMAAdEventType.AD_BREAK_STARTED:
    print("Ad break started.")
    break
  case IMAAdEventType.AD_BREAK_ENDED:
    print("Ad break ended.")
    break
  case IMAAdEventType.AD_PERIOD_STARTED:
    print("Ad period started.")
    break
  case IMAAdEventType.AD_PERIOD_ENDED:
    print("Ad period ended.")
    break
  default:
    break
  }
}

func streamManager(_ streamManager: IMAStreamManager, didReceive error: IMAAdError) {
  print("StreamManager error with type: \(error.type)")
  print("code: \(error.code)")
  print("message: \(error.message ?? "Unknown Error")")
}

เรียกใช้แอป หากสำเร็จ ให้ขอและเล่นสตรีม DAI ของ Google ด้วย IMA SDK ดูข้อมูลเกี่ยวกับฟีเจอร์ SDK ขั้นสูงเพิ่มเติมได้ในคำแนะนำอื่นๆ ที่แสดงในแถบด้านข้างทางซ้ายหรือตัวอย่างใน GitHub