המדריך הזה מיועד לבעלי אפליקציות שמטמיעים מודעות בפתיחת אפליקציה.
מודעות בפתיחת אפליקציה הן פורמט מודעה מיוחד שמיועד לבעלי אפליקציות שרוצים לייצר הכנסות ממסכי הטעינה של האפליקציה שלהם. המשתמשים יכולים לסגור מודעות בפתיחת האפליקציה בכל שלב. מודעות בפתיחת אפליקציה יכולות להופיע כשמשתמשים מעבירים את האפליקציה שלכם לחזית.
מודעות בפתיחת האפליקציה מציגות באופן אוטומטי אזור מיתוג קטן כדי שהמשתמשים ידעו שהם באפליקציה שלכם. הנה דוגמה למודעה בפתיחת האפליקציה:
אלה השלבים הנדרשים להטמעה של מודעות בפתיחת אפליקציה:
- יוצרים מחלקה לניהול שמטעינה מודעה לפני שצריך להציג אותה.
- הצגת המודעה במהלך אירועים של העברת האפליקציה לחזית.
- טיפול בהחזרות (callbacks) של מצגות.
דרישות מוקדמות
- פועלים לפי הוראות ההגדרה במדריך לתחילת העבודה.
- לדעת איך להגדיר את המכשיר כמכשיר בדיקה.
תמיד כדאי לבצע בדיקות באמצעות מודעות בדיקה
כשמפתחים ובודקים אפליקציות, חשוב להשתמש במודעות בדיקה ולא במודעות פעילות שמוצגות למשתמשים. אם לא תעשו את זה, אנחנו עשויים להשעות את החשבון שלכם.
הדרך הכי קלה לטעון מודעות בדיקה היא להשתמש במזהה יחידת המודעות הייעודי לבדיקה של מודעות לפתיחת אפליקציה:
ca-app-pub-3940256099942544/5575463023
הוא הוגדר במיוחד להחזרת מודעות בדיקה לכל בקשה, ואתם יכולים להשתמש בו באפליקציות שלכם בזמן כתיבת קוד, בדיקה וניפוי באגים. חשוב להקפיד להחליף אותו במזהה יחידת המודעות שלכם לפני פרסום האפליקציה.
מידע נוסף על אופן הפעולה של מודעות בדיקה ב-Mobile Ads SDK זמין במאמר מודעות בדיקה.
הטמעה של מחלקה לניהול
המודעה צריכה להופיע במהירות, ולכן מומלץ לטעון אותה לפני שצריך להציג אותה. כך תהיה לכם מודעה מוכנה להצגה ברגע שהמשתמש ייכנס לאפליקציה. כדאי להטמיע מחלקה לניהול כדי לשלוח בקשות להצגת מודעות לפני שצריך להציג את המודעה.
יוצרים מחלקה חדשה מסוג Singleton בשם AppOpenAdManager
וממלאים אותה באופן הבא:
Swift
class AppOpenAdManager: NSObject {
var appOpenAd: AppOpenAd?
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 AppOpenAd.load(
with: "ca-app-pub-3940256099942544/5575463023", request: Request())
} 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:@"ca-app-pub-3940256099942544/5575463023"
request:[GADRequest 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(from: 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, FullScreenContentDelegate {
// ...
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 AppOpenAd.load(
with: "ca-app-pub-3940256099942544/5575463023", request: Request())
appOpenAd?.fullScreenContentDelegate = self
} catch {
print("App open ad failed to load with error: \(error.localizedDescription)")
}
isLoadingAd = false
}
// ...
// MARK: - FullScreenContentDelegate methods
func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
print("App open ad will be presented.")
}
func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
appOpenAd = nil
isShowingAd = false
// Reload an ad.
Task {
await loadAd()
}
}
func ad(
_ ad: FullScreenPresentingAd,
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:@"ca-app-pub-3940256099942544/5575463023"
request:[GADRequest 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, FullScreenContentDelegate {
var appOpenAd: AppOpenAd?
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 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)")
}
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:@"ca-app-pub-3940256099942544/5575463023"
request:[GADRequest 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
.