Skip to main content

Featured

Single Buy vs. Genuine Cluster

Insider buying alerts get treated as a single, uniform signal, but a single purchase and a genuine cluster of independent purchases carry very different informational weight — and the distinction is checkable in public filings well before it becomes a headline. The Surface Issue Stock-screening tools flag "insider buying" whenever any officer or director makes an open-market purchase, with no distinction between a routine, isolated transaction and a genuinely unusual pattern. That flattening is what makes the raw alert an unreliable signal on its own. The Structural Cause Insiders buy shares for reasons that often have nothing to do with a near-term view on the stock — personal financial planning, routine plan participation, diversification timing. A single purchase can't be distinguished from these ordinary reasons. Multiple, independent insiders buying within a short window is much harder to explain away as coincidence or routine planning. 144TICKJOURNAL · TR...

How to Add AdMob Ads to a Flutter App — What I Learned Building My First Monetized Mobile App

When I decided to make the NanoRich signal app free and support it through advertising, the logical choice was Google AdMob — Google's mobile advertising platform that works natively with Flutter. The concept is straightforward: you add code to your app that displays ads, Google fills those ad slots with content from its advertising network, and you earn a share of the revenue when users see or click the ads.


What's less straightforward is the actual implementation process. Getting from "I want to show ads" to "ads are showing correctly and revenue is appearing in my AdMob account" involves more steps than the documentation implies, and several of those steps have specific failure modes that aren't obvious until you hit them. This post covers the full process from account creation to live ads, including the mistakes I made along the way.


What AdMob Actually Is — For Non-Developers


AdMob is Google's advertising platform specifically for mobile apps. It sits between two groups: advertisers who want their ads shown inside mobile apps, and app developers who have users and want to earn money from them. Advertisers pay Google to show their ads. Google distributes those ads to apps through AdMob. Developers earn a share of what advertisers paid.


The amount you earn depends on three things: how many people use your app and see ads (impressions), how many people click on ads (clicks), and what advertisers are willing to pay for those interactions in your app's category. Financial apps tend to attract financial advertisers, who generally pay more per click than advertisers in lower-value categories. This is one reason the NanoRich app's advertising revenue potential is better than it would be for, say, a casual game — the audience and the advertising context are both financially oriented, which attracts higher-paying advertisers.


There are three main ad types in AdMob, each suited to different parts of an app:


Banner ads are small rectangular ads that sit at the top or bottom of the screen and remain visible while the user is using the app. They're the least intrusive ad type and typically earn less per view than other formats, but they earn continuously as long as the app is open.


Interstitial ads are full-screen ads that appear at natural transition points — when a user opens the app, when they navigate between screens, or when they complete an action. They're more prominent and earn more per impression, but showing them too frequently creates a poor user experience that drives users away.


Rewarded ads show users an ad in exchange for some in-app benefit — extra features, premium content, or similar. For the NanoRich app, rewarded ads weren't the right fit because there's no in-app benefit structure to offer, but they're worth mentioning for completeness.


For the NanoRich app, I chose banner ads on the main signal display screen and a single interstitial ad on app launch. This combination keeps the monetization present without overwhelming the trading signal content that's the reason users have the app in the first place.


Setting Up the AdMob Account


Before any code can be written, an AdMob account needs to be created and connected to the app. This happens at admob.google.com. The process involves creating a Google account (or using an existing one), registering the app in the AdMob interface, and receiving an App ID — a unique identifier that connects your code to your AdMob account.


The AdMob interface asks for the app's name and whether it's already available in an app store. For an app still in development, you indicate that it's not yet published. AdMob will still create the account and provide test ad units, which is what you use during development. Using real production ad units during development is explicitly against AdMob's terms — clicking your own ads or generating artificial impressions can result in account suspension — so test ad units exist specifically to let you develop and test without those risks.


Once the account is created, you create ad units for each ad format you plan to use. An ad unit is essentially a specific ad slot in your app — the banner at the bottom of the main screen is one ad unit; the interstitial on launch is another. Each ad unit gets its own ID, which is what you reference in your code.


Adding AdMob to the Flutter Project


Flutter has an official AdMob package called google_mobile_ads, maintained by Google. Adding it to the project involves declaring it as a dependency, running the package installation command, and then adding the AdMob App ID to the Android configuration files.


The App ID needs to be added to the AndroidManifest.xml file — a configuration file that Android uses to understand what the app is and what permissions it needs. The specific addition is a metadata entry inside the application tag:


<meta-data

  android:name="com.google.android.gms.ads.APPLICATION_ID"

  android:value="ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX"/>


