invertase / react-native-google-mobile-ads

React Native Google Mobile Ads enables you to monetize your app with AdMob.
https://docs.page/invertase/react-native-google-mobile-ads
Other
686 stars 139 forks source link

Investigate iOS rewarded ad no-fill errors in example app #109

Closed mikehardy closed 1 year ago

mikehardy commented 2 years ago

I asked the SDK forum about iOS rewarded ad no-fills: https://groups.google.com/g/google-admob-ads-sdk/c/5ixRSHOkhHE

Originally posted by @mikehardy in https://github.com/invertase/react-native-google-mobile-ads/issues/108#issuecomment-1093381741

mikehardy commented 2 years ago

Okay, this was the response from the forum:

Hi Mike,

Thank you for reaching out to us.

I've checked our test ad unit for rewarded ads in our Sample App iOS, and I was able to get ads on it. It means that this has something to do in your implementation. Since your implementation is react native, I would suggest reaching out to their support team as we only support implementation for Android, iOS, Unity and Flutter.

Regards, Google Logo
Princess Pamela Mobile Ads SDK Team

Which is great! I mean, it means our iOS rewarded ad implementation is a problem but a) we could see it! our example app was sufficient to detect the issue, that's a good result and b) it's working in other integrations so not ours, meaning the problem is localized here.

Something is wrong in our rewarded ads implementation for iOS, and it doesn't appear to be the native SDK or the ad unit ID.

So we have a valid test rig to see failure, and we are in control of the issue in our code.

This just needs internal triage + dev effort now if anyone has time to pick it up

mikehardy commented 2 years ago

