מודעות בפתיחת אפליקציה

בחירת פלטפורמה: Android iOS Unity Flutter

המדריך הזה מיועד לבעלי אפליקציות שמטמיעים מודעות בפתיחת אפליקציה.

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

מודעות בפתיחת האפליקציה מציגות באופן אוטומטי אזור מיתוג קטן כדי שהמשתמשים ידעו שהם באפליקציה שלכם. הנה דוגמה למודעה בפתיחת האפליקציה:

אלה השלבים הנדרשים להטמעה של מודעות בפתיחת אפליקציה:

  1. יוצרים מחלקה לניהול שמטעינה מודעה לפני שצריך להציג אותה.
  2. הצגת המודעה במהלך אירועים של העברת האפליקציה לחזית.
  3. טיפול בהחזרות (callbacks) של מצגות.

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

תמיד כדאי לבצע בדיקות באמצעות מודעות בדיקה

כשמפתחים ובודקים אפליקציות, חשוב להשתמש במודעות בדיקה ולא במודעות פעילות שמוצגות למשתמשים. אם לא תעשו את זה, אנחנו עשויים להשעות את החשבון שלכם.

הדרך הכי קלה לטעון מודעות בדיקה היא להשתמש במזהה יחידת המודעות הייעודי לבדיקה של מודעות לפתיחת אפליקציה:

ca-app-pub-3940256099942544/5575463023

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

מידע נוסף על אופן הפעולה של מודעות בדיקה ב-Mobile Ads SDK זמין במאמר מודעות בדיקה.

הטמעה של מחלקה לניהול

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

יוצרים מחלקה חדשה מסוג Singleton בשם AppOpenAdManager:

Swift

class AppOpenAdManager: NSObject {
  /// The app open ad.
  var appOpenAd: AppOpenAd?
  /// Maintains a reference to the delegate.
  weak var appOpenAdManagerDelegate: AppOpenAdManagerDelegate?
  /// Keeps track of if an app open ad is loading.
  var isLoadingAd = false
  /// Keeps track of if an app open ad is showing.
  var isShowingAd = false
  /// Keeps track of the time when an app open ad was loaded to discard expired ad.
  var loadTime: Date?
  /// For more interval details, see https://support.google.com/admob/answer/9341964
  let timeoutInterval: TimeInterval = 4 * 3_600

  static let shared = AppOpenAdManager()

Objective-C

@interface AppOpenAdManager ()

/// The app open ad.
@property(nonatomic, strong, nullable) GADAppOpenAd *appOpenAd;
/// Keeps track of if an app open ad is loading.
@property(nonatomic, assign) BOOL isLoadingAd;
/// Keeps track of if an app open ad is showing.
@property(nonatomic, assign) BOOL isShowingAd;
/// Keeps track of the time when an app open ad was loaded to discard expired ad.
@property(nonatomic, strong, nullable) NSDate *loadTime;

@end

/// For more interval details, see https://support.google.com/admob/answer/9341964
static const NSInteger kTimeoutInterval = 4;

@implementation AppOpenAdManager

+ (nonnull AppOpenAdManager *)sharedInstance {
  static AppOpenAdManager *instance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    instance = [[AppOpenAdManager alloc] init];
  });
  return instance;
}

ומטמיעים את פרוטוקול AppOpenAdManagerDelegate:

Swift

protocol AppOpenAdManagerDelegate: AnyObject {
  /// Method to be invoked when an app open ad life cycle is complete (i.e. dismissed or fails to
  /// show).
  func appOpenAdManagerAdDidComplete(_ appOpenAdManager: AppOpenAdManager)
}

Objective-C

@protocol AppOpenAdManagerDelegate <NSObject>
/// Method to be invoked when an app open ad life cycle is complete (i.e. dismissed or fails to
/// show).
- (void)adDidComplete;
@end

טעינת מודעה

השלב הבא הוא טעינת מודעה להצגה בפתיחת אפליקציה:

Swift

func loadAd() async {
  // Do not load ad if there is an unused ad or one is already loading.
  if isLoadingAd || isAdAvailable() {
    return
  }
  isLoadingAd = true

  do {
    appOpenAd = try await AppOpenAd.load(
      with: "ca-app-pub-3940256099942544/5575463023", request: Request())
    appOpenAd?.fullScreenContentDelegate = self
    loadTime = Date()
  } catch {
    print("App open ad failed to load with error: \(error.localizedDescription)")
    appOpenAd = nil
    loadTime = nil
  }
  isLoadingAd = false
}

