7.9 KiB
Mediation Patterns
How ad mediation works in decompiled Android code — identifying the primary mediator, adapter chains, waterfall vs bidding, and configuration extraction.
What is Mediation
Ad mediation allows an app to use multiple ad networks through a single SDK. A mediator (e.g., AdMob, IronSource, AppLovin MAX) orchestrates which ad network serves each impression via:
- Waterfall: Networks are tried in priority order; first to fill wins
- Bidding (header bidding): Networks bid simultaneously; highest bid wins
- Hybrid: Some networks bid, others fill via waterfall
Identifying the Primary Mediator
The mediator is the SDK that controls ad loading. Look for:
Google AdMob Mediation
// AdMob is the mediator when you see mediation adapters:
com.google.ads.mediation.*
// Adapter classes follow the pattern:
com.google.ads.mediation.unity.UnityAdapter
com.google.ads.mediation.ironsource.IronSourceMediationAdapter
com.google.ads.mediation.applovin.AppLovinMediationAdapter
com.google.ads.mediation.facebook.FacebookMediationAdapter
com.google.ads.mediation.vungle.VungleMediationAdapter
Grep:
grep -rn 'com\.google\.ads\.mediation\.' "$SOURCE_DIR"
IronSource / LevelPlay Mediation
// IronSource is the mediator when you see adapter packages:
com.ironsource.adapters.*
// Adapter naming:
com.ironsource.adapters.admob.*
com.ironsource.adapters.unityads.*
com.ironsource.adapters.applovin.*
com.ironsource.adapters.facebook.*
com.ironsource.adapters.vungle.*
Grep:
grep -rn 'com\.ironsource\.adapters\.' "$SOURCE_DIR"
AppLovin MAX Mediation
// MAX is the mediator when you see MAX adapter packages:
com.applovin.mediation.adapters.*
// Adapter classes extend MediationAdapterBase:
com.applovin.mediation.adapters.GoogleMediationAdapter
com.applovin.mediation.adapters.UnityAdsMediationAdapter
com.applovin.mediation.adapters.IronSourceMediationAdapter
com.applovin.mediation.adapters.FacebookMediationAdapter
Grep:
grep -rn 'com\.applovin\.mediation\.adapters\.' "$SOURCE_DIR"
Waterfall vs Bidding
Waterfall indicators
# Priority/floor price configuration
grep -rn 'waterfall\|floorPrice\|ecpm\|eCPM\|setPriority\|adNetworkOrder' "$SOURCE_DIR"
# Manual network ordering
grep -rn 'setNetworkOrder\|setAdapterOrder\|setWaterfallConfiguration' "$SOURCE_DIR"
Bidding indicators
# Real-time bidding signals
grep -rn 'bidding\|headerBidding\|bidToken\|collectSignal\|getBiddingToken' "$SOURCE_DIR"
# Bidding adapter classes (often have "Bidding" in the name)
grep -rn 'BiddingAdapter\|BiddingProvider\|RTBAdapter' "$SOURCE_DIR"
# MAX bidding
grep -rn 'MaxMediatedNetworkInfo\|isBidding\|bidFloor' "$SOURCE_DIR"
Adapter Discovery
List all mediation adapters present
# Find all adapter class files
find "$SOURCE_DIR" -path "*/mediation/adapters/*.java" -o -path "*/adapters/*Adapter*.java" | head -50
# Find adapter registration/initialization
grep -rn 'registerAdapter\|initializeAdapter\|setAdapterState\|MediationAdapter' "$SOURCE_DIR"
Extract adapter configuration
# Network IDs and app keys passed to adapters
grep -rn 'setAppKey\|setAppId\|setGameId\|setSdkKey\|setNetworkKey' "$SOURCE_DIR"
# Ad unit/placement mapping (mediator → network)
grep -rn 'placementMap\|adUnitMap\|networkPlacementId\|customEventExtras' "$SOURCE_DIR"
Common Mediation Setups
Setup 1: AdMob as Mediator
AdMob (primary) → loads via:
├── Google Ads (direct)
├── UnityAdapter → Unity Ads SDK
├── IronSourceMediationAdapter → IronSource SDK
├── AppLovinMediationAdapter → AppLovin SDK
└── FacebookMediationAdapter → Meta AN SDK
Setup 2: IronSource/LevelPlay as Mediator
IronSource (primary) → loads via:
├── IronSource Network (direct)
├── AdMob adapter → Google Mobile Ads SDK
├── Unity adapter → Unity Ads SDK
├── AppLovin adapter → AppLovin SDK
└── Vungle adapter → Vungle SDK
Setup 3: AppLovin MAX as Mediator
AppLovin MAX (primary) → loads via:
├── AppLovin Network (direct, always bidding)
├── GoogleMediationAdapter → AdMob SDK
├── IronSourceMediationAdapter → IronSource SDK
├── UnityAdsMediationAdapter → Unity Ads SDK
└── FacebookMediationAdapter → Meta AN SDK
Active vs Passive SDKs
When mediation is present, most ad SDKs in the APK are passive dependencies — they are only invoked internally by the mediator's adapter classes, never by the app's own code.
The Entry Point Graph
App code (com.example.myapp.*)
│
▼
Mediator SDK (e.g., AdMob) ← ACTIVE: called by app code
│
├──→ Adapter (com.google.ads.mediation.unity.*)
│ └──→ Unity Ads SDK ← PASSIVE: called only by adapter
│
├──→ Adapter (com.google.ads.mediation.ironsource.*)
│ └──→ IronSource SDK ← PASSIVE: called only by adapter
│
└──→ Adapter (com.google.ads.mediation.applovin.*)
└──→ AppLovin SDK ← PASSIVE: called only by adapter
How to Distinguish
An SDK is active if its init/load/show calls appear in app code. An SDK is passive if its code is present only inside library packages.
Key principle: Search for SDK calls only in non-library directories. Known library packages to exclude:
| Package prefix | SDK |
|---|---|
com/google |
Google/AdMob |
com/unity3d |
Unity Ads |
com/ironsource |
IronSource/LevelPlay |
com/applovin |
AppLovin/MAX |
com/facebook |
Meta Audience Network |
com/vungle, io/vungle |
Vungle/Liftoff |
com/inmobi |
InMobi |
com/chartboost |
Chartboost |
com/bytedance, com/pgl |
Pangle/TikTok |
com/mbridge, com/mintegral |
Mintegral |
Grep Examples
# Search for ad SDK calls ONLY in app code (exclude all library packages)
grep -rn --include="*.java" --include="*.kt" \
--exclude-dir="com/google" --exclude-dir="com/unity3d" \
--exclude-dir="com/ironsource" --exclude-dir="com/applovin" \
--exclude-dir="com/facebook" --exclude-dir="com/vungle" \
--exclude-dir="com/inmobi" --exclude-dir="com/chartboost" \
--exclude-dir="com/bytedance" --exclude-dir="com/pgl" \
--exclude-dir="com/mbridge" \
-E '(MobileAds\.initialize|UnityAds\.initialize|IronSource\.init|AppLovinSdk\.getInstance)' \
"$SOURCE_DIR"
Interpreting results:
- If
MobileAds.initializeappears incom/example/myapp/AdManager.java→ AdMob is active - If
UnityAds.initializeappears only incom/google/ads/mediation/unity/UnityAdapter.java→ Unity Ads is passive (but this file is excluded, so it won't show up) - If
UnityAds.initializeappears incom/example/myapp/AdsHelper.java→ Unity Ads is also active (direct integration alongside mediation)
Architecture Classification
| Architecture | Meaning | Example |
|---|---|---|
| Single mediator | App calls 1 SDK; all others are passive adapter deps | AdMob init + 5 mediated networks |
| Multiple direct | App calls 2+ SDKs directly; no mediation | AdMob banners + Unity interstitials |
| Hybrid | App calls a mediator + some SDKs directly | AdMob mediation + direct IronSource rewarded |
Automated Detection
Use the --entrypoints flag of find-ads.sh:
bash find-ads.sh <source-dir> --entrypoints
This runs the exclusion-based grep automatically and shows only app-initiated SDK calls.
Extracting Mediation Configuration
Look for server-side configuration that controls the mediation waterfall:
# JSON config responses from mediation servers
grep -rn 'mediationConfig\|auctionResponse\|waterfallConfig\|adNetworkConfig' "$SOURCE_DIR"
# Remote config / A/B test for ad setup
grep -rn 'RemoteConfig.*ad\|firebase.*ad_config\|ad_waterfall\|ad_network_ids' "$SOURCE_DIR"