Añadir Google Admob ads a React Native y expo 47

Tiempo de lectura: 7 minutos

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({

});

Deja un comentario