Posts tagged with admob

I’m encountering an issue with app-ads.txt verification in Google AdMob. I selected 'Verify App' in 'App Verification'. Despite following all the steps and confirming that the file is properly set up, I keep getting the error: "We couldn't verify", along with the following message from Google AdMob:

"Your details don't match the information in your AdMob account."

Here’s what I’ve done so far:

app-ads.txt File Accessibility:

The app-ads.txt file is hosted at:

Visiting either of these links returns the app-ads.txt content successfully. I validated the file’s format using adstxt.guru, and it states that the file is formatted correctly.

Developer Website and App Store Integration: The app is published on the Apple App Store, and clicking the 'App Support' link from the app listing successfully navigates to the company website: https://www.theiafintech.com/

Guide Reviewed: I’ve carefully reviewed the AdMob instructions here. Everything appears to match the requirements, as the file is publicly accessible on both HTTP and HTTPS formats.

Issue: Despite the above, Google AdMob is unable to verify the app-ads.txt file, and I continually get the error message "We couldn't verify."

Request: Could someone help identify what might be going wrong? Are there additional steps or requirements (beyond those outlined in the guide) that I might be missing? I’d really appreciate any insights or suggestions.

Thank you for your help!

FYI: Here’s what I get after selecting 'Verify App':

I have implemented AdMob Server Side Verification How to verify Admob Rewarded Video Ad on a server?

Everytime the user finishes watcing a rewarded ad, Google Server Makes a GET call to my Server. I verify the signature, then store an entry to my database.

To my surprise, I noticed a discrepancy between the number of API calls recorded and the impression count on the AdMob Panel.

This results in lesser earning than what I actually reward my user.

Server Logs:

ad_reward_audit.dart:52:7) 2024-07-31 00:00:00.000Z: 2 ad_reward_audit.dart:52:7) 2024-08-01 00:00:00.000Z: 3 ad_reward_audit.dart:52:7) 2024-08-02 00:00:00.000Z: 1 ad_reward_audit.dart:52:7) 2024-08-03 00:00:00.000Z: 2 ad_reward_audit.dart:52:7) 2024-08-04 00:00:00.000Z: 35 ad_reward_audit.dart:52:7) 2024-08-06 00:00:00.000Z: 6 ad_reward_audit.dart:52:7) 2024-08-07 00:00:00.000Z: 3 ad_reward_audit.dart:52:7) 2024-08-08 00:00:00.000Z: 5 ad_reward_audit.dart:52:7) 2024-08-09 00:00:00.000Z: 36 ad_reward_audit.dart:52:7) 2024-08-10 00:00:00.000Z: 28 

AdMob Panel:

Am I wrong to think that the number of impression should match the number SSV API call ?

If it should be the case, what other steps can I do to investigate this ? I am making loss at the moment do this issue as my rewards to user actually cost me actual money (Computing time cost on expensive GPU)

