◉RORK LABJP
●EXPO — EAS Observe now records native crashes (Oct 7). On SDK 57, update to 57.0.21 or later●RORK — GPT-6.1 Sol (Sep 29) and Claude Sonnet 5.5 (Sep 28) are now in the model menu●RN 0.88 — The stable release was still unpublished on its Oct 12 target. rc.4 (Oct 7) is the newest; 0.87.1 is Latest●Q&A — Readers report expo-widgets showing a black widget in production builds only●WINDOWS — A walkthrough shows how to ship an iPhone app from Windows only, with no Mac●NEW — Three checks to run first when notifications stop arriving in Expo Go●EXPO — EAS Observe now records native crashes (Oct 7). On SDK 57, update to 57.0.21 or later●RORK — GPT-6.1 Sol (Sep 29) and Claude Sonnet 5.5 (Sep 28) are now in the model menu●RN 0.88 — The stable release was still unpublished on its Oct 12 target. rc.4 (Oct 7) is the newest; 0.87.1 is Latest●Q&A — Readers report expo-widgets showing a black widget in production builds only●WINDOWS — A walkthrough shows how to ship an iPhone app from Windows only, with no Mac●NEW — Three checks to run first when notifications stop arriving in Expo Go
Articles/Business
⟐ Business/2026-05-21Advanced

Putting AdMob Bidding into Production for a Rork App — Five Networks Bidding in Parallel, eCPM Trends, and Daily Operations

I moved the AdMob mediation layer of my Rork-generated apps from waterfall to bidding, with five ad networks bidding in parallel. Here are my real-world numbers after three weeks of production, the SDK pitfalls, and how I delegate daily monitoring to Claude in Chrome.

AdMob71BiddingMediation7Rork577eCPM5Indie Development26

✦ Premium Article

The morning I opened the AdMob dashboard and saw the bidding acceptance rate sitting near 100% across the day, I finally felt that the migration work was behind me. The Rork-generated apps I run had been moving from waterfall mediation to bidding for the past three weeks, and that day was the first one where the numbers looked stable.

I have been shipping mobile apps as an indie developer since 2014. Among everything that has shifted around AdMob, the move from waterfall (call networks in sequence) to bidding (have them bid in parallel) is one of the most meaningful changes for solo operators. On the surface it looks like a single checkbox in the AdMob console, but actually running it in production with several networks side by side took quite a bit of tuning across SDK setup, console configuration, and daily monitoring.

The migration covered six wallpaper apps. I had planned to move them one at a time, but a round of SDK updates landed across the whole catalog at once, and all six ended up going through the switch in parallel over three weeks. Running the same setup six times in a row turned out to be the useful part: it made very clear which steps snag every single time and which ones only ever bit me once.

What follows are the notes from that run. Starting from the Rork-generated baseline, I'll walk through what it takes to have AdMob plus five networks (AppLovin / Meta Audience Network / Unity Ads / Pangle / Liftoff) bid in parallel in production — the integration changes, the pitfalls that cost me the most time, the eCPM and fill rate shifts against the prior waterfall setup, and the daily monitoring loop I now run through Claude in Chrome.

Why I Moved off Waterfall — The Ceiling I Could Feel but Not Measure

With waterfall, AdMob queries networks in order of their declared eCPM floor. If I set AppLovin's floor at $2.00 and Unity Ads at $1.50, requests go to AppLovin first and fall through to Unity Ads only when AppLovin doesn't fill. It is a clean mental model, but in my apps it had two limits I kept bumping into.

The first one was that floor values are static, which means they cannot absorb variability across currency, hour of day, and audience composition. AppLovin tends to dominate during Japanese hours; Meta Audience Network shows up stronger during overseas hours. Watching the dashboards I could see the patterns, but adjusting floor values by hand to chase them is not realistic when you have six apps to maintain.

The second one was that unfilled-impression opportunity cost is hard to see. In the waterfall logs you can see "AppLovin didn't fill, so the request went to network 2," but you can't see "if all five networks had bid in parallel, what eCPM would the auction have produced?" Bidding shows you that number every time, because the auction actually happens.

In a bidding setup, AdMob sends a parallel bid request to all participating networks and instantly picks the highest bid that arrives inside the time window. The mechanism removes both limits above. Google has been steering publishers toward bidding in their docs as well, and the case for it is especially strong when you have multiple SDKs co-resident in the same app.

