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

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

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

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

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

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

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

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

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

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

/21775744923/example/app-open

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

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

הטמעת סוג מנהלים

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

יוצרים מחלקת singleton חדשה בשם AppOpenAdManager וממלאים אותה באופן הבא:

Swift

class AppOpenAdManager: NSObject {
  var appOpenAd: GADAppOpenAd?
  var isLoadingAd = false.
  var isShowingAd = false

  static let shared = AppOpenAdManager()

  private func loadAd() async {
    // TODO: Implement loading an ad.
  }

  func showAdIfAvailable() {
    // TODO: Implement showing an ad.
  }

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

Objective-C

@interface AppOpenAdManager ()
@property(nonatomic, strong) GADAppOpenAd *appOpenAd;
@property(nonatomic, assign) BOOL isLoadingAd;
@property(nonatomic, assign) BOOL isShowingAd;

@end

@implementation AppOpenAdManager

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

- (void)loadAd {
  // TODO: Implement loading an ad.
}

// Add this method to the .h file.
- (void)showAdIfAvailable {
  // TODO: Implement showing an ad.
}

- (BOOL)isAdAvailable {
  // Check if ad exists and can be shown.
  return self.appOpenAd != nil;
}

@end

טעינת מודעה

השלב הבא הוא למלא את השיטה loadAd().

Swift

private 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 GADAppOpenAd.load(
      withAdUnitID: "/21775744923/example/app-open", request: GAMRequest())
  } catch {
    print("App open ad failed to load with error: \(error.localizedDescription)")
  }
  isLoadingAd = false
}

Objective-C

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

  [GADAppOpenAd loadWithAdUnitID:@"/21775744923/example/app-open"
                       request:[GAMRequest request]
             completionHandler:^(GADAppOpenAd *_Nullable appOpenAd, NSError *_Nullable error) {
               self.isLoadingAd = NO;
               if (error) {
                 NSLog(@"Failed to load app open ad: %@", error);
                 return;
               }
               self.appOpenAd = appOpenAd;
             }];
}

הצגת מודעה

השלב הבא הוא למלא את השיטה showAdIfAvailable(). אם אין מודעה זמינה, המערכת תנסה לטעון מודעה.

Swift

func showAdIfAvailable() {
  // If the app open ad is already showing, do not show the ad again.
  guard !isShowingAd else { return }

  // If the app open ad is not available yet but is supposed to show, load
  // a new ad.
  if !isAdAvailable() {
    Task {
      await loadAd()
    }
    return
  }

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

Objective-C

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

  // If the app open ad is not available yet but is supposed to show, load a
  // new ad.
  if (![self isAdAvailable]) {
    [self loadAd];
    return;
  }

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

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

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

Swift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  // ...

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

Objective-C

@implementation AppDelegate
// ...

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

@end

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

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

בכיתה AppOpenAdManager, מוסיפים את הפרטים הבאים:

Swift

class AppOpenAdManager: NSObject, GADFullScreenContentDelegate {
  // ...

  private 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 GADAppOpenAd.load(
        withAdUnitID: "/21775744923/example/app-open", request: GAMRequest())
      appOpenAd?.fullScreenContentDelegate = self
    } catch {
      print("App open ad failed to load with error: \(error.localizedDescription)")
    }
    isLoadingAd = false
  }

  // ...

  // MARK: - GADFullScreenContentDelegate methods

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

  func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
    appOpenAd = nil
    isShowingAd = false
    // Reload an ad.
    Task {
      await loadAd()
    }
  }

  func ad(
    _ ad: GADFullScreenPresentingAd,
    didFailToPresentFullScreenContentWithError error: Error
  ) {
    appOpenAd = nil
    isShowingAd = false
    // Reload an ad.
    Task {
      await loadAd()
    }
  }
}

Objective-C

@interface AppOpenAdManager () <GADFullScreenContentDelegate>
@property(nonatomic, strong) GADAppOpenAd *appOpenAd
@property(nonatomic, assign) BOOL isLoadingAd;
@property(nonatomic, assign) BOOL isShowingAd;

@end

@implementation AppOpenAdManager

// ...

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

  [GADAppOpenAd loadWithAdUnitID:@"/21775744923/example/app-open"
                       request:[GAMRequest request]
             completionHandler:^(GADAppOpenAd *_Nullable appOpenAd, NSError *_Nullable error) {
              self.isLoadingAd = NO;
               if (error) {
                 NSLog(@"Failed to load app open ad: %@", error);
                 return;
               }
               self.appOpenAd = appOpenAd;
               self.appOpenAd.fullScreenContentDelegate = self;
             }];
}

- (BOOL)isAdAvailable {
  // Check if ad exists and can be shown.
  return self.appOpenAd != nil;
}

// ...

#pragma mark - GADFullScreenContentDelegate methods

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

- (void)adDidDismissFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
  self.appOpenAd = nil;
  self.isShowingAd = NO;
  // Reload an ad.
  [self loadAd];
}

- (void)ad:(nonnull id<GADFullScreenPresentingAd>)ad
    didFailToPresentFullScreenContentWithError:(nonnull NSError *)error {
  self.appOpenAd = nil;
  self.isShowingAd = NO;
  // Reload an ad.
  [self loadAd];
}

@end

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

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

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

Swift

class AppOpenAdManager: NSObject, GADFullScreenContentDelegate {
  var appOpenAd: GADAppOpenAd?
  var isLoadingAd = false.
  var isShowingAd = false
  var loadTime: Date?
  let fourHoursInSeconds = TimeInterval(3600 * 4)

  // ...

  private 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 GADAppOpenAd.load(
        withAdUnitID: "/21775744923/example/app-open", request: GAMRequest())
      appOpenAd?.fullScreenContentDelegate = self
      loadTime = Date()
    } catch {
      print("App open ad failed to load with error: \(error.localizedDescription)")
    }
    isLoadingAd = false
  }

  private func wasLoadTimeLessThanFourHoursAgo() -> Bool {
    guard let loadTime = loadTime else { return false }
    // Check if ad was loaded more than four hours ago.
    return Date().timeIntervalSince(loadTime) < fourHoursInSeconds
  }

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

Objective-C

static NSTimeInterval const fourHoursInSeconds = 3600 * 4;

@interface AppOpenAdManager () <GADFullScreenContentDelegate>
@property(nonatomic, strong) GADAppOpenAd *appOpenAd
@property(nonatomic, assign) BOOL isLoadingAd;
@property(nonatomic, assign) BOOL isShowingAd;
@property(weak, nonatomic) NSDate *loadTime;

@end

@implementation AppOpenAdManager

// ...

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

  [GADAppOpenAd loadWithAdUnitID:@"/21775744923/example/app-open"
                       request:[GAMRequest request]
             completionHandler:^(GADAppOpenAd *_Nullable appOpenAd, NSError *_Nullable error) {
              self.isLoadingAd = NO;
               if (error) {
                 NSLog(@"Failed to load app open ad: %@", error);
                 return;
               }
               self.appOpenAd = appOpenAd;
               self.appOpenAd.fullScreenContentDelegate = self;
               self.loadTime = [NSDate date];
             }];
}

- (BOOL)wasLoadTimeLessThanFourHoursAgo {
  // Check if ad was loaded more than four hours ago.
  return [[NSDate Date] timeIntervalSinceDate:self.loadTime] < fourHoursInSeconds;
}

- (BOOL)isAdAvailable {
  // Check if ad exists and can be shown.
  return self.appOpenAd != nil && [self wasLoadTimeLessThanFourHoursAgo];
}

@end

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

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

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

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

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

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

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

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

Swift Objective-C

השלבים הבאים

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