Google Ad Manager for Mobile Apps: The Complete Operator Guide

Google Ad Manager (the ad server, not Workspace) for mobile apps: GMA SDK, ad unit setup, mediation, COPPA flags, and the 2024 policy change, in one operator guide.

Google Ad Manager (GAM) uses the same GMA SDK as AdMob but requires separate ad unit configuration, different initialization parameters, and a distinct mediation approach. Before serving live ads, an iOS app requires a Privacy Manifest entry and App Store listing; an Android app requires the App ID in AndroidManifest.xml. COPPA and TFUA flags must be set before calling MobileAds.initialize. GAM mediation for mobile runs through yield groups, not AdMob-style mediation groups. Since 2024, direct third-party network line items in GAM mobile are no longer supported. All non-Google demand routes through mediation adapters.

Disambiguating Google Ad Manager from Google Workspace

Google Ad Manager (GAM) is the ad serving platform at admanager.google.com. It was previously called DoubleClick for Publishers (DFP). It has nothing to do with Google Workspace, formerly G Suite. If you searched for "Google Apps Manager" and landed here: this is the ad server, not the productivity suite. The article you need is this one.

The web version of GAM (orders, line items, Prebid header bidding, GAM tags in browser) is a related but separate implementation track. That setup is covered in detail in the Google Ad Manager Setup: Complete Implementation Guide for Publishers. This article is the mobile-app version: GMA SDK integration, mobile-specific ad unit types, mediation via yield groups, and the compliance flags that apply before the SDK initializes. The two articles address different audiences on different implementation paths.

For mobile app operators: GAM becomes relevant when AdMob does not give you enough control. Direct deals, Prebid Mobile integration, custom CPM floors per geo and format, or access to AdX demand outside AdMob's optimization logic are the common reasons to move to GAM. If none of those apply to your current situation, stay on AdMob. It is the simpler starting point.

AdMob vs GAM vs GAM 360 for mobile apps

This is the decision that shapes everything downstream. Getting it wrong means either setting up a stack that is more complex than your situation requires, or hitting the limits of a simpler platform at the wrong moment.

AdMob

AdMob is Google's self-serve mobile ad platform. Mediation is configured through the AdMob UI using mediation groups and ad sources. AdX demand is available for eligible publishers. ARPDAU optimization runs automatically through AdMob's AAEON system. No order management, no line items, no trafficking knowledge required.

AdMob is right for: indie developers, apps below roughly 1 million monthly ad requests, teams without a dedicated AdOps resource, and publishers who want managed optimization without the overhead of trafficking configuration. Use the AdMob Approval Checker if you are evaluating whether your account is in good standing before deciding.

AdMob is wrong for: publishers who need direct deals, Prebid Mobile, custom floor controls per buyer, or programmatic guaranteed access to AdX demand.

For the mediation platform comparison on the demand-network side, see AdMob Mediation vs AppLovin MAX before committing to either path.

GAM (free tier)

The full ad serving platform: order management, line items, targeting, and reporting. For mobile apps, GAM uses the same GMA SDK as AdMob but requires the operator to configure ad units, orders, and line items manually. Mediation runs through yield groups. The free tier is capped at 90 million ad impressions per month. AdX demand is available via dynamic allocation.

GAM is right for: publishers running direct deals or Prebid Mobile, publishers who need floor control per geo and format, publishers moving off AdMob who need programmatic guaranteed capability, or publishers where GAM's reporting granularity (custom dimensions, Data Transfer) is necessary for reconciliation.

Migration from AdMob: apps already using the GMA SDK for AdMob can migrate to GAM without an SDK change. The App ID format is the same (ca-app-pub-...~...) but the value changes. Ad units must be recreated in GAM. Orders and line items must be configured. The AdMob mediation groups are replaced by GAM yield groups. This is a meaningful AdOps workload. Plan for it before committing to the migration.

GAM 360

The enterprise tier. Adds programmatic guaranteed deal types, no impression cap, advanced forecasting, custom video features, and dedicated support. Access requires direct negotiation with Google and is not self-served.

