שנתחיל?

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

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

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

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

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

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

לפני שתתחילו, אתם צריכים:

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.22.1'
    end
    
  2. מהספרייה שמכילה את ה-Podfile, מריצים את pod install --repo-update

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

התקנת ה-SDK באמצעות מנהל החבילות של Swift

Interactive Media Ads SDK תומך ב-Swift Package Manager החל מגרסה 3.18.4. כדי לייבא את חבילת Swift:

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

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

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

כשמסיימים, Xcode מסדיר את יחסי התלות של החבילות ומוריד אותן ברקע. במאמר של Apple מוסבר איך מוסיפים יחסי תלות בחבילות.

הורדה והתקנה ידנית של ה-SDK

אם אתם לא רוצים להשתמש במנהל החבילות של Swift או ב-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 מתי התוכן שלכם מוכן, כדי שניתן יהיה להציג מודעות בסוף הסרטון (post-roll). כדי לעשות זאת, מתקשרים ל-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&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 קורא ל-method 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. איך מעניקים גישה ל-Ads Manager

לסיום, כדי לנהל אירועים ושינויי מצב, מנהל Google Ads צריך גישה משלו. ל-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. במדריכים אחרים ובדוגמאות ב-GitHub תוכלו לקרוא על תכונות נוספות של SDK.

השלבים הבאים

כדי להגדיל את ההכנסות מפרסום בפלטפורמת iOS, צריך לבקש הרשאה למעקב ולשקיפות באפליקציה לגבי שימוש ב-IDFA.