בעזרת ערכות ה-IMA SDK אפשר לשלב בקלות מודעות מולטימדיה באתרים ובאפליקציות. IMA SDK יכול לבקש הצגה של מודעות מכל שרת מודעות שתואם ל-VAST ולנהל את הפעלת המודעות באפליקציות שלך. ערכות SDK בצד הלקוח של IMA מאפשרת לך לשלוט בהפעלת הסרטונים בתוכן, וה-SDK מטפל בהפעלת המודעות. המודעות מופעלות בנגן וידאו נפרד שממוקם מעל נגן הווידאו של תוכן האפליקציה.
המדריך הזה מדגים איך לשלב את ה-IMA SDK באפליקציה פשוטה לנגן וידאו. אם אתם רוצים לראות את השילוב לדוגמה או לעקוב אחריו, תוכלו להוריד את BasicExample מ-GitHub.
סקירה כללית בצד הלקוח של IMA
ההטמעה של IMA בצד הלקוח כוללת ארבעה רכיבי SDK עיקריים, שמוכחים במדריך הזה:
IMAAdDisplayContainer
: אובייקט מאגר שבו המודעות מעובדות.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
התקנת ה-SDK באמצעות CocoaPods (מומלץ)
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.22.1' end
מהספרייה שמכילה את ה-Podfile, מריצים את
pod install --repo-update
כדי לוודא שההתקנה בוצעה בהצלחה, פותחים את הקובץ BasicExample.xcworkspace ומוודאים שהוא מכיל שני פרויקטים: BasicExample ו-Pods (יחסי התלות שהותקנו על ידי CocoaPods).
התקנת ה-SDK באמצעות מנהל החבילות של Swift
Interactive Media Ads SDK תומך ב-Swift Package Manager החל מגרסה 3.18.4. כדי לייבא את חבילת Swift:
ב-Xcode, כדי להתקין את חבילת Swift של IMA SDK, עוברים אל File > Add Packages... (קובץ > הוספת חבילות...).
בהודעה שמופיעה, מחפשים את מאגר GitHub של IMA SDK SDK Swift Package:
https://github.com/googleads/swift-package-manager-google-interactive-media-ads-ios
עליך לבחור בגרסה של חבילת 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.