The final shape I landed on is a hybrid: one or two networks stay on the waterfall (because their adapter doesn't support bidding yet), and the five networks that do support bidding compete in parallel.

Separating the Code You Leave Alone from the Code You Touch

A Rork-generated app comes with a reasonable AdMob initialization scaffold. In my wallpaper apps I keep that initialization centralized in App.tsx, and I let all the mediation SDKs load as AdMob adapters rather than as direct SDKs. This keeps the code footprint small and matches what bidding wants.

I use Google's official react-native-google-mobile-ads package rather than the older Firebase wrapper. Bidding has strict requirements around SDK and adapter versions — get them wrong, and bidding will appear to be enabled in the console but never actually fill an impression.

# package.json dependencies
"react-native-google-mobile-ads": "^14.7.0",
"@react-native-async-storage/async-storage": "^1.23.1",

Adapters are picked up through EAS Build natively. In app.json I declare them like this:

{
  "plugins": [
    [
      "react-native-google-mobile-ads",
      {
        "androidAppId": "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX",
        "iosAppId": "ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX",
        "userTrackingUsageDescription": "Used to measure ad performance for the apps you enjoy.",
        "skAdNetworkItems": [
          "cstr6suwn9.skadnetwork",
          "4fzdc2evr5.skadnetwork",
          "ydx93a7ass.skadnetwork"
        ]
      }
    ]
  ]
}

Every network publishes the SKAdNetwork IDs it needs declared in Info.plist. AppLovin, Unity Ads, Pangle, Liftoff, and Meta Audience Network each have their own list, and I learned to enumerate all of them in skAdNetworkItems. Miss one, and on iOS you can see impressions in the console but the attribution silently breaks, which means the eCPM reports do not reflect actual revenue several days later.

The Rork-generated code itself I leave essentially intact. The three additions I make are: an initialization hook, environment-variable-based ad unit IDs, and an adjustment to where the App Tracking Transparency (ATT) prompt sits in the launch sequence.

// hooks/useAdMobInit.ts
import { useEffect } from "react";
import { Platform } from "react-native";
import mobileAds, { MaxAdContentRating } from "react-native-google-mobile-ads";
import { request, PERMISSIONS, RESULTS } from "react-native-permissions";
 
export const useAdMobInit = () => {
  useEffect(() => {
    const init = async () => {
      if (Platform.OS === "ios") {
        // Resolve ATT before initializing AdMob
        await request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY);
      }
      await mobileAds()
        .setRequestConfiguration({
          maxAdContentRating: MaxAdContentRating.PG,
          tagForChildDirectedTreatment: false,
          tagForUnderAgeOfConsent: false,
        })
        .then(() => mobileAds().initialize());
    };
    void init();
  }, []);
};

The detail that matters is resolving the ATT dialog before AdMob initializes. Reversing the order causes personalized ads to drop off on iOS 14.5+ devices and, in my measurements, takes 20–25% off the bidding eCPM. The same principle applied under waterfall, but the impact is larger now that bidding amplifies competition for ATT-authorized impressions.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Concrete SDK integration steps for AdMob Bidding alongside an existing waterfall setup, with the gotchas I hit on iOS and Android
✦Three weeks of measured eCPM, fill rate, and latency numbers across five networks (AppLovin / Meta Audience Network / Unity Ads / Pangle / Liftoff), plus how the auction wins actually split between them
✦A diagnostic order for telling apart a bid that never arrived, a bid that lost, and a win whose creative failed to load — plus the Claude in Chrome prompt I use for the morning rounds
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $15 for lifetime access
View Membership →

Related Articles

⟐ Business2026-09-06
Your Blended eCPM Dropped and Revenue Went Up: Splitting the Change Into Country Mix and Rate
Blended eCPM is a weighted average, not a price. Here is how I split a month-over-month change into a country-mix effect and a rate effect that reconcile exactly to the total, plus what to check before you cut a low-eCPM country.
⟐ Business2026-05-03
From Rork to $1,000/month with AdMob — A Practical Indie Developer's Monetization Playbook
How to take a Rork-built mobile app toward meaningful monthly AdMob revenue: category fit, getting the ATT-before-initialize order right, time-based interstitial pacing, judging by ARPDAU, app-ads.txt, and running a small portfolio.
⟐ Business2026-05-02
A Solo Developer's Strategy for Pushing a Mobile App Past ¥100k/Month — Real Revenue Tuning Tested on Rork-Built Apps
The hands-on strategy for breaking the ¥100k/month wall in solo mobile development. Ad eCPM optimization, IAP tuning, subscription retention, and ASO — every lever I've actually tested on Rork-built apps over 12 years of solo monetization, with code and numbers.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links