The value is the App ID from the AdMob console, not an ad unit ID. Getting these two types of IDs confused is one of the most common early mistakes — the App ID goes in the manifest, while ad unit IDs are referenced in the Dart code.


Initialization happens in the app's startup code, after Firebase is initialized:


await MobileAds.instance.initialize();


This line loads the AdMob SDK and prepares it to serve ads. It needs to complete before any ad widgets are displayed, which is why it belongs in the startup sequence alongside Firebase initialization.


Displaying a Banner Ad


A banner ad in Flutter is displayed using the BannerAd class from the google_mobile_ads package. The basic implementation involves creating an ad object, loading it, and then displaying it in a widget.


The ad unit ID used during development is a test ID provided by Google specifically for this purpose — something like ca-app-pub-3940256099942544/6300978111 for Android banners. When the app is published and ready for production, this test ID gets replaced with the real ad unit ID from the AdMob console.


The most reliable way to display a banner ad at the bottom of a screen is to use a Stack widget that overlays the ad on top of the main content, positioned at the bottom. This keeps the signal display cards visible while the ad sits in a fixed position below them. Alternatively, a Column with the ad below the main content list works, but requires careful handling of the available screen height to prevent the content from being cut off when the ad loads.


One important behavior to understand about banner ads: they are not instant. When the code requests a banner ad, AdMob sends a request to its network, which finds an appropriate ad for the user, and then returns it to the app. This process typically takes one to three seconds. During this time, the app needs to handle the empty space gracefully — either showing nothing in the ad position until the ad loads, or showing a placeholder. The NanoRich app shows nothing until the ad loads, which avoids a jarring layout jump when the ad appears.


Displaying an Interstitial Ad


Interstitial ads require slightly different handling because they cover the entire screen. The pattern is to preload the ad before you need it — during app startup, before the user has navigated to where the ad will be shown — and then display it at the appropriate moment.


For the NanoRich app, the interstitial is preloaded during the splash screen and then shown once when the user first reaches the main signal display. This sequence ensures the ad is ready to show immediately rather than having the user wait for it to load at the moment of display.


The production policy for interstitials requires showing them only at natural breaks in the user experience. Showing an interstitial in the middle of a user's active task — like while they're reading a signal card — violates AdMob's policies and creates a poor user experience that reduces the app's effectiveness at retaining users long enough to see the ad in the first place.


The Mistake That Delayed My AdMob Approval


Getting AdMob ads working in development with test ad units was straightforward. Getting the live production ads approved took longer than expected because of a step I had skipped.


AdMob requires that apps displaying ads include a privacy disclosure that informs users about data collection for advertising purposes. For apps distributed in Europe and several other regions, this disclosure needs to take the form of a formal consent dialog under Google's User Messaging Platform (UMP). Without this consent implementation, AdMob will serve limited ads or no ads to users in those regions — and in some cases can flag the account for policy review.


The UMP implementation adds a consent dialog on first launch — the kind of "this app uses cookies and personalized advertising" prompt that appears in most apps. For markets outside Europe, this step is less critical, but implementing it correctly ensures the app complies with AdMob's global policies and prevents revenue loss from restricted ad serving in regulated markets.


Adding UMP added about a day of development work I hadn't budgeted for. The google_mobile_ads package includes UMP support, but setting it up requires additional configuration in the AdMob console and additional code in the app's startup sequence. The documentation for this part of the setup is more scattered than the core AdMob documentation, which is why it caught me off guard.


Today's Investing Insight — How Mobile Advertising Revenue Works


Mobile advertising revenue is calculated primarily through two metrics: CPM (Cost Per Mille, meaning cost per thousand impressions) and CPC (Cost Per Click). CPM-based ads pay a fixed rate for every thousand times the ad is shown, regardless of whether anyone clicks. CPC-based ads pay only when a user clicks the ad. In practice, most mobile ad networks use a hybrid approach where the ad that will generate the most revenue in a given slot is selected dynamically from a pool of available ads. Financial apps tend to attract both CPM and CPC advertisers, with CPC rates particularly high because a single click from a financially active user is worth more to an advertiser than a click from a user with no demonstrated financial interest. AdSense on the web and AdMob in apps operate on the same fundamental principles but with different rate structures — mobile ads in financial content categories typically generate meaningful revenue once an app has several hundred daily active users.


---


This post documents a personal journey of building and monetizing a mobile application and is not a recommendation of any specific advertising platform or revenue strategy. AdMob policies and revenue rates are subject to change. All investment decisions and their outcomes are the sole responsibility of the investor.

Comments