GAM 360 is relevant for: apps above 90 million monthly impressions, publishers running complex programmatic guaranteed deal structures, and apps that need custom video ad configurations beyond what GAM free supports.

If you are not sure whether you need 360, you do not need it. The 90 million monthly impression cap on GAM free is generous. An app monetizing interstitials and rewarded video at typical fill rates will generally not reach it below roughly 300K DAU. GAM 360 access is applied through Google account management; existing free accounts can be upgraded when the threshold becomes relevant.

Pre-flight checklist

Operators who skip these steps hit avoidable blockers after completing the SDK integration. Address them before writing a line of SDK code.

Account and payment

GAM account access is available at admanager.google.com. Approval is not automatic and can take 24-48 hours. If you are coming from AdMob, you may be able to link accounts via the AdMob interface. Set up a payment profile before SDK integration. GAM requires a valid payment profile before live ads serve, and it is the kind of blocker that surfaces at the worst moment (launch day). Once your account is approved, your network code (a numeric ID) appears in the GAM interface. You will need it to initialize the SDK and configure ad units.

App registration and store listing

Register the app as a mobile app in GAM under Inventory > Apps. For iOS, the app must have an active App Store listing before live programmatic ads serve. Unpublished apps (no store link) will fill test ads but will show near-zero live ad fill after removing test mode. For Android, a Play Store listing is required for live ad serving.

App ID format: the GAM App ID is in the format ca-app-pub-################~##########. Same format as AdMob App IDs, different identifier. Do not use your AdMob App ID in a GAM-configured app. The SDK initializes against the wrong network code and the symptom is not always obvious.

app-ads.txt

app-ads.txt must be live at your developer domain (the domain registered in the app store listing) before serving live programmatic ads. The file declares that Google is an authorized seller of your app inventory. Line format: google.com, pub-################, DIRECT, f08c47fec0942fa0. Obtain your publisher ID from the GAM interface.

The file lives at the developer domain root. If your developer domain is developer.example.com, the file is at developer.example.com/app-ads.txt. The app store listing must declare that developer domain for the association to be validated. A domain mismatch between the app store listing and where the file is hosted is one of the most common sources of unexplained programmatic fill degradation.

Consent management platform

EEA/UK publishers must collect user consent before initializing the GMA SDK. The Google User Messaging Platform (UMP) SDK is the recommended CMP for GAM. Consent collection must complete before calling MobileAds.initialize. Calling initialize before consent is collected means the SDK may preload ad requests with incorrect targeting parameters. The compliance implication and the fill rate impact in consent-required regions are both real. The Google quick-start guide notes the consent requirement but does not explain the initialization sequencing consequence of skipping it.

GMA SDK integration (Android and iOS)

The GMA SDK is the same codebase for AdMob and GAM. The difference is the App ID and ad unit IDs used at initialization and request time. If you have an existing AdMob SDK integration, migrating to GAM is primarily a configuration change, not an SDK change. For SDK version compatibility and known adapter conflicts, run the Mediation SDK Checker before any GMA SDK version bump.

Android setup

Dependency: com.google.android.gms:play-services-ads:25.2.0 (as of 2026; verify the current version at developers.google.com/ad-manager/mobile-ads-sdk). Minimum SDK version: 23. Compile SDK version: 35.

App ID configuration: add a <meta-data> tag in AndroidManifest.xml with name com.google.android.gms.ads.APPLICATION_ID and your GAM App ID as the value. Using the wrong App ID (for example, an AdMob App ID in a GAM-configured app) will cause the SDK to initialize against the wrong account. The symptom ranges from test ads serving in production to complete no-fill, depending on the account state.

Initialization: call MobileAds.initialize() once at app launch on a background thread. Calling it on the main thread causes an IllegalStateException in some SDK versions and may cause ANRs in others. Use a coroutine or background executor.