@wjaykim you mentioned that trying to load two rewarded ads at once could cause problems (in #135) - I wonder if that could be the problem in the example app? What's strange is it works for android but not for iOS (the opposite of #135). This one seems strange since it did not reproduce for the support team on a pure native app, it works on android, and I swear I see an "advertisement amount of data traffic" (vague but trust me) download when I enter the rewarded ads hook implementation for instance, and it loads one. But on ad inspector it says no-fill :thinking:

wjaykim commented 2 years ago

In #135, the problem was creating ad instance again;

trying to load two rewarded ads at once

So this is not the problem, maybe

wjaykim commented 2 years ago

But in my local environment, rewarded ad in example app works both in Android and iOS 🤔

mikehardy commented 2 years ago

Hahah - of course it does. Couldn't be a reproducible problem, that would be too easy ;-). I'll examine it from an environment difference angle though, simply knowing it works for you is really helpful. Any information you can give on what you used (say, react-native info or similar) might help

wjaykim commented 2 years ago

Sure, here it is,

System:
    OS: macOS 12.3.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 5.39 GB / 32.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 16.14.2 - ~/.nvm/versions/node/v16.14.2/bin/node
    Yarn: 1.22.15 - ~/.nvm/versions/node/v16.14.2/bin/yarn
    npm: 8.7.0 - ~/Documents/JS/react-native-google-mobile-ads/node_modules/.bin/npm
    Watchman: 2022.03.21.00 - /opt/homebrew/bin/watchman
  Managers:
    CocoaPods: 1.11.3 - /opt/homebrew/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 15.4, macOS 12.3, tvOS 15.4, watchOS 8.5
    Android SDK: Not Found
  IDEs:
    Android Studio: 2021.1 AI-211.7628.21.2111.8309675
    Xcode: 13.3.1/13E500a - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.14.1 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.2 => 17.0.2 
    react-native: 0.68.1 => 0.68.1 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found
parasdaryanani commented 2 years ago

I've got the same issue as @wjaykim - rewarded ads load fine in dev and release mode for android, but only work in dev for ios. Tried a couple of workarounds but can't get it to work in the release app. Will the PR that's in progress resolve this issue?

mikehardy commented 2 years ago

@parasdaryanani with apologies - I do not think the PR in progress - if you mean #167 - will affect this. The only connection to #167 was that during testing I noted that I personally am unable to load rewarded ads on iOS at all (even in dev mode!) but that it was not a regression, I cannot load rewarded ads for iOS now, I have not been able to in the past, and I still cannot with #167 under test.

parasdaryanani commented 2 years ago

@wjaykim Have you had any luck working around this one? I've had to pull an app from production because of this unfortunately.

DoctorJohn commented 2 years ago

I have set some time aside to investigate this issue this weekend. Feel free to share any information you found during debugging @parasdaryanani, could potentially save me a lot of time since my setup is not ideal to debug this issue (I don't have a Mac, need to use workarounds).

mikehardy commented 2 years ago

@DoctorJohn if you haven't seen it - https://github.com/kholia/OSX-KVM

I usually have a few up at a time (it's only constrained by RAM for the most part), looks like this:

image

I use visual studio code on my ubuntu host system to remote-ssh in to the OSX-KVMs and it works pretty well. YMMV of course

Sincere best of luck figuring out what's going on! I've got work deadlines all next week so will probably be online a fair bit on the weekend if you're just blocked on something

DoctorJohn commented 2 years ago

Thanks Mike! I'm aware of OSX-KVM. So far I didn't think about using the vscode remote-ssh feature though. That could make things a lot more confortable. So thanks for that tip and the offer to help.

mikehardy commented 2 years ago

Without vscode remote-ssh it would be a non-starter in my opinion (likely shared, based on your comment). With it, the setup is definitely my daily driver. I have 3 up and running at most times, to work on different projects (or different branches in same project) without time spent context-switching between projects. Probably 3 years like this. Fiddly to set up and get them booted and running well but once on and running stable indefinitely

DoctorJohn commented 2 years ago

I actually spent multiple hours investigating this issue last weekend. However, the results are slightly underwhelming. Here is what I did:

1. Validate ads are not loading in our example app

I started by confirming that rewarded ads don't load in my setup with the react-native-google-mobile-ads example app. They don't. The following is logged in the console:

LOG  ios rewarded interstitial ad event: error
LOG  ios rewarded interstitial error: [googleMobileAds/no-fill] Request Error: No ad to show.
LOG  ios rewarded ad event: error
LOG  ios rewarded error: [googleMobileAds/no-fill] Request Error: No ad to show.

Here is what the ad inspector had to say:

When I turn on single ad source test:

image

2. Compared our code to the official examples

I continued comparing our code to the official documentation and the official example app. Luckily/Unfortunately I didn't really (check "Other findings" further down) find any issues here.

3. Checked whether ads load in the official example app

Checked whether rewarded ads load in the official example app. They don't. Interesting. All other ad types work as expected.

The xcode logs report:

Rewarded ad failed to load with error: Request Error: No ad to show

The logs also warn:

To get test ads on this device, set:
Objective-C
    GADMobileAds.sharedInstance.requestConfiguration.testDeviceIdentifiers = @[ GADSimulatorID ];
Swift
    GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = [ GADSimulatorID ]

So I added the suggested code. The warning went away, still no ads to show though.

4. Checked whether ads load in the official flutter example app

Checked whether our flutter friends get any special treatment by running the official flutter example app. Rewarded ads don't load there either. All other ad types work as expected.

That's what their console logs:

flutter: RewardedAd failed to load: LoadAdError(code: 1, domain: com.google.admob, message: Request Error: No ad to show., responseInfo: ResponseInfo(responseId: NlceY9CaIYCg7_UPzN-CkAM, mediationAdapterClassName: null, adapterResponses: [AdapterResponseInfo(adapterClassName: GADMAdapterGoogleAdMobAds, latencyMillis: 2980), description: {
    AdUnitMapping =     {
        "campaign_id" = 1057492276;
        pubid = "ca-app-pub-3940256099942544/1712485313/cak=no_cache&cadc=7d&caqid=NlceY9DHIKmy9u8Pt6GFmAg";
    };
    Error = "Error Domain=com.google.admob Code=5 \"Request Error: The Google ad request was unable to be fulfilled before a timeout occurred.\" UserInfo={NSLocalizedDescription=Request Error: The Google ad request was unable to be fulfilled before a timeout occurred.}";
    Latency = "2.98";
    Network = GADMAdapterGoogleAdMobAds;
}, adUnitMapping: {pubid: ca-app-pub-3940256099942544/1712485313/cak=no_cache&cadc=7d&caqid=NlceY9DHIKmy9u8Pt6GFmAg, campaign_id: 1057492276}, adError: AdE<…>

My setup (using OSX-KVM):

System:
    OS: macOS 12.5.1
    CPU: (8) x64 Intel Core 2 Duo P9xxx (Penryn Class Core 2)
    Memory: 44.92 MB / 4.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.8.0 - /var/folders/_5/z62cpbj13md90cw362b32sfc0000gn/T/yarn--1662931012332-0.5539745813245331/node
    Yarn: 1.22.19 - /var/folders/_5/z62cpbj13md90cw362b32sfc0000gn/T/yarn--1662931012332-0.5539745813245331/yarn
    npm: 8.18.0 - /usr/local/bin/npm
    Watchman: 2022.08.29.00 - /usr/local/bin/watchman
  Managers:
    CocoaPods: 1.11.3 - /Users/developer/.gem/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 21.4, iOS 15.5, macOS 12.3, tvOS 15.4, watchOS 8.5
    Android SDK: Not Found
  IDEs:
    Android Studio: Not Found
    Xcode: 13.4.1/13F100 - /usr/bin/xcodebuild
  Languages:
    Java: Not Found
  npmPackages:
    @react-native-community/cli: Not Found
    react: 17.0.2 => 17.0.2 
    react-native: 0.68.1 => 0.68.1 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found

Next steps

We should check whether rewarded ads load with real ad ids in an app that already has been released to the Apple App Store and which is linked to admob. (Currently can't do that myself, maybe in a month or so).

I also tried swapping in my iOS admob app and ad ids. Got the same results. However, my app and ad ids were freshly created the day I did the testing. Should try again, now that they have been around a little longer.

I'm curious whether this issue has something to do with my and Mikes setup (OSX-KVM).

Other findings

The admob iOS quick start guide suggests adding a SKAdNetworkItems array to the info.plist file. As far as I can tell we don't do that in our example app. However, my test results didn't change after adding said array to the example app.

Our App Transport Security setup also slighty differs from the official docs. Again, adjusting these in our example apps info.plist didn't make any difference.

The googleads-mobile-flutter package has more detailed errors about ad loading errors in the console. They do that by adding ad response infos to their errors. We don't really need to add that to our implementation since I noticed the ad inspector gives us about as much information. Still here is their implementation in case someone is curious and wants to add something similar to assist further investigations of this or similar issues:

https://github.com/googleads/googleads-mobile-flutter/blob/bdcc9df9e69c87fb22ee50998121ef48811cf3c8/packages/google_mobile_ads/ios/Classes/FLTAdInstanceManager_Internal.m#L92-L99

https://github.com/googleads/googleads-mobile-flutter/blob/bdcc9df9e69c87fb22ee50998121ef48811cf3c8/packages/google_mobile_ads/ios/Classes/FLTAd_Internal.m#L277-L294

https://github.com/googleads/googleads-mobile-flutter/blob/bdcc9df9e69c87fb22ee50998121ef48811cf3c8/packages/google_mobile_ads/ios/Classes/FLTAd_Internal.m#L230-L249

github-actions[bot] commented 1 year ago

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

parasdaryanani commented 1 year ago

Apologies for not responding to the previous comments sooner.

Firstly @DoctorJohn, thanks so much for your efforts in debugging. From what I've seen, this is not a bug.

I found out that ads will not in release mode for iOS apps until the app satisfies both of the following conditions:

  1. The app is published to the app store
  2. The admob app ID is approved by Google for this app.

Bit of a chicken and egg problem:

In my app, users can either subscribe to a paid plan or watch an ad to continue. In order to get through app approval without working ads, I hid the "watch an ad" button in case ads were not loaded or filled, as follows:


const [adsAdapterState, setAdsAdapterState] = useState(0);

const {
    adLoadedError,
    setAdLoadedError,
    isLoaded,
    isClosed,
    error,
    load,
    show,
  } = useGoogleRewardedAd();

useEffect(() => {
  mobileAds()
    .initialize()
    .then(adapterStatuses => {
      if (adapterStatuses && adapterStatuses[0].state) {
        setAdsAdapterState(adapterStatuses[0].state)
      }
    });
},[])

return (
  <> 
  {isLoaded &&
    !error &&
    !adLoadedError &&
    adsAdapterState && (
      <ContinueWithAdButton onPress={handleShowAd} />
    )}
  </>
)

Shortly after the app was published in the app store, I was able to go to Admob, select the published app and get the admob ID approved. For the short period between app approval and admob ID approval, users could only use paid subscriptions to use the app. Annoying, though it was a one-time issue at first release.

I hope this helps @novirusallowed