Same app, same users, native ads paid 38x more per 1,000 impressions than banners, and why I stopped short of deleting the banner units
Seven days of AdMob data from two TV remote apps, comparing revenue per 1,000 impressions for banners and native advanced ads. How over-exposure kills the rate, how to read native's low fill rate, and why I aborted deleting the banner ad units the next day.
I wanted to know how much the ad format alone changes revenue, so I compared two remote apps with the same kind of users over seven days. The gap was bigger than I expected.
The measurements
| App | Format | Impressions | Click-through | Revenue per 1,000 |
|---|---|---|---|---|
| Genie TV remote | Native advanced | 99 | 4.04% | $8.85 |
| Genie TV remote | Banner | 524 | 4.39% | $2.98 |
| U+TV remote | Banner | 11,645 | 0.24% | $0.23 |
Inside Genie TV alone, native pays 3x the banner. U+TV's banner against Genie TV's native is 38x.
Why the U+TV banner was worth $0.23
98.5% of U+TV's impressions were banners, and it was showing them 16 times a day per user. Genie TV's banner showed 0.8 times a day. Same format, click-through 4.39% versus 0.24%, an 18x difference, for that reason. A person who sees the same banner 16 times a day stops looking at it. Push impressions up and the rate comes down, so total revenue does not scale with impressions.
The lesson is not "make more impressions". The previous post said session time creates impressions, but if you inflate those impressions with banner refreshes, the rate takes it back. One banner view for the whole app, not a new one per screen. Creating one per screen resets the refresh timer every time, which adds impressions and subtracts rate.
Native's catch: fill rate
Switching everything to native is not the end of it either. Over the same period the show rate (impressions divided by matched requests) was 98% for banners and 21% for native. Native fills one request in five. The ad space is often empty.
So the verdict is total revenue, not impressions and not the rate. A 38x rate with one-fifth the fill is a much smaller real difference. I switch one app at a time, fix a re-measurement date in advance, and compare total revenue. As I write this, that date is 18 September. Nothing gets reverted before then.
Implementation notes
- When a native ad takes a banner's place, give the layout a fixed height and keep it
invisibleuntil loaded. Withwrap_contentthe screen jumps the moment the ad appears. - Put a hard cap on native load retries. Mine started as unlimited retries every 60 seconds, which is a pattern AdMob can flag as invalid traffic. Now it is 5 attempts with exponential backoff from 3 to 48 seconds.
- Do not reload in
onResume. Every screen change becomes a request, and that only cuts the rate.
Why I stopped short of deleting the banner units
The day after switching the code from banners to native, I went to clean up the banner ad units in the AdMob console. Before deleting, I pulled the previous seven days of revenue by format.
- B TV remote: banner $1.88, native $0.77
- U+TV remote: banner $3.29 (up 127% on the week), native $0.51
The code had moved to native, but most of the revenue was still coming from banners. Users who had not updated were still requesting ads with the old ad-unit IDs baked into the APK on their phones. Deleting the unit in the console would have zeroed those requests on the spot, and ad-unit deletion cannot be undone.
The ad unit in the console and the ID constant in the source are two different things. Removing it from the source leaves the ID alive in every installed APK, and the revenue keeps arriving. Before deleting a unit, look at its recent revenue and wait until old-version users have thinned out. This is one of the reasons I later put forced in-app updates into every app.
Summary
- Native advanced paid 3x the banner inside one app and 38x across apps, per 1,000 impressions.
- Sixteen banner impressions a day pushed click-through down to 0.24%. Inflated impressions get paid back in rate.
- Native fills 21%, so judge by total revenue only.
- Check revenue by format before deleting an ad unit. Old APKs are still earning on old IDs.