I am trying to implement Google Ads into my flutter app. I closely followed the implementation guides but when I start the app even though it says the ad successfully loaded it does not show up. Sometimes it flashes up for a second but immediately disappears afterwords. Does anyone have an idea what could be the problem?

    loadAd() {     BannerAd banner = BannerAd(       adUnitId: adUnitId,       request: AdRequest(),       size: AdSize.banner,       listener: BannerAdListener(           // Called when an ad is successfully received.           onAdLoaded: (ad) {         debugPrint('$ad loaded.');         setState(() {           _isLoaded = true;         });       },           // Called when an ad request failed.           onAdFailedToLoad: (ad, err) {         debugPrint('BannerAd failed to load: $err');         // Dispose the ad here to free resources.         ad.dispose();       }, )     );     banner.load();     setState(() {       _bannerAd = banner;     });   } 
 Widget build(BuildContext context) {     return _isLoaded         ? Container()         : Container(           alignment: Alignment.center,           child: SizedBox(             height: AdSize.banner.height.toDouble(),             width: AdSize.banner.width.toDouble(),             child: AdWidget(               ad: _bannerAd!,             ),           ),         );   } 

What I am doing doing

  • I have the below code where the AD is Displaying
  • I am using google AD-Mob
  • AD is displaying fine

What I am trying to understand

  • onAdImpression() is not triggered when the view is rendered in the screen instead its triggered when I click the AD, GO to the designated AD and return back to the APP where the AD container is present
  • Is it supposed to work this way or onAdImpression() should be triggered as soon as the AD is rendered on the screen
@Composable fun BannerAdView(adUnitId: String) {     val context = LocalContext.current     val adView = remember { AdView(context) }          AndroidView(         factory = {             adView.apply {                 setAdSize(AdSize.BANNER)                 this.adUnitId = adUnitId                 adListener = object : AdListener() {                     override fun onAdLoaded() {                         // Called when an ad is loaded.                     }                     override fun onAdFailedToLoad(error: LoadAdError) {                         // Called when an ad fails to load.                     }                     override fun onAdOpened() {                         // Called when an ad opens an overlay that covers the screen.                     }                     override fun onAdClicked() {                         // Called when an ad is clicked.                     }                     override fun onAdClosed() {                         // Called when the user is about to return to the app after tapping on an ad.                     }                     override fun onAdImpression() {                         // Called when an ad impression is recorded.                         Log.d("AdImpression", "Ad impression recorded")                     }                 }                 loadAd(AdRequest.Builder().build())             }         },         update = {             it.loadAd(AdRequest.Builder().build())         }     ) } 

This is my Ad provider

import 'package:bg_remover/services/ads_helper.dart'; import 'package:flutter/material.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; class AdaptiveBannerAdProvider with ChangeNotifier{   BannerAd? _anchoredAdaptiveAd;   bool _isLoaded = false;   BannerAd? get anchoredAdaptiveAd => _anchoredAdaptiveAd;   bool get isAdLoaded => _isLoaded;   Future<void> loadAnchoredAdaptiveAd(BuildContext context) async {     final AnchoredAdaptiveBannerAdSize? size =         await AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(             MediaQuery.of(context).size.width.truncate());     if (size == null) {       debugPrint('Unable to get height of anchored banner.');       return;     }     _anchoredAdaptiveAd = BannerAd(       adUnitId: AdHelper.bannerAdUnitId,       size: size,       request: const AdRequest(),       listener: BannerAdListener(         onAdLoaded: (Ad ad) {           debugPrint('$ad has been >>>>>loaded: ${ad.responseInfo}');           //there was an error of @This AdWidget is already in the Widget tree@           // so for that we apply this widgetsBinding to notify listener           //and place the banner add in FutureBuilder and that's work           // WidgetsBinding.instance.addPostFrameCallback((_) {           //   _isLoaded = true;           //   notifyListeners();           // });           // Ad was not showing when loaded           _isLoaded = true;           notifyListeners();         },         onAdFailedToLoad: (Ad ad, LoadAdError error) {           debugPrint('Anchored adaptive banner failedToLoad: $error');           ad.dispose();         },       ),     );     return _anchoredAdaptiveAd!.load();   }   void disposeAd() {     _anchoredAdaptiveAd?.dispose();   } } 

call it here to display Ad:

 import 'package:bg_remover/utils/routes/routes_name.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:gap/gap.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; import 'package:provider/provider.dart'; import '../provider/ads_provider/adaptiveBanner_ad_provider.dart'; import '../utils/colors.dart'; import '../utils/images_assets_path.dart'; import '../utils/strings.dart'; import 'bottom_tabs/home_page.dart'; import 'bottom_tabs/project_page.dart'; import 'bottom_tabs/settings_page.dart'; class HomeFeedPage extends StatefulWidget{   const HomeFeedPage({Key? key}) : super(key: key);   @override   State<HomeFeedPage> createState() => _HomeFeedPageState(); } class _HomeFeedPageState extends State<HomeFeedPage>{   int index = 1;   final List<Widget> pages = const [     ProjectPage(),     HomePage(),     SettingsPage(),   ];   final List<String> icons = [     AssetImages.projectIcon,     AssetImages.inactiveHomeIcon,     AssetImages.settingsIcon,   ];   final List<String> titles = const [     Strings.projects,     Strings.home,     Strings.settings,   ];   void _onIconPressed(int newIndex) {     if (newIndex == 2) {       Navigator.pushNamed(context, RoutesName.settings);     } else {       setState(() {         index = newIndex;       });     }   }   @override   void didChangeDependencies() {     super.didChangeDependencies();     final adaptiveAdProvider =         Provider.of<AdaptiveBannerAdProvider>(context, listen: false);     adaptiveAdProvider.loadAnchoredAdaptiveAd(context);   }   @override   Widget build(BuildContext context) {     return Scaffold(       resizeToAvoidBottomInset: false,       body: Column(         children: [           Expanded(child: pages[index]),           displayAd(),           _buildBottomBar(),         ],       ),     );   }   Widget _buildBottomBar() {     return Container(       padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),       color: AppColors.bottomBarColor,       child: Row(         mainAxisAlignment: MainAxisAlignment.spaceAround,         children: List.generate(           icons.length,           (int i) => GestureDetector(             onTap: () => _onIconPressed(i),             child: _buildIconColumn(i),           ),         ),       ),     );   }   Widget _buildIconColumn(int i) {     final bool isActiveHome = index == 1 && i == 1;     final String iconPath = isActiveHome ? AssetImages.homeIcon : icons[i];     return Column(       children: [         AnimatedContainer(           duration: const Duration(milliseconds: 300),           width: 70,           height: 35,           decoration: BoxDecoration(             color: index == i ? AppColors.activeTabColor : Colors.transparent,             borderRadius: BorderRadius.circular(20),           ),           child: Padding(             padding: const EdgeInsets.all(8.0),             child: SvgPicture.asset(               iconPath,               colorFilter: ColorFilter.mode(                 index == i ? AppColors.whiteColor : AppColors.activeColor,                 BlendMode.srcIn,               ),             ),           ),         ),         const Gap(5),         Text(           titles[i],           style: TextStyle(             color: index == i ? AppColors.whiteColor : AppColors.activeColor,             fontWeight: index == i ? FontWeight.w700 : null,           ),         ),       ],     );   }   Widget displayAd() {     return Consumer<AdaptiveBannerAdProvider>(       builder: (context, adProvider, _) {         if (adProvider.isAdLoaded) {           return SizedBox(             width: adProvider.anchoredAdaptiveAd!.size.width.toDouble(),             height: adProvider.anchoredAdaptiveAd!.size.height.toDouble(),             child: AdWidget(ad: adProvider.anchoredAdaptiveAd!),           );         } else {           return Container(             color: AppColors.yellowColor,             width: adProvider.anchoredAdaptiveAd?.size.width.toDouble(),             height: adProvider.anchoredAdaptiveAd?.size.height.toDouble(),             child: Center(               child: Text(                 'Ad is Loading.......',                 style: TextStyle(color: AppColors.whiteColor),               ),             ),           );         }       },     );   }  verride   void dispose() {     Provider.of<AdaptiveBannerAdProvider>(context, listen: false).disposeAd();     super.dispose();   } }  @ 

working fine when I go to next having same process to display ad show error : Flutter :- This AdWidget is already in the Widget tree. How to disable this exception. And what does it mean?

Above Code is Working fine on HomeFeed Page. when I go to next having same process to display ad error : Flutter :- This AdWidget is already in the Widget tree. How to disable this exception. And what does it mean?