Objective-C

- (void)loadAd {
  // Do not load ad if there is an unused ad or one is already loading.
  if ([self isAdAvailable] || self.isLoadingAd) {
    return;
  }
  self.isLoadingAd = YES;

  [GADAppOpenAd loadWithAdUnitID:@"ca-app-pub-3940256099942544/5575463023"
                         request:[GADRequest request]
               completionHandler:^(GADAppOpenAd * _Nullable appOpenAd, NSError * _Nullable error) {
    self.isLoadingAd = NO;
    if (error) {
      NSLog(@"App open ad failed to load with error: %@", error);
      self.appOpenAd = nil;
      self.loadTime = nil;
      return;
    }
    self.appOpenAd = appOpenAd;
    self.appOpenAd.fullScreenContentDelegate = self;
    self.loadTime = [NSDate date];
  }];
}

הצגת מודעה

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

Swift

func showAdIfAvailable() {
  // If the app open ad is already showing, do not show the ad again.
  if isShowingAd {
    return print("App open ad is already showing.")
  }

  // If the app open ad is not available yet but is supposed to show, load
  // a new ad.
  if !isAdAvailable() {
    print("App open ad is not ready yet.")
    // The app open ad is considered to be complete in this example.
    appOpenAdManagerDelegate?.appOpenAdManagerAdDidComplete(self)
    // Load a new ad.
    return
  }

  if let appOpenAd {
    appOpenAd.present(from: nil)
    isShowingAd = true
  }
}

Objective-C

- (void)showAdIfAvailable {
  // If the app open ad is already showing, do not show the ad again.
  if (self.isShowingAd) {
    NSLog(@"App open ad is already showing.");
    return;
  }

  // If the app open ad is not available yet but is supposed to show, load
  // a new ad.
  if (![self isAdAvailable]) {
    NSLog(@"App open ad is not ready yet.");
    // The app open ad is considered to be complete in this example.
    [self adDidComplete];
    // Load a new ad.
    return;
  }

  [self.appOpenAd presentFromRootViewController:nil];
  self.isShowingAd = YES;
}

הצגת המודעה במהלך אירועים של העברת האפליקציה לחזית

כשהאפליקציה הופכת לפעילה, מתבצעת קריאה ל-showAdIfAvailable() כדי להציג מודעה אם יש מודעה זמינה, או נטענת מודעה חדשה.

Swift

func applicationDidBecomeActive(_ application: UIApplication) {
  // Show the app open ad when the app is foregrounded.
  AppOpenAdManager.shared.showAdIfAvailable()
}

Objective-C

- (void) applicationDidBecomeActive:(UIApplication *)application {
  // Show the app open ad when the app is foregrounded.
  [AppOpenAdManager.sharedInstance showAdIfAvailable];
}

טיפול בהתקשרות חזרה של מצגות

