הגדרת IMA SDK

התחלת להפעיל מונטיזציה של תוכן הווידאו שלך באמצעות מודעות.

ערכות IMA SDK מאפשרות לשלב בקלות מודעות מולטימדיה באתרים ובאפליקציות. ‫IMA SDKs יכולים לשלוח בקשות למודעות מכל שרת מודעות שתואם ל-VAST ולנהל את ההפעלה של המודעות באפליקציות. עם IMA SDK בצד הלקוח, אתם שומרים על שליטה בהפעלת תוכן הווידאו, בזמן שה-SDK מטפל בהפעלת המודעה. המודעות מוצגות בנגן וידאו נפרד שממוקם מעל נגן הווידאו של התוכן באפליקציה.

במדריך הזה מוסבר איך לשלב את IMA SDK באפליקציית נגן וידאו פשוטה. אם רוצים לראות או לעקוב אחרי שילוב לדוגמה, אפשר להוריד את BasicExample מ-GitHub.

סקירה כללית על IMA בצד הלקוח

הטמעה של IMA בצד הלקוח כוללת ארבעה רכיבי SDK עיקריים, שמוסברים במדריך הזה:

  • IMAAdDisplayContainer: אובייקט מאגר שמציין איפה IMA מעבד רכיבי ממשק משתמש של מודעות ומודד את הניראות, כולל Active View ו-Open Measurement.
  • IMAAdsLoader: אובייקט שמבקש מודעות ומטפל באירועים מתגובות לבקשות מודעות. צריך ליצור רק מופע אחד של הכלי להעלאת מודעות, שאפשר להשתמש בו שוב לאורך חיי האפליקציה.
  • IMAAdsRequest: אובייקט שמגדיר בקשה להצגת מודעות. בבקשות להצגת מודעות מצוינת כתובת ה-URL של תג המודעה בפורמט VAST, וגם פרמטרים נוספים כמו מידות המודעה.
  • IMAAdsManager: אובייקט שמכיל את התגובה לבקשה להצגת מודעות, שולט בהפעלת המודעות ומאזין לאירועים של מודעות שהופעלו על ידי ה-SDK.

דרישות מוקדמות

לפני שמתחילים, צריך:

  • ‫Xcode 13 ואילך
  • CocoaPods (מומלץ), Swift Package Manager או עותק להורדה של IMA SDK ל-iOS

1. יצירת פרויקט חדש ב-Xcode

ב-Xcode, יוצרים פרויקט iOS חדש באמצעות Objective-C או Swift. משתמשים ב-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.26.1'
    end
    
  2. מהספרייה שמכילה את Podfile, מריצים את הפקודה pod install --repo-update

  3. כדי לוודא שההתקנה בוצעה בהצלחה, פותחים את הקובץ BasicExample.xcworkspace ומוודאים שהוא מכיל שני פרויקטים: BasicExample ו-Pods (התלויות שהותקנו על ידי CocoaPods).

התקנת ה-SDK באמצעות Swift Package Manager

החל מגרסה 3.18.4,‏ Interactive Media Ads SDK תומך ב-Swift Package Manager. כדי לייבא את חבילת Swift, פועלים לפי השלבים הבאים.

  1. ב-Xcode, מתקינים את חבילת ה-Swift של IMA SDK על ידי מעבר אל File > Add Packages... (קובץ > הוספת חבילות...).

  2. בהנחיה שמופיעה, מחפשים את מאגר IMA SDK Swift Package GitHub:

    https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
    
  3. בוחרים את הגרסה של חבילת IMA SDK Swift שרוצים להשתמש בה. לפרויקטים חדשים, מומלץ להשתמש באפשרות עד הגרסה הראשית הבאה.

אחרי שתסיימו, פלטפורמת 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. הטמעה של כלי למעקב אחר מיקום ההפעלה של תוכן ושל כלי למעקב אחר סיום הסטרימינג

כדי להציג מודעות באמצע הסרטון (mid-roll), ערכת IMA SDK צריכה לעקוב אחרי המיקום הנוכחי של תוכן הווידאו. כדי לעשות זאת, יוצרים מחלקה שמטמיעה את IMAContentPlayhead. אם אתם משתמשים ב-AVPlayer, כמו שמוצג בדוגמה הזו, ה-SDK מספק את המחלקה IMAAVPlayerContentPlayhead שמבצעת את הפעולה הזו בשבילכם. אם אתם לא משתמשים ב-AVPlayer, תצטרכו להטמיע את IMAContentPlayhead בכיתה משלכם.

צריך גם להודיע ל-SDK מתי התוכן סיים את ההפעלה כדי שיוכל להציג מודעות אחרי הפעלת התוכן. כדי לעשות את זה, קוראים ל-contentComplete ב-IMAAdsLoader באמצעות AVPlayerItemDidPlayToEndTimeNotification.

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. אפשר להשתמש בטוען הזה כדי לעבד אובייקטים של IMAAdsRequest שמשויכים לכתובת URL ספציפית של תג מודעה.

מומלץ לשמור רק מופע אחד של IMAAdsLoader לאורך כל מחזור החיים של האפליקציה. כדי לשלוח בקשות נוספות להצגת מודעות, צריך ליצור אובייקט 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&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&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()
    }
  }

...
      

טיפול בשגיאות

כדאי להוסיף גם handler לשגיאות שקשורות למודעות. אם מתרחשת שגיאה, כמו בשלב הקודם, מפעילים מחדש את התוכן.

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()
  }
      

הפעלת אירועי הפעלה והשהיה

שתי שיטות ההקצאה האחרונות שצריך להטמיע משמשות להפעלת אירועי הפעלה והשהיה בתוכן הווידאו הבסיסי, כשמתקבלת בקשה מ-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.