Ads placed in ListView is getting impression before they appear on the screen in Flutter 3
See original GitHub issueHi, I originally posted this here https://github.com/googleads/googleads-mobile-flutter/issues/269#issuecomment-1059741368, before the new Android PlatformView implementation was merged with the stable channel, but this issue is now in Flutter 3 stable channel.
With the new Android PlatformView implementation, banner placed in ListView
is getting impression before it appears on the screen.
This conflicts with Admob policy. (https://support.google.com/admob/answer/3269069?hl=en)
In the previous version, getting impression only when the first pixel of banner is seen on the screen.
This is a critical issue, apps using this plugin with Flutter 3 can be banned by Admob, because technically you are creating fake impressions with this implementation.
Steps to Reproduce
To reproduce, try this example code with Flutter 3, plugin version doesn’t matter.
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: 15,
itemBuilder: (context, index) {
if (index != 0 && index % 5 == 0) {
return const _BannerAd();
}
return Container(
height: 200,
color: Color((Random().nextDouble() * 0xFFFFFF).toInt())
.withOpacity(1),
);
},
),
);
}
}
class _BannerAd extends StatefulWidget {
const _BannerAd({Key? key}) : super(key: key);
@override
_BannerAdState createState() => _BannerAdState();
}
class _BannerAdState extends State<_BannerAd>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
late BannerAd myBanner;
@override
void initState() {
super.initState();
myBanner = BannerAd(
adUnitId: BannerAd.testAdUnitId,
size: AdSize.banner,
request: const AdRequest(),
listener: BannerAdListener(
onAdLoaded: (ad) => print('Ad loaded.'),
onAdFailedToLoad: (ad, error) {
ad.dispose();
print('Ad failed to load .');
},
onAdOpened: (ad) => print('Ad opened.'),
onAdClosed: (ad) => print('Ad closed.'),
onAdImpression: (ad) => print('Ad impression.'),
),
)..load();
}
@override
void dispose() {
myBanner.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
super.build(context);
return Container(
width: myBanner.size.width.toDouble(),
height: myBanner.size.height.toDouble(),
margin: const EdgeInsets.all(20),
alignment: Alignment.center,
child: AdWidget(ad: myBanner),
);
}
}
Expected results: Ads placed in the ListView should get impression when they appear on the screen.
Actual results: All ads in ListView are simultaneously get impression when the ListView is built.
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:21
Top GitHub Comments
I think because of this bug I got suspension for the last 7 months (I’ve migrated to facebook audience network)
Unfortunatelly, google admob, do not have a support to contact to resolve it (yes, I’m trying to reach contact for 7 months)
Error when try to contact on https://support.google.com/admob/gethelp:
Google forum thread that I’ve created, and have many others peoples complaining: https://groups.google.com/g/google-admob-ads-sdk/c/NCshQ7Fh46w/m/MI2p3ULMBwAJ
@bparrishMines I did some more testing and have confirmed that https://github.com/bparrishMines/flutter/tree/current_engine_main fixes the issue. You can also verify by checking out https://github.com/jjliu15/googleads-mobile-flutter-1/tree/impression_bug and running the example app.
After removing the visibility workaround and using
flutter:stable
the current behavior is:BannerAd
uses aloaded
impression definition, so it should not be used for testing this issueAdManagerBannerAd
andNativeAd
into view, you’ll see that their impressions are fired about half a screen before they are actually visibleAfter removing the visibility workaround and using https://github.com/bparrishMines/flutter/tree/current_engine_main, the impressions occur when the ad views are scrolled into view.