Skip to main content

How to Switch Meta Audience Network from Waterfall to Bidding

 If your Meta Audience Network (MAN) revenue has plummeted or your fill rates have flatlined to 0%, you are likely a casualty of Meta’s deprecation of waterfall mediation. Meta has aggressively shifted to a "Bidding Only" model, rendering traditional eCPM floor setups obsolete.

For AdOps specialists and developers, this isn't just a configuration tweak; it is a fundamental architectural change in how ad requests are authenticated and auctioned.

This guide provides the specific technical steps to migrate from Waterfall to Partner Bidding within AdMob and AppLovin MAX, ensuring your implementation handles the required Real-Time Bidding (RTB) signals correctly.

The Root Cause: Why Waterfall Failed

To fix the issue, you must understand the mechanism failing under the hood.

In a Waterfall setup, your mediation platform (AdMob/MAX) called network adapters sequentially based on historical eCPM. When it called Meta, it requested an ad with a hardcoded placement ID. Meta checked if it had inventory above that price floor and responded.

In Bidding (RTB), the process is parallel and token-based.

  1. The Mediation SDK requests a secure, time-limited bidder token from the installed Meta SDK on the device.
  2. This token is passed to the mediation server (Google or AppLovin).
  3. The mediation server sends the token to Meta's bidding endpoint server-to-server.
  4. Meta decrypts the token (containing user targeting data) and returns a bid price in real-time.

The Error: If you are still using a Waterfall placement ID, or if your mediation adapter is too old to generate the bidder token, Meta rejects the request immediately. There is no fallback.

Phase 1: Meta Business Manager Configuration

Before touching code or the mediation dashboards, you must generate a System User Access Token. Unlike waterfall IDs, bidding requires server-side authentication between your mediation provider and Meta.

  1. Log in to Meta Business Suite.
  2. Navigate to Business Settings > Users > System Users.
  3. Click Add to create a new System User (name it "Mediation Bidding").
  4. Assign the Role as Admin.
  5. Click Generate New Token.
  6. Crucial Scope Selection: You must select read_audience_network_insights and manage_audience_network.
  7. Copy this token. It is required for both AdMob and MAX.

Note: Ensure the token is set to "Never Expire" or you will face a catastrophic revenue drop when it lapses.

Phase 2: Mediation Platform Setup

Scenario A: Google AdMob

AdMob refers to this as "Partner Bidding."

  1. Go to AdMob Dashboard > Mediation.
  2. Select your Mediation Group.
  3. Remove any existing Meta Audience Network entries from the "Waterfall" section.
  4. Under Bidding, click Add Bid Source.
  5. Select Meta Audience Network.
  6. You will be prompted to map your units. Enter the System User Access Token you generated in Phase 1.
  7. Map your AdMob Ad Unit ID to the Placement ID from the Meta Monetization Manager.
    • Tip: Meta recommends creating NEW Placement IDs specifically flagged for "Bidding" rather than reusing waterfall IDs to prevent algorithm confusion.

Scenario B: AppLovin MAX

MAX is a unified auction, but Meta requires specific network enabling.

  1. Go to MAX Dashboard > Manage > Networks.
  2. Select Meta Audience Network.
  3. Set Status to "Enabled".
  4. Paste your System User Access Token in the "App ID / Token" field.
  5. Navigate to Manage > Ad Units.
  6. Select your Ad Unit.
  7. Under Bidding Configuration, ensure Meta Audience Network is toggled ON.
  8. Enter the Meta Placement ID.

Phase 3: Client-Side Implementation (The Code)

Configuration is useless if the mobile app cannot generate the required bidder token. You must update your dependencies to versions that support the latest bidding protocols.

Android Integration (Kotlin)

You do not need to manually initialize the Meta SDK for bidding if you use the mediation adapter correctly. The adapter handles the token generation.

1. Update build.gradle.kts (App Level): Ensure you are using the AndroidX compatible versions.

dependencies {
    // Google AdMob SDK
    implementation("com.google.android.gms:play-services-ads:23.0.0")
    
    // AdMob Adapter for Meta (Automatically pulls in the correct Meta SDK)
    implementation("com.google.ads.mediation:facebook:6.17.0.0")

    // OR IF USING MAX:
    // AppLovin SDK
    implementation("com.applovin:applovin-sdk:12.4.1")
    // MAX Meta Adapter
    implementation("com.applovin.mediation:facebook-adapter:6.17.0.0")
}

2. ProGuard Rules (R8): If you use code shrinking, the Meta SDK relies on reflection to generate tokens. Add this to proguard-rules.pro:

