This guide covers from configuring the Admob account, setting up ios and android for expo managed workflow. I'm using https://github.com/invertase/react-native-google-mobile-ads.
Configure Admob
Go to your Admob account and click to add a new app.

If your app is not yet listed in the stores, that's ok. You can add it later in app settings and App store details.
But, I wish I thought about this at the beginning. If you think about it, you want more users installing and staying when your app is new. Lots of them will be turned off when they see ATT popup, then GDPR popup, and then ads. That's too much annoyance and users haven't even started to use your app. That's also negative for your ASO, and you don't even have app reviews yet. That's my current opinion, I'm not so sure it's worth it unless you have a large user base and very little subscribers.
You need to provide Admob the app-ads.txt. Instructions are available when you click to see all apps. You should see a tab app-ads.txt. If your app's website is e.g. example.com, the file needs to be available at example.com/app-ads.txt.
If you want to serve it from expo-web, expo has a public directory. Put it there.
Personally, I have a static website rendered with docusaurus, served with cloudflare pages. It serves for docs and privacy policy, and any app-ads, .well-known and other static files.
Configure Test Devices
When testing admob from your device, you need to let Admob know that it is your device. Admob will only show test ads on your device. You do that by saving your device's advertising id in Test Devices. It's a uuid that can't be all zeros. You'd see all zeros when user opts out of idfa.
iOS Devices
Apple makes it hard for you to get idfa. It can be obtained either by installing one of the idfa apps from the app store. There's also a way with Xcode, haven't tried it. I've used the idfa app.
Android Devices
Go to settings, then Ads, and copy the uuid at the bottom of the screen.
No need to configure emulators, Admob knows it's an emulator.
Configure User Consent
Go to Admob Privacy & Messaging and configure IDFA explainer, this is needed for ios apps. When you set your message, don't forget to link ios admob apps.

- You will also need to configure GDPR and US States consent, link your apps
This step cannot be skipped, otherwise admob ads won't be served!
Link Admob to Firebase
This is optional and only if you use firebase in your app. Linking admob to firebase enabled advanced analytics and ads segmentation.
To link, go to Admob app settings, linked services and select firebase.
You will have to redownload google service files.
Google Play Console
You need to configure Privacy settings for your app. Go to Console, select app, Monitor and improve, expand Policy and Programs, select App content. Declare that your app uses Ads, and that you collect device id.

AppStore Connect
Go to connect, select your app, then Privacy. Make sure that privacy policy url is set, declare that you collect device id, check anything that has advertising or ads option.
Add ATT Popup
This is required on iOS, and the full guide is here. Without the ATT popup, reviewer will not approve your app.
Expo App Config
Edit your expo-build-properties and make sure proguard doesn't obfuscate com.google.gms package. That package is important because it ensures compliance with privacy laws and obtains Advertising ID. Reason for improperly configure admob in production can sometimes be proguard:
[
"expo-build-properties",
{
"android": {
"enableProguardInReleaseBuilds": true,
"extraProguardRules":
"-keep class com.google.android.gms.** { *; }"
},
"ios": {
"useFrameworks": "static"
},
},
],
AdMob relies on the Google Mobile Ads SDK(com.google.android.gms) for ad integration. Other part, for ios, Google's AdMob SDK for iOS needs static frameworks, that's all I know.
Add react-native-google-mobile-ads to plugins:
[
'react-native-google-mobile-ads',
{
// App ID can be found in app settings
androidAppId: 'ca-app-pub-...',
iosAppId: 'ca-app-pub-...',
userTrackingUsageDescription: 'This identifier will be used to deliver personalized ads to you.',
skAdNetworkItems: [
'cstr6suwn9.skadnetwork',
'4fzdc2evr5.skadnetwork',
'4pfyvq9l8r.skadnetwork',
'2fnua5tdw4.skadnetwork',
'ydx93a7ass.skadnetwork',
'5a6flpkh64.skadnetwork',
'p78axxw29g.skadnetwork',
'v72qych5uu.skadnetwork',
'ludvb6z3bs.skadnetwork',
'cp8zw746q7.skadnetwork',
'3sh42y64q3.skadnetwork',
'c6k4g5qg8m.skadnetwork',
's39g8k73mm.skadnetwork',
'3qy4746246.skadnetwork',
'f38h382jlk.skadnetwork',
'hs6bdukanm.skadnetwork',
'v4nxqhlyqp.skadnetwork',
'wzmmz9fp6w.skadnetwork',
'yclnxrl5pm.skadnetwork',
't38b2kh725.skadnetwork',
'7ug5zh24hu.skadnetwork',
'gta9lk7p23.skadnetwork',
'vutu7akeur.skadnetwork',
'y5ghdn5j9k.skadnetwork',
'n6fk4nfna4.skadnetwork',
'v9wttpbfk9.skadnetwork',
'n38lu8286q.skadnetwork',
'47vhws6wlr.skadnetwork',
'kbd757ywx3.skadnetwork',
'9t245vhmpl.skadnetwork',
'eh6m2bh4zr.skadnetwork',
'a2p9lx4jpn.skadnetwork',
'22mmun2rn5.skadnetwork',
'4468km3ulz.skadnetwork',
'2u9pt9hc89.skadnetwork',
'8s468mfl3y.skadnetwork',
'klf5c3l5u5.skadnetwork',
'ppxm28t8ap.skadnetwork',
'ecpz2srf59.skadnetwork',
'uw77j35x4d.skadnetwork',
'pwa73g5rt2.skadnetwork',
'mlmmfzh3r3.skadnetwork',
'578prtvx9j.skadnetwork',
'4dzt52r2t5.skadnetwork',
'e5fvkxwrpn.skadnetwork',
'8c4e2ghe7u.skadnetwork',
'zq492l623r.skadnetwork',
'3rd42ekr43.skadnetwork',
'3qcr597p9d.skadnetwork',
],
},
],
Up to date list of skadnetwork items can be found here. skadnetwork is a privacy safe attribution framework from Apple, it is the only Apple-approved way to track app installs and campaign performance without relying on the very restricted IDFA.
The Code
Before showing any kind of advertisement, you need ask the user for consent, then you can initialize the ads instance. I use that show consent after att popup, and it's in the root layout. Put it wherever you think it's best, just it has to be before banners or interstitials are called.
export default function useShowConsent(onConsented: () => Promise<void>) {
const initializedRef = React.useRef(false);
const prepare = useCallback(async () => {
if (initializedRef.current) {
return;
}
try {
initializedRef.current = true;
const consentInfo = await AdsConsent.requestInfoUpdate();
if (consentInfo.isConsentFormAvailable && consentInfo.status === AdsConsentStatus.REQUIRED) {
await AdsConsent.showForm();
}
await onConsented(); // any custom code that needs to execute after
} catch (err) {
logger.error(err as Error, 'Error during ad consent process!');
}
try {
await mobileAds().initialize();
} catch (err) {
logger.error(err as Error, 'Could not initialize mobile ads!');
}
}, []);
useEffect(() => {
void prepare();
}, [prepare]);
}
After that you can initialize your ads.
It's best that you consult the docs for examples.
I also have a github repository demo and if you'd like to see it in action, take a look at my YouTube video.