Issue
I'm using Capacitor Community AdMob (v5.3.1) to display banner and interstitial ads on an Android and IOS app. I'm using Angular with the Ionic Framework - codebase is the same except for the 'native' things like Info.plist for IOS.
I set up both my iPhone and Android phone as test devices on AdMob, so I can display real ads (but in test mode). The ads display fine on the Android phone, but do not work on the iPhone. I keep getting the error "No ad to show." when trying to display iPhone ads. I treble checked that I set up the correct IDFA in AdMob for the iPhone. I'm getting the IDFA using the 'My Device Identifiers' app. That app also gives me an IDFV, but I think the IDFA is the correct ID to use.
My AdMob account doesn't seem to have any restrictions. This is supported by the fact that it's serving the ads for Android fine.
I am able to display demo ad units fine on both iPhone and Android. I also found that I was able to display test ads if I add the iPhone as a test device during the AdMob.initialize step, using the device ID displayed in the Logcat message which looks like:
2023-12-03 21:08:15.779400+0000 MyTestApp[1707:99269] <Google> To get test ads on this device, set:
Objective-C
GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = @[ @"770185167e05233828007f06c16a1211" ];
This is my initialize method:
AdMob.initialize({
testingDevices: environment.testingDevices,
initializeForTesting: true,
});
I'm using an environment varible to store the test device IDs:
testingDevices: ['770185167e05233828007f06c16a1211','1E80E3909C199A8778EBFB88E5F9DA71']
If I use the AdMob.initialize method to programmatically add the test devices, the IPhone test ads display OK. The problem of course with using the testDeviceIdentifier in Logcat is that it changes for each fresh install of the app, which is why I'd like to simply register the iPhone as a test device on AdMob, and have an empty AdMob.initialize.
I'm stumped as to why it works fine for the Android device but not for the iPhone. Is there something 'extra' that is needed for the iPhone for it to work as a test device, without it needing to be registered programmatically in AdMob.initialize?
I already found a few posts that suggested I just need to wait for a few hours for the iPhone ads to display, but this has been going on for 2 weeks now so I don't think it's a timing/waiting thing. Also - the ads work fine if the iPhone is added programmatically as mentioned, so I don't believe it's an issue with the AdMob account.
Here is my Info.plist file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>MyTestApp</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-7752708518900938~4403450338</string>
<key>GADIsAdManagerApp</key>
<true/>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSUserTrackingUsageDescription</key>
<string>[Why you use NSUserTracking. ex: This identifier will be used to deliver personalized ads to you.]</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
</dict>
</plist>
This is my advert component which manages the ads:
import { Component, OnInit } from '@angular/core';
import { Platform } from '@ionic/angular';
import { isPlatform } from "@ionic/angular";
//Capacitor AdMob plugin
import { AdMob, AdLoadInfo, BannerAdOptions, BannerAdSize, BannerAdPosition, BannerAdPluginEvents, AdMobBannerSize, AdOptions, InterstitialAdPluginEvents, AdMobError } from '@capacitor-community/admob';
import { environment } from 'src/environments/environment';
@Component({
selector: 'app-advert',
templateUrl: './advert.component.html',
styleUrls: ['./advert.component.scss'],
})
export class AdvertComponent implements OnInit {
constructor(
private platform: Platform) {
//init Ads
this.initializeAds();
}
failedToLoadBannerAd: boolean = false;
failedToLoadInterstitialAd: boolean = false;
//delay for displaying ad banners
bannerDelay : number = 5000;
//delay for prepping ads (e.g. interstitial)
prepAdsDelay : number = 5000;
ngOnInit() {}
async initializeAds() {
const { status } = await AdMob.trackingAuthorizationStatus();
if (status === 'notDetermined') {
/**
*
* If you want to explain TrackingAuthorization before showing the iOS dialog,
* you can show the modal here.
* ex)
* const modal = await this.modalCtrl.create({
* component: RequestTrackingPage,
* });
* await modal.present();
* await modal.onDidDismiss(); // Wait for close modal
**/
}
AdMob.initialize({
testingDevices: environment.testingDevices,
initializeForTesting: true,
});
AdMob.addListener(BannerAdPluginEvents.FailedToLoad, (error: AdMobError) => {
this.failedToLoadBannerAd = true;
});
AdMob.addListener(InterstitialAdPluginEvents.FailedToLoad, (error: AdMobError) => {
this.failedToLoadInterstitialAd = true;
});
AdMob.addListener(InterstitialAdPluginEvents.Loaded, (info: AdLoadInfo) => {
//console.log(`Ad loaded info: ${info}`);
});
//listener for interstit dismissed event
AdMob.addListener(InterstitialAdPluginEvents.Dismissed, () => {
this.prepInterstitialAd();
});
this.prepInterstitialAd();
this.displayBannerAd();
}
//resets the 'failed to load ads' flags, so we can try to load again
resetFailed(){
this.failedToLoadBannerAd = false;
this.failedToLoadInterstitialAd = false;
//prep interstitial again
this.prepInterstitialAd();
}
async showBanner()
{
const adId = isPlatform('ios') ? environment.iosBannerAdId : environment.androidBannerAdId;
const options: BannerAdOptions = {
adId: adId,
adSize: BannerAdSize.ADAPTIVE_BANNER,
position: BannerAdPosition.BOTTOM_CENTER,
margin: 0,
isTesting: false
// npa: true
};
await AdMob.showBanner(options);
}
async hideBanner()
{
await AdMob.hideBanner();
}
async showInterstitial()
{
await AdMob.removeBanner();
await AdMob.showInterstitial();
}
async prepInterstitialAd() {
const adId = isPlatform('ios') ? environment.iosInterstitialVideoAdId : environment.androidInterstitialVideoAdId;
const options: AdOptions = {
adId: adId,
isTesting: false
}
await AdMob.prepareInterstitial(options);
}
displayBannerAd(){
setTimeout(() => {
this.showBanner();
}, this.bannerDelay);
}
prepAds() {
setTimeout(() => {
this.prepInterstitialAd();
}, this.prepAdsDelay);
}
}
Solution
I figured out the problem. My IOS phone was set up as a test device on AdMob. But I wasn't implementing the ATT (App Transparency Tracking) for IOS correctly. So when I was requesting ads, Admob wasn't getting the phone's Advertising ID/IDFA. So it didn't know it was a test device, and therefore, no ads were displayed.
As soon as I implemented ATT correctly, and clicked 'Allow' on the ATT popup to allow tracking of the phone's IDFA, everything kicked in and the test ads now display properly.
If you uninstall and reinstall the app to reset ATT, and click 'Ask App Not to Track' option in the ATT dialog, Admob doesn't get the phone's IDFA, and it doesn't display ads any more.
This is expected behaviour, and once the app goes into production, and production ads are enabled, everything should hopefully work correctly.
Answered By - VincentH
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.