Hoy os voy a enseñar cómo añadir Google Admob Ads a la última versión de Expo y React Native disponible en febrero de 2023.
Utilizaremos esta librería (https://docs.page/invertase/react-native-google-mobile-ads):
expo install react-native-google-mobile-ads
Opcional: Si usas ios y quieres implementar Static Frameworks añade esto a app.json e instala el plugin:
expo install expo-build-properties expo install expo-dev-client
Añadimos dentro de plugins de nuestro archivo app.json:
"plugins": [ ... [ "expo-build-properties", { "ios": { "useFrameworks": "static" } } ] ... ]
Añadimos en app.json (al final del fichero) fuera de expo:{}
"expo": { .... }, "react-native-google-mobile-ads": { "android_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx", "ios_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx" } } }
Indicaremos nuestro android_app_id y nuestro ios_app_id, obtenidos de Admob.
Una vez añadido todos estos datos, hay que ir a la carpeta de ios y ejecutar pod install:
npx pod-install expo run:ios
Para generar el proyecto en Android o actualizar las dependencias usando Expo:
expo run:android
Generamos prebuild:
expo prebuild
Una vez generado el proyecto nativo, podemos crear un build dev (Como crear un build development usando Expo EAS con React Native)
Instalamos el build dev nativo y continuamos.
Una vez listo el proyecto, lo arrancamos a partir de ahora con:
npx expo start --dev-client
Para que funcione correctamente con las últimas versiónes de iOS, tenemos que añadir user_tracking_usage_description dentro de react-native-google-mobile-ads:
"user_tracking_usage_description": "This identifier will be used to deliver personalized ads to you."
Quedando de la siguiente forma:
{ "react-native-google-mobile-ads": { "android_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx", "ios_app_id": "ca-app-pub-xxxxxxxx~xxxxxxxx", "user_tracking_usage_description": "This identifier will be used to deliver personalized ads to you." } }
Para solicitar el permiso al usuario usaremos la libreria react-native-permissions
- Primero la instalamos:
npm install --save react-native-permissions
Y luego creamos un componente de requestAdsPermissions:
import { check, request, PERMISSIONS, RESULTS } from 'react-native-permissions'; const result = await check(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY); if (result === RESULTS.DENIED) { // The permission has not been requested, so request it. await request(PERMISSIONS.IOS.APP_TRACKING_TRANSPARENCY); } const adapterStatuses = await mobileAds().initialize();
En caso de Expo podemos usar expo-tracking-transparency:
Primero tenemos que instalar expo-tracking-transparency:
npx expo install expo-tracking-transparency
En este ejemplo además tenemos que instalar react-native-async-storage:
npx expo install @react-native-async-storage/async-storage
Y ahora creamos el componente TrackingPermissions.js
import React, { useState, useEffect } from "react"; import { StyleSheet, Platform, View } from "react-native"; import { requestTrackingPermissionsAsync } from 'expo-tracking-transparency' import AsyncStorage from '@react-native-async-storage/async-storage'; //Componente boton const Request = () => { function guardarPermisoAnuncios(status) { AsyncStorage.setItem('cargarPermisoAnunciosLoad', status); } async function cargarPermisoAnuncios(funcionRetorno) { try { const value = await AsyncStorage.getItem('cargarPermisoAnunciosLoad'); funcionRetorno(value); } catch (error) { funcionRetorno(error); } } useEffect(() => { //request permissons only one canAskAgain = false cargarPermisoAnuncios(functionRetorno); function functionRetorno(permiso) { //alert(permiso); if (permiso != "1") { requestTrackingPermissionsAsync().then((e) => { guardarPermisoAnuncios("1"), console.log(e) }); } } //getPermissionsAsync().then((e) => console.log(e)); }, []); return ( null ) }; export default Request;
Para usarlo lo importamos:
import RequestTrackingAds from '../componentes/Anuncios/TrackingPermissions';
Y lo añadimos al tender del screen donde queremos que aparezca:
<RequestTrackingAds />
Ahora vamos a crear un Banner:
import React, { useState, useEffect } from "react"; import { StyleSheet, Text } from "react-native"; import mobileAds, { BannerAd, TestIds, BannerAdSize } from 'react-native-google-mobile-ads'; //Componente boton const Banner = (props) => { //Parametros de constructor se pasan por props const { texto, onPress, styleExtra = {} } = props; useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds initialized successfully"); }); }, []); return ( <BannerAd unitId={TestIds.BANNER} size={BannerAdSize.ANCHORED_ADAPTIVE_BANNER} /> ) }; export default Banner; const styles = StyleSheet.create({ });
Para usarlo lo importamos:
import Banner from '../componentes/Anuncios/Banner'
Y lo añadimos al render:
<Banner />
Interstitial:
import React, { useState, useEffect } from "react"; import { StyleSheet, Text } from "react-native"; import mobileAds, { InterstitialAd, TestIds, AdEventType } from 'react-native-google-mobile-ads'; const interstitial = InterstitialAd.createForAdRequest(TestIds.INTERSTITIAL, { }); //Componente boton const Interstitial = (props) => { //Parametros de constructor se pasan por props const { texto, onPress, styleExtra = {} } = props; const [loaded, setLoaded] = useState(false); useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds initialized successfully"); }); }, []); useEffect(() => { if (!loaded) { const unsubscribe = interstitial.addAdEventListener(AdEventType.LOADED, () => { setLoaded(true); }); // Start loading the interstitial straight away interstitial.load(); // Unsubscribe from events on unmount return unsubscribe; } }, [loaded]); useEffect(() => { if (loaded) { interstitial.show(); setLoaded(false); } }, [loaded]); }; export default Interstitial; const styles = StyleSheet.create({ });
Para usarlo lo importamos:
import Interstitial from '../componentes/Anuncios/Interstitial'
Y lo añadimos al render:
<Interstitial />
Rewarded
import React, { useState, useEffect } from "react"; import { StyleSheet, Text } from "react-native"; import mobileAds, { RewardedAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads'; const rewarded = RewardedAd.createForAdRequest(TestIds.REWARDED, { }); //Componente boton const Rewarded = (props) => { //Parametros de constructor se pasan por props const { texto, onPress, styleExtra = {} } = props; const [loaded, setLoaded] = useState(false); useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds initialized successfully"); }); }, []); useEffect(() => { if (!loaded) { const unsubscribeLoaded = rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => { setLoaded(true); }); const unsubscribeEarned = rewarded.addAdEventListener( RewardedAdEventType.EARNED_REWARD, reward => { console.log('User earned reward of ', reward); }, ); // Start loading the rewarded ad straight away rewarded.load(); // Unsubscribe from events on unmount return () => { unsubscribeLoaded(); unsubscribeEarned(); }; } }, [loaded]); useEffect(() => { if (loaded) { rewarded.show(); setLoaded(false); } }, [loaded]); }; export default Rewarded; const styles = StyleSheet.create({ });
Ahora importamos el componente:
import Rewarded from '../componentes/Anuncios/Rewarded'
Y lo inicializamos:
<Rewarded />
Rewarded Interstitial
import React, { useState, useEffect } from "react"; import { StyleSheet, Text } from "react-native"; import mobileAds, { RewardedInterstitialAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads'; const rewardedInterstitial = RewardedInterstitialAd.createForAdRequest(TestIds.REWARDED_INTERSTITIAL, { }); //Componente boton const Rewarded = (props) => { //Parametros de constructor se pasan por props const { texto, onPress, styleExtra = {} } = props; const [loaded, setLoaded] = useState(false); useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds initialized successfully"); }); }, []); useEffect(() => { if (!loaded) { const unsubscribeLoaded = rewardedInterstitial.addAdEventListener( RewardedAdEventType.LOADED, () => { setLoaded(true); }, ); const unsubscribeEarned = rewardedInterstitial.addAdEventListener( RewardedAdEventType.EARNED_REWARD, reward => { console.log('User earned reward of ', reward); }, ); // Start loading the rewarded interstitial ad straight away rewardedInterstitial.load(); // Unsubscribe from events on unmount return () => { unsubscribeLoaded(); unsubscribeEarned(); }; } }, [loaded]); useEffect(() => { if (loaded) { rewardedInterstitial.show(); setLoaded(false); } }, [loaded]); }; export default Rewarded; const styles = StyleSheet.create({ });
Para usarlo lo importamos:
import RewardedInterstitialAd from '../componentes/Anuncios/RewardedInterstitial'
Y lo añadimos al render:
<RewardedInterstitialAd />
Open APP:
import { useState, useEffect } from "react"; import { AppState, AppStateStatus } from "react-native"; import mobileAds, { AppOpenAd, AdEventType, TestIds, } from 'react-native-google-mobile-ads'; const appOpenAd = AppOpenAd.createForAdRequest(TestIds.APP_OPEN, {}); //TestIds.APP_OPEN export const useOpenAppAds = () => { const [appState, setAppState] = useState<AppStateStatus>(AppState.currentState); const [loaded, setLoaded] = useState(false); useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds OpenAPP initialized successfully"); }); }, []); useEffect(() => { const handleAppStateChange = (nextAppState: AppStateStatus) => { if (appState.match(/inactive|background/) && nextAppState === 'active') { console.log('App has come to the foreground!'); if (loaded) { showAppOpenAd(); }else{ loadAd(); } } setAppState(nextAppState); }; const appStateListener = AppState.addEventListener('change', handleAppStateChange); return () => { appStateListener.remove(); }; }, [appState, loaded]); const loadAd = () => { if (!loaded) { console.log("OpenAPP try to Ad load"); const unsubscribeLoaded = appOpenAd.addAdEventListener(AdEventType.LOADED, () => { console.log("OpenAPP Ad loaded"); setLoaded(true); }); const unsubscribeError = appOpenAd.addAdEventListener(AdEventType.ERROR, (error) => { console.log("OpenAPP Ad failed to load with error: ", error); }); appOpenAd.load(); return () => { unsubscribeLoaded(); unsubscribeError(); }; } } const showAppOpenAd = () => { console.log("OpenAPP Ad show"); appOpenAd.show(); setLoaded(false); loadAd(); // Cargar un nuevo anuncio después de mostrar uno }; return { loadAd, showAppOpenAd, loaded }; };
Para utilizar OpenAPP tenemos que añadirlo cuando la APP se abra.
Para ello lo mejor sería integrarlo dentro de un context y realizar la llamada que inicializa el proceso:
const { showAppOpenAd, loadAd, loaded } = useOpenAppAds(); // Usar el hook useEffect(() => { console.log("Loaded: " + loaded); if (!loaded) { loadAd(); } }, [loaded]);
*Extra:
Si queremos que los anuncios interstitiales se carguen cuándo se realice un evento, podemos crear una función que los inicialice y lance, para ello haremos esta modificación:
import React, { useState, useEffect } from "react"; import { StyleSheet, Text } from "react-native"; import mobileAds, { InterstitialAd, TestIds, AdEventType } from 'react-native-google-mobile-ads'; import { getVideoAds } from '../../util/Ids_anuncios'; const interstitial = InterstitialAd.createForAdRequest(getVideoAds(), { }); var setLoadAd = null; //Componente boton const Banner = (props) => { //Parametros de constructor se pasan por props const { texto, onPress, styleExtra = {} } = props; const [loaded, setLoaded] = useState(false); const [initLoad, setInitLoad] = useState(false); setLoadAd = setInitLoad; useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds initialized successfully"); }); }, []); useEffect(() => { if (initLoad) { const unsubscribe = interstitial.addAdEventListener(AdEventType.LOADED, () => { setLoaded(true); }); // Start loading the interstitial straight away interstitial.load(); // Unsubscribe from events on unmount return unsubscribe; } }, [initLoad]); useEffect(() => { if (loaded) { interstitial.show(); setLoaded(false); } }, [loaded]); }; export default Banner; export function initLoadInterstitial() { setLoadAd(true); } const styles = StyleSheet.create({ });
De esta forma tendremos que llamar a la función initLoadInterstitial() desde el Screen o botón en el que queramos visualizar el anuncio.
import Interstitial, { initLoadInterstitial } from '../componentes/Anuncios/Interstitial';
Ejecutar:
useEffect(() => { initLoadInterstitial(); }, []);
Así quedarían los anuncios Rewarded:
import React, { useState, useEffect } from "react"; import { StyleSheet, Text } from "react-native"; import mobileAds, { RewardedAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads'; import { getBonificado } from '../../util/Ids_anuncios'; const rewarded = RewardedAd.createForAdRequest(getBonificado(), { }); var setLoadAd = null; //Componente boton const Rewarded = (props) => { //Parametros de constructor se pasan por props const { texto, onPress, styleExtra = {} } = props; const [loaded, setLoaded] = useState(false); const [initLoad, setInitLoad] = useState(false); useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds initialized successfully"); }); }, []); useEffect(() => { if (initLoad) { const unsubscribeLoaded = rewarded.addAdEventListener(RewardedAdEventType.LOADED, () => { setLoaded(true); }); const unsubscribeEarned = rewarded.addAdEventListener( RewardedAdEventType.EARNED_REWARD, reward => { console.log('User earned reward of ', reward); }, ); // Start loading the rewarded ad straight away rewarded.load(); // Unsubscribe from events on unmount return () => { unsubscribeLoaded(); unsubscribeEarned(); }; } }, [initLoad]); useEffect(() => { if (loaded) { rewarded.show(); setLoaded(false); } }, [loaded]); }; export default Rewarded; export function initLoadRewardedAds() { setLoadAd(true); } const styles = StyleSheet.create({ });
Interstitial Rewarded:
import React, { useState, useEffect } from "react"; import { StyleSheet, Text } from "react-native"; import mobileAds, { RewardedInterstitialAd, RewardedAdEventType, TestIds } from 'react-native-google-mobile-ads'; const rewardedInterstitial = RewardedInterstitialAd.createForAdRequest(TestIds.REWARDED_INTERSTITIAL, { }); var setLoadAd = null; //Componente boton const Rewarded = (props) => { //Parametros de constructor se pasan por props const { texto, onPress, styleExtra = {} } = props; const [loaded, setLoaded] = useState(false); const [initLoad, setInitLoad] = useState(false); useEffect(() => { mobileAds() .initialize() .then(adapterStatuses => { console.log("MobileAds initialized successfully"); }); }, []); useEffect(() => { if (initLoad) { const unsubscribeLoaded = rewardedInterstitial.addAdEventListener( RewardedAdEventType.LOADED, () => { setLoaded(true); }, ); const unsubscribeEarned = rewardedInterstitial.addAdEventListener( RewardedAdEventType.EARNED_REWARD, reward => { console.log('User earned reward of ', reward); }, ); // Start loading the rewarded interstitial ad straight away rewardedInterstitial.load(); // Unsubscribe from events on unmount return () => { unsubscribeLoaded(); unsubscribeEarned(); }; } }, [initLoad]); useEffect(() => { if (loaded) { rewardedInterstitial.show(); setLoaded(false); } }, [loaded]); }; export default Rewarded; export function initLoadRewardedInterstititalAds() { setLoadAd(true); } const styles = StyleSheet.create({ });
Ingeniero en Informática, Investigador, me encanta crear cosas o arreglarlas y darles una nueva vida. Escritor y poeta. Más de 20 APPs publicadas y un libro en Amazon.