כדי לקבל התראות על אירועים של הצגת מודעות, צריך להקצות את GADFullScreenContentDelegate למאפיין של fullScreenContentDelegate`s במודעה שמוחזרת:

Swift

appOpenAd?.fullScreenContentDelegate = self

Objective-C

self.appOpenAd.fullScreenContentDelegate = self;

בפרט, כדאי לשלוח בקשה להצגת מודעה לפתיחת האפליקציה הבאה אחרי שהמודעה הראשונה מסיימת את ההצגה. בדוגמה הבאה אפשר לראות איך מטמיעים את הפרוטוקול בקובץ AppOpenAdManager:

Swift

func adDidRecordImpression(_ ad: FullScreenPresentingAd) {
  print("App open ad recorded an impression.")
}

func adDidRecordClick(_ ad: FullScreenPresentingAd) {
  print("App open ad recorded a click.")
}

func adWillDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("App open ad will be dismissed.")
}

func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("App open ad will be presented.")
}

func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("App open ad was dismissed.")
  appOpenAd = nil
  isShowingAd = false
  appOpenAdManagerDelegate?.appOpenAdManagerAdDidComplete(self)
  Task {
    await loadAd()
  }
}

func ad(
  _ ad: FullScreenPresentingAd,
  didFailToPresentFullScreenContentWithError error: Error
) {
  print("App open ad failed to present with error: \(error.localizedDescription)")
  appOpenAd = nil
  isShowingAd = false
  appOpenAdManagerDelegate?.appOpenAdManagerAdDidComplete(self)
  Task {
    await loadAd()
  }
}

Objective-C

- (void)adDidRecordImpression:(nonnull id<GADFullScreenPresentingAd>)ad {
  NSLog(@"App open ad recorded an impression.");
}

- (void)adDidRecordClick:(nonnull id<GADFullScreenPresentingAd>)ad {
  NSLog(@"App open ad recorded a click.");
}

- (void)adWillPresentFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
  NSLog(@"App open ad will be presented.");
}

- (void)adWillDismissFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
  NSLog(@"App open ad will be dismissed.");
}

- (void)adDidDismissFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
  NSLog(@"App open ad was dismissed.");
  self.appOpenAd = nil;
  self.isShowingAd = NO;
  [self adDidComplete];
  [self loadAd];
}

- (void)ad:(nonnull id<GADFullScreenPresentingAd>)ad
    didFailToPresentFullScreenContentWithError:(nonnull NSError *)error {
  NSLog(@"App open ad failed to present with error: %@", error.localizedDescription);
  self.appOpenAd = nil;
  self.isShowingAd = NO;
  [self adDidComplete];
  [self loadAd];
}

כדאי לשקול את תפוגת התוקף של המודעות

כדי לוודא שלא מוצגת מודעה שתוקפה פג, אפשר להוסיף שיטה לנציג האפליקציה שבודקת את הזמן שחלף מאז שההפניה למודעה נטענה.

ב-AppOpenAdManager מוסיפים מאפיין Date בשם loadTime ומגדירים את המאפיין כשהמודעה נטענת. לאחר מכן אפשר להוסיף שיטה שמחזירה true אם עברו פחות ממספר מסוים של שעות מאז שהמודעה נטענה. לפני שמנסים להציג את המודעה, חשוב לבדוק את התוקף של הפניה למודעה.

Swift

private func wasLoadTimeLessThanNHoursAgo(timeoutInterval: TimeInterval) -> Bool {
  // Check if ad was loaded more than n hours ago.
  if let loadTime = loadTime {
    return Date().timeIntervalSince(loadTime) < timeoutInterval
  }
  return false
}

private func isAdAvailable() -> Bool {
  // Check if ad exists and can be shown.
  return appOpenAd != nil && wasLoadTimeLessThanNHoursAgo(timeoutInterval: timeoutInterval)
}

Objective-C

- (BOOL)wasLoadTimeLessThanNHoursAgo:(int)n {
  // Check if ad was loaded more than n hours ago.
  NSDate *now = [NSDate date];
  NSTimeInterval timeIntervalBetweenNowAndLoadTime = [now timeIntervalSinceDate:self.loadTime];
  double secondsPerHour = 3600.0;
  double intervalInHours = timeIntervalBetweenNowAndLoadTime / secondsPerHour;
  return intervalInHours < n;
}

- (BOOL)isAdAvailable {
  // Check if ad exists and can be shown.
  return _appOpenAd && [self wasLoadTimeLessThanNHoursAgo:kTimeoutInterval];
}

הפעלות במצב התחלתי (cold start) ומסכי טעינה

במסמכים מניחים שאתם מציגים מודעות בפתיחת האפליקציה רק כשהמשתמשים מעבירים את האפליקציה לחזית כשהיא מושהית בזיכרון. 'הפעלות קרות' מתרחשות כשהאפליקציה מופעלת אבל לא הושעתה קודם בזיכרון.

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

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

שיטות מומלצות

מודעות בפתיחת האפליקציה נועדו לעזור לכם לייצר הכנסות מדף הטעינה של האפליקציה, אבל חשוב להקפיד על שיטות מומלצות כדי שהמשתמשים ייהנו מהשימוש באפליקציה. הקפידו על הדברים הבאים:

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

דוגמה מלאה ב-GitHub

Swift Objective-C

השלבים הבאים

מידע נוסף על פרטיות המשתמשים