-keep class com.facebook.ads.** { *; }
-dontwarn com.facebook.ads.**

iOS Integration (Swift/CocoaPods)

Update your Podfile to ensure specific version matching.

platform :ios, '14.0'

target 'YourAppTarget' do
  use_frameworks!

  # AdMob
  pod 'Google-Mobile-Ads-SDK'
  pod 'GoogleMobileAdsMediationFacebook' # Ensures adapter & Meta SDK

  # OR IF USING MAX
  # pod 'AppLovinSDK'
  # pod 'AppLovinMediationFacebookAdapter'
end

Essential: Data Processing Options

Meta Bidding is extremely sensitive to privacy flags. If you do not explicitly set Data Processing Options (LDU) for CCPA/GDPR, the bidder token may be generated with a "restricted" flag, causing Meta to bid $0.00.

AdMob (Kotlin): AdMob adapters generally forward the consent status from the UMP SDK, but explicit routing is safer.

import com.google.android.gms.ads.MobileAds
import com.google.ads.mediation.facebook.FacebookMediationAdapter

// Initialize MobileAds first
MobileAds.initialize(context) { status -> 
    // Adapter status check
    val metaStatus = status.adapterStatusMap["com.google.ads.mediation.facebook.FacebookAdapter"]
    if (metaStatus?.initializationState == AdapterStatus.State.READY) {
        // Meta is ready to generate tokens
    }
}

// Pass CCPA settings to Meta via AdMob Bundle if necessary
val networkExtras = Bundle()
networkExtras.putBoolean("RDP", true) // Restricted Data Processing for CCPA

val adRequest = AdRequest.Builder()
    .addNetworkExtrasBundle(FacebookAdapter::class.java, networkExtras)
    .build()

AppLovin MAX (Swift): MAX handles this globally via the Privacy Settings API.

import AppLovinSDK

// Set this BEFORE initializing the SDK
ALSdk.shared().configuration.consentFlowUserGeography = .gdpr
ALPrivacySettings.setHasUserConsent(true) // For GDPR
ALPrivacySettings.setIsAgeRestrictedUser(false) // For COPPA
ALPrivacySettings.setDoNotSell(false) // For CCPA

// Initialize
ALSdk.shared().initializeSdk { configuration in
    // SDK is initialized, start loading ads
}

Deep Dive: Verifying the Token Exchange

How do you confirm the fix is working before pushing to production?

Use the Charles Proxy or Android Studio Network Inspector.

  1. Trigger an ad load.
  2. Look for the request to googleads.g.doubleclick.net (AdMob) or ms.applovin.com (MAX).
  3. Inspect the JSON payload.
  4. Search for a field often labeled bidder_token or token.
  5. Validation: This token should be a long, opaque string (base64 encoded).
    • If this string is missing or null, the adapter is failing to communicate with the Meta SDK. Check your dependency versions.
    • If the token is present but Meta returns "No Fill," the issue is likely low eCPM floors in your Meta configuration or a lack of advertiser demand for that user profile.

Common Pitfalls & Edge Cases

1. The "Mixed Mode" Disaster

Do not leave the Waterfall instance active while Bidding is enabled for the same Ad Unit.

  • Result: AdMob/MAX might attempt to call the waterfall adapter first (or last), resulting in latency spikes and duplicate impression counting errors. Delete the waterfall entries entirely once bidding is verified.

2. Test Mode Invisibility

Meta Bidding behaves differently in Test Mode. Unlike waterfall, where you could force fill, bidding relies on live auction dynamics.

  • Fix: You must add your device's Hash ID to Meta Monetization Manager > Integration > Testing. Without this, you will likely see "No Fill" errors during development, even if the implementation is correct.

3. iOS SKAdNetwork IDs

With the shift to bidding, ensuring your Info.plist contains the latest Meta SKAdNetwork IDs is mandatory for iOS 14+ attribution. Without these, Meta will not bid competitively.

<key>SKAdNetworkItems</key>
<array>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v9wttpbfk9.skadnetwork</string>
  </dict>
  <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n38lu8286q.skadnetwork</string>
  </dict>
  <!-- Ensure you have the full list from Meta's documentation -->
</array>

Conclusion

Migrating Meta Audience Network to bidding is not optional; it is the new standard for mobile ad monetization. By generating a proper System User Token, ensuring your adapters are updated, and validating the token exchange via network inspection, you can restore and potentially increase your ad revenue.

The shift removes the latency of sequential waterfall checks, allowing Meta to bid its true value for every single impression in real-time.