Consent sequencing on Android: (1) request consent info update via ConsentInformation.getInstance().requestConsentInfoUpdate(), (2) present the consent form if required, (3) after consent is collected or confirmed unnecessary, call MobileAds.initialize. Skipping this sequence in EEA may result in non-personalized ads serving to users who have not consented to personalized targeting.

iOS setup

Dependency options: CocoaPods (pod 'Google-Mobile-Ads-SDK'), Swift Package Manager, or manual framework embedding. Xcode 16.0 or higher. Minimum target iOS 13.0.

SPM limitation: mediation adapter libraries are not available via Swift Package Manager. If you plan to run mediation (and you should), use CocoaPods or manual installation for the GMA SDK from the start. Running a mixed integration (GMA SDK via SPM, adapters via CocoaPods) causes linker errors and is not supported.

Info.plist configuration: add GADApplicationIdentifier key with your GAM App ID as the string value. Add SKAdNetworkItems array with the required SKAdNetworkIdentifier entries. For GAM, include Google's SKAdNetwork ID (cstr6suwn9.skadnetwork). For mediation, include all mediation network SKAdNetwork IDs as well. The maintenance requirement here is ongoing; see the mediation section for the implication.

For the full SKAdNetwork attribution configuration, including the crowd anonymity constraints and conversion value schema design that determine whether iOS attribution data is usable, see SKAdNetwork 4.0 Conversion Value Setup.

Privacy Manifest: required for any iOS app using the GMA SDK when submitting to the App Store. The GMA SDK accesses several data types that Apple requires disclosure of in a PrivacyInfo.xcprivacy file: device identifiers (IDFA when consent is granted), coarse location (for targeting), and system uptime (for fraud prevention). Google publishes the required NSPrivacyAccessedAPITypes entries in their Privacy Manifest documentation. Add the GMA-specific entries to your app's PrivacyInfo.xcprivacy, not just to the SDK's own manifest. App Store review validates the app-level manifest. Missing entries will cause App Store review rejection for apps targeting iOS 17.5+.

Initialization: call MobileAds.shared.start() (Swift) or [GADMobileAds.sharedInstance startWithCompletionHandler:nil] (Objective-C). Collect user consent before calling start. With mediation enabled, allow the completion handler to fire before loading the first ad. The completion handler signals that adapters are ready. Loading an ad before it fires results in mediation calls that fail silently.

SDK version maintenance

The GMA SDK releases regularly. Breaking changes (API deprecations, adapter incompatibilities) are documented in the release notes but easy to miss across a multi-network mediation stack. The Mediation SDK Checker audits your declared GMA SDK version against known compatibility issues with mediation adapters. For the full compatibility matrix and maintenance implications, see the Mediation SDK & Adapter Compatibility Guide.

Ad unit creation and naming conventions

Ad units in GAM are created under Inventory > Ad Units. Each ad unit has a name, size, and format. The ad unit path (not the UUID) is used in ad requests: /networkcode/ad-unit-name. For example, /123456/BrewTimer/iOS/Banner/HomeTab.

Supported formats for mobile apps

Banner: Standard IAB sizes (320x50, 300x250, 320x100). Adaptive banners (responsive width, fixed height) are the Google-recommended production format and outperform fixed-size banners in most publisher tests. Use GAM's BANNER ad unit type with the adaptive banner request from the SDK side.

Interstitial: full-screen ad that covers the app interface, placed at natural pause points (level transitions, content loads). The GAM interstitial ad unit format must match the SDK request's format. A mismatch results in no-fill with no error logged.

Rewarded: full-screen rewarded video or image where the user receives an in-app reward for completion. The reward amount and item are configured in the GAM ad unit settings. The reward configuration in GAM must match the reward handling logic in the SDK.

Rewarded interstitial: a hybrid format (rewarded experience in an interstitial placement). Available in GAM as of GMA SDK 8.x+. Useful for apps where the user is not explicitly opting in for a reward but the format is still full-screen.

Native: custom-rendered ads where the publisher controls layout. GAM native ads require a native ad configuration (defining asset types: headline, image, call-to-action) in the GAM interface. The SDK loads the native asset object; the publisher renders it. Native ads require more implementation work than banner or interstitial.

App open: full-screen ad shown at app launch or foreground resume. GAM supports app open ads as a dedicated ad unit type with a specific ad loader in the SDK. High CPM potential for apps with frequent foreground events, but requires rate-limiting to avoid user experience degradation that affects session metrics.

Naming convention

Create a naming convention before creating your first ad unit. Retroactively applying a naming convention to an existing GAM account is painful, and an account without one becomes unmanageable after five or six apps and a handful of formats.

Recommended structure: [AppName]/[OS]/[Format]/[Placement]. Example: BrewTimer/iOS/Banner/HomeTab or BrewTimer/Android/Rewarded/LevelEnd.

Why separate by OS: GAM allows per-OS targeting at the ad unit level. iOS and Android inventory typically have different eCPMs, fill rates, and mediation configurations. Separate ad units allow granular reporting and configuration per platform.

Why separate by placement: multiple banner placements in the same app should be separate ad units. Aggregated reporting across all banner placements hides per-placement performance differences that matter for optimization.

Keep names under 100 characters. Avoid special characters that do not render cleanly in GAM's reporting interface.

Targeting, line items, and orders for mobile inventory

For operators coming from AdMob, GAM's order and line item system is the primary conceptual shift. AdMob allocates demand automatically. GAM requires explicit order and line item creation for each demand source. This gives more control; it also requires more operational overhead.

Orders and line items

An order in GAM represents a deal or campaign. For mediation, each third-party network typically gets its own order. Line items within that order define the CPM tier, ad format, ad unit targeting, and the creative (for mediation, an SDK creative that calls the network's adapter).

For programmatic demand (AdX and Google demand), GAM handles this through dynamic allocation, not manual line items. Dynamic allocation lets AdX compete against your manually-set line items in real time. Publishers do not create AdX line items manually; they enable dynamic allocation at the ad unit or network level.

Floor pricing: GAM allows CPM floors per ad unit, per geo, and per format. Floors apply to the dynamic allocation auction. A floor of $3 CPM for US banner inventory means AdX and other demand must bid at or above $3 to win that impression. Floors below market rates have no effect. Floors above market rates produce unfilled impressions. Start without a floor and adjust based on observed average CPM data before adding price controls.

Mobile-specific targeting

OS targeting: target line items to iOS or Android when the demand source or creative is platform-specific. Most mediation adapter creatives are platform-specific; an Android adapter creative should not serve on iOS.

App version targeting: target by app version number. Useful for phased rollouts or for serving different ad configurations to users on legacy SDK versions that may have different adapter compatibility.

Custom key-values: the GMA SDK allows passing custom key-value pairs with ad requests (for example, levelNumber=5, userSegment=engaged). These can be used as targeting parameters in GAM line items. This is how Prebid Mobile passes bid price information to GAM for line item matching.

For the full order and line item trafficking reference covering the web GAM side of this same platform, see Google Ad Manager Setup: Complete Implementation Guide for Publishers.

Mediation in GAM mobile

Mediation in GAM mobile works through yield groups, not through AdMob mediation groups. This is the most common point of confusion for operators migrating from AdMob, and it has practical implications for how you configure each demand source.

For context on whether to structure your demand as a waterfall or shift to in-app bidding before configuring yield groups, see Mediation Waterfall vs In-App Bidding.

Yield groups vs AdMob mediation groups

In AdMob, mediation groups are configured in the AdMob UI. Networks are added as ad sources with optional eCPM floors. AdMob's AAEON optimization automatically reorders networks to maximize fill.

In GAM, yield groups are configured under Delivery > Yield Groups. Each network requires a yield partner company entry in GAM (Admin > Companies), a yield partner configuration under that company, and then addition to the yield group. The configuration is more manual than AdMob but gives more control over waterfall ordering and CPM floors.

For operators migrating from AdMob to GAM: you will need to recreate your AdMob mediation configuration as GAM yield groups. The networks are the same; the interface and terminology are different. Plan for this as a separate implementation task after the SDK integration is complete.

Third-party network integration via yield groups

Third-party networks (AppLovin MAX, Unity LevelPlay, Meta Audience Network, Mintegral, and others) integrate with GAM through mediation adapters. The adapter is a library that the publisher includes in their app alongside the GMA SDK. When GAM's yield group calls a third-party network, the adapter translates the GMA SDK ad request into the network's SDK request, loads the ad, and returns it to the GMA SDK for rendering.

When adding a third-party network to a yield group, GAM requires an integration type and class name (the adapter class that handles the request). These values are provided by the network in their GAM integration documentation. The class name must match the adapter version installed in the app. A mismatch between GAM configuration and installed adapter version is a common source of no-fill. The failure is silent: GAM records a request to the yield partner, but the adapter returns nothing.

Networks without a first-party GAM adapter can be integrated as Custom Events. This requires more configuration (custom class name, parameter JSON) but supports any network that has a GMA SDK adapter library.

Adapter version compatibility: mediation adapters are versioned separately from the GMA SDK and from the demand network's own SDK. All three must be compatible simultaneously. See the Mediation SDK & Adapter Compatibility Guide for the compatibility matrix and maintenance implications. The Mediation SDK Checker audits your declared adapter versions against known conflicts before you push a build.

The 2024 mediation policy change

In 2024, Google ended support for direct third-party network line items in GAM mobile. Previously, publishers could call a third-party network SDK directly from a line item creative without going through a mediation adapter. That configuration path is no longer supported for mobile app inventory. The practical effect: publishers who had direct network line items must migrate those demand sources to the mediation adapter pattern via yield groups. The direct line item approach was simpler to set up but limited GAM's reporting and fill optimization signal.

Operators who have GAM mobile setups predating 2024 should audit their line items for any remaining direct-call creatives and migrate them to yield group configurations. The symptom of a non-migrated setup is specific demand partners showing high request counts in old line item reporting with zero or near-zero recent delivery.

If your GAM mobile setup was built before 2024 and has not been audited since, there is a reasonable chance you are still running direct line item configurations that no longer serve, or that are underperforming because they were not migrated to yield group mediation. That is the kind of configuration audit that pays for itself quickly. The free initial conversation is the right starting point: Book a free 30-minute call.

Test ads vs production and SDK initialization patterns

GAM provides test ad unit IDs that return test ads regardless of account configuration. Using these during development matters: running live ad requests against production ad units during development consumes impression quotas, can trigger invalid traffic (IVT) detection, and can affect fill rate reporting before the account configuration is complete.

Test ad unit IDs

Google provides sample test App IDs and ad unit IDs for both Android and iOS in their documentation. Android sample App ID: ca-app-pub-3940256099942544~3347511713. iOS sample App ID: ca-app-pub-3940256099942544~1458002511. These values return Google test ads and are safe to use during development and QA. Switch to production ad unit IDs only when submitting to the store or running a production test build.

For testing against a real account configuration, register the device hash in your initialization code using testDeviceIdentifiers. The SDK will serve test ads to that device while production serves normally. The test device hash is logged by the SDK on first initialization; retrieve it from Android Logcat or iOS Console.

Initialization sequence

The correct sequence for a GAM app: (1) initialize the CMP and collect user consent if required, (2) set COPPA and TFUA flags if applicable, (3) call MobileAds.initialize(). Any ad loading that happens before initialization completes will produce no-fill or unexpected behavior.

Background thread requirement on Android: MobileAds.initialize() on the main thread causes an IllegalStateException in some SDK versions and may cause ANRs in others. Always call on a background thread using a coroutine or background executor.

With mediation: the completion handler for MobileAds.initialize() returns when all mediation adapters have completed their own initialization. Load ads only after the completion handler fires. Loading before adapter initialization completes results in mediation calls that fail silently. For apps that pre-fetch ads at the splash screen, this is the most common place the sequencing is skipped.

Before any GMA SDK version bump, run the Mediation SDK Checker to confirm adapter compatibility across the stack.

Reporting and reconciliation

GAM reporting for mobile differs from AdMob reporting in structure, latency, and granularity. Operators migrating from AdMob should understand these differences before interpreting their first GAM reports.

Reporting differences from AdMob

GAM reports are available in the Report Manager under Reports and are run on demand or scheduled. There is no persistent real-time dashboard comparable to AdMob's home screen. Operators accustomed to checking AdMob ARPDAU metrics daily need to build report templates in GAM and schedule them, rather than checking a live view.

Latency: GAM reporting data is typically available with a 24-48 hour lag. Some metrics (impressions, clicks) appear more quickly, but yield metrics (eCPM, revenue) may lag. Do not compare GAM same-day revenue to AdMob same-day revenue without accounting for this difference.

Reporting dimensions: GAM supports custom reporting dimensions that AdMob does not, including advertiser, order, line item, and custom key-values. This granularity is the primary reporting advantage of GAM for publishers who need to reconcile demand source performance. Build a standard report template that includes ad unit, format, country, and demand source (yield partner) as dimensions.

Data Transfer

GAM's Data Transfer feature exports raw impression-level data to BigQuery or Google Cloud Storage. For mobile publishers at scale, Data Transfer is the primary mechanism for building custom dashboards, reconciling mediation partner data, and detecting fill anomalies. Data Transfer is available in both GAM free and GAM 360; 360 adds more frequent export schedules and more field types. For the full Data Transfer reference, see Google Ad Manager Setup: Complete Implementation Guide for Publishers.

Reconciliation with mediation networks

Each mediation network reports its own revenue in its own dashboard: AdMob reporting for AdSense/AdX demand, MAX dashboard for AppLovin demand, and so on. GAM reporting shows yield group fill rate and estimated revenue from GAM's side. Discrepancies between GAM-reported revenue and network-reported revenue are normal and expected. GAM reports estimated network revenue; the network reports actuals. For reconciliation purposes, the network's dashboard is the authoritative revenue figure. GAM's mediation revenue estimate is a yield management tool, not a billing reference.

Known gotchas

Each issue below follows the same structure: what breaks, why it breaks, what to do. These are drawn from the GMA SDK release notes, third-party network integration guides, and the 2024 policy change. No other editorial page on this SERP covers more than two or three of these failure modes in operator terms.

Gotcha 1: COPPA and TFUA flags omitted

If your app targets children under 13 (COPPA) or users under 16 in EEA/UK (TFUA), you must set the corresponding flags before calling MobileAds.initialize. For COPPA: set tagForChildDirectedTreatment(true) in the RequestConfiguration. For TFUA: set tagForUnderAgeOfConsent(true). Omitting these flags on a COPPA-covered app results in non-compliant personalized ads serving to children, which is a policy violation with account suspension risk. Setting the flags after initialization does not retroactively apply to already-loaded ads. Many operators set these flags conditionally based on user-entered age during onboarding. Confirm the flag-setting logic fires before the SDK initialization call, not after.

Gotcha 2: App ID format error (GAM ID vs AdMob ID)

The GAM App ID and AdMob App ID are both in the ca-app-pub-################~########## format. Using an AdMob App ID in a GAM-configured app (or vice versa) causes the SDK to initialize against the wrong account. The symptom is test ads serving when you expect production ads, or no fill when the account is not approved. Double-check that the App ID in AndroidManifest.xml (Android) or Info.plist (iOS) matches the App ID shown in your GAM account, not your AdMob account.

Gotcha 3: iOS App Store listing required for live ads

Test ads serve without an App Store listing. Live programmatic ads from GAM require a valid App Store URL associated with the app in GAM's interface under Inventory > Apps. If you register an iOS app in GAM as unpublished (no store link), you will see test ad fill but near-zero live ad fill after removing test mode. This is a common source of confusion during staged rollouts: the app is in TestFlight but not yet on the App Store, and live ads fail to fill. The App Store listing must be live and the URL must match the registered developer domain's app-ads.txt setup.

Gotcha 4: SPM-mediation limitation on iOS

The GMA SDK is available via Swift Package Manager, but mediation adapter libraries are not. If you integrate via SPM and then try to add mediation adapters (AppLovin MAX, Unity LevelPlay, and others), the adapters must be added via CocoaPods or manual embedding. Running a mixed integration (GMA SDK via SPM, adapters via CocoaPods) is not supported and causes linker errors. If mediation is part of your plan, use CocoaPods or manual installation for the GMA SDK from the start.

Gotcha 5: Privacy Manifest missing or incomplete (iOS)

Apps submitted to the App Store targeting iOS 17.5+ must include a Privacy Manifest (PrivacyInfo.xcprivacy) declaring all APIs accessed for tracking purposes. The GMA SDK accesses several tracked API types. If the manifest entries for GMA-accessed APIs are missing or incomplete, App Store review rejects the submission with a privacy manifest validation error. Google publishes the required entries in their Privacy Manifest documentation. Add them to your app's PrivacyInfo.xcprivacy, not just to the SDK's own manifest. App Store review validates the app-level manifest, not individual framework manifests.

Gotcha 6: Adapter class name mismatch in yield group

When configuring a third-party network in a GAM yield group, the integration class name must exactly match the adapter class name in the version of the adapter installed in the app. Pre-v8.0.0 and post-v8.0.0 GMA SDK versions use different class name conventions for some adapters. If the class name in GAM does not match the adapter version in the app, the yield partner call fails silently: GAM records a request to the yield partner, but the adapter returns no fill. The symptom is 0% fill rate for that yield partner in GAM reporting despite the adapter being installed.

Gotcha 7: Mediation adapters loaded before GMA SDK completion handler

If you load an ad from a mediation-backed ad unit before the MobileAds.initialize() completion handler fires, mediation adapters may not be ready. The symptom is inconsistent fill from mediation sources, particularly at app launch. The fix: gate all ad loading behind the completion handler callback. With mediation, initialization can take several seconds. An SDK loading a pre-fetched ad at the splash screen is the most common place this is skipped.

Gotcha 8: Test device IDs not removed at production release

During development, adding device IDs to testDeviceIdentifiers causes the SDK to serve test ads to those devices even in production builds. If a development device ID is left in the production build's initialization code, that device receives test ads after release. This does not affect other users but means your QA device cannot be used to verify production ad fill after launch without removing the test device registration. Use build flag conditionals (#if DEBUG) to gate test device ID registration to non-production builds.

Gotcha 9: app-ads.txt developer domain mismatch

The app-ads.txt file must be hosted at the developer domain associated with the app store listing, not the app's website or any other domain. If the app store listing declares developer.example.com as the developer domain and the app-ads.txt is at example.com/app-ads.txt, GAM's crawler will not find it. Programmatic demand will treat the inventory as not ads.txt authorized. The symptom is below-expected programmatic fill for GAM AdX demand with no obvious error in the interface. Check the developer domain in the app store listing settings and confirm app-ads.txt is accessible at the exact domain root.

Gotcha 10: Direct line item creatives from pre-2024 mediation setup

As of 2024, GAM no longer supports direct third-party SDK calls from line item creatives for mobile app inventory. If your GAM setup includes line items with SDK-call creatives created before this policy change, those line items no longer fill or fill at degraded rates. The fix is to migrate those demand sources to yield group configurations with adapter-based mediation. The diagnostic signal: specific demand partners show high request counts in old line item reporting with zero recent delivery, while the same partners are absent from yield group reporting entirely.

If multiple gotchas from this list apply to your current setup, a structured configuration audit is faster than working through each one individually. The free initial conversation is the right starting point: Book a free 30-minute call.

Frequently Asked Questions

What is the difference between AdMob and Google Ad Manager for mobile apps?

AdMob is Google's self-serve mobile ad platform with automatic mediation optimization. Google Ad Manager (GAM) is the full ad serving platform that requires manual order and line item configuration but gives publishers more control: custom floor pricing, direct deal trafficking, Prebid Mobile integration, and granular reporting via Data Transfer. Both use the same GMA SDK. The App ID and ad unit IDs are different between AdMob and GAM. AdMob is the better starting point for apps below roughly one million monthly ad requests or teams without AdOps resources. GAM is the right choice when you need programmatic guaranteed deals, Prebid Mobile, or floor pricing control that AdMob's automatic optimization does not provide.

Do I need GAM 360 for mobile app monetization?

Most mobile publishers do not need GAM 360. The free tier of GAM supports up to 90 million ad impressions per month, which is sufficient for apps with up to roughly 300,000 DAU at typical interstitial and rewarded fill rates. GAM 360 adds programmatic guaranteed deal types, no impression cap, advanced forecasting, and dedicated support. If your app is below the 90 million monthly impression cap and you do not have complex programmatic guaranteed deal requirements, GAM free is the correct choice. GAM 360 access requires direct negotiation with Google and is not self-served.

How do I configure the GMA SDK for GAM ad units instead of AdMob?

The GMA SDK is the same codebase for both AdMob and GAM. The difference is the App ID you provide at initialization. In your AndroidManifest.xml (Android) or Info.plist (iOS), replace any AdMob App ID with your GAM App ID obtained from Inventory > Apps in the GAM interface. The format is identical: ca-app-pub-################~##########, but the value is a different identifier. Replace AdMob ad unit IDs in your SDK ad request code with GAM ad unit IDs, which follow the path format /networkcode/ad-unit-name. Set COPPA and TFUA flags and collect user consent before calling MobileAds.initialize(). Do not use an AdMob App ID in a GAM-configured app; the SDK will initialize against the wrong account.

Why aren't my GAM mobile ads filling?

The most common causes are: the app is registered in GAM as unpublished without an App Store listing, which blocks live programmatic ads; app-ads.txt is missing or hosted at the wrong developer domain; a mediation adapter class name in the yield group does not match the adapter version installed in the app; ads are being loaded before MobileAds.initialize() completes so mediation adapters are not ready; or COPPA and TFUA flags are set, which restricts personalized demand and reduces available fill. Check these five conditions before looking for more complex causes. If the app was set up before 2024, also check whether any line items are using direct third-party SDK call creatives, which Google no longer supports for mobile app inventory.

Can I run third-party networks directly in GAM mobile without a mediation adapter?

No. As of 2024, Google no longer supports direct third-party SDK calls from line item creatives in GAM mobile app inventory. All third-party demand sources must go through mediation adapters configured in yield groups. If your GAM setup predates 2024 and includes direct-call line items for third-party networks, those line items will show low or zero fill rates. Migrate those demand sources to yield group configurations with the appropriate adapter integration type, class name, and parameter JSON. This policy change was confirmed in Google's platform updates and reported by industry publications in 2024.

How do I migrate from AdMob to GAM for my mobile app?

The GMA SDK does not need to change. Update the App ID to your GAM App ID in AndroidManifest.xml or Info.plist and update ad unit IDs to GAM ad unit paths in the format /networkcode/ad-unit-name. Re-register the app in GAM under Inventory > Apps. Recreate your AdMob mediation configuration as GAM yield groups: create a yield partner company for each network, configure the yield partner with adapter class name and parameters, and add each partner to a yield group covering your ad units. Set up app-ads.txt at your developer domain. Verify the initialization sequence: consent before initialize, COPPA and TFUA flags before initialize, completion handler fires before first ad load. Expect a fill rate adjustment period of 7 to 14 days while GAM dynamic allocation calibrates against your inventory.

GAM for mobile apps is a capable platform when it is configured correctly. The setup surface is large enough that most teams hit at least two or three of the gotchas above before the stack is stable. If you want a second set of eyes on your GAM mobile configuration before or after launch, that is what the free initial conversation is for: Book a free 30-minute call.