# Inicio

Bienvenido a la documentación oficial de Wortise.

Aquí encontrará las instrucciones para integrar nuestro SDK para todas las plataformas soportadas actualmente:

| Plataforma       | Enlace                                    |
| ---------------- | ----------------------------------------- |
| **Android**      | [Guía](/android-sdk/integracion-del-sdk)  |
| **iOS**          | [Guía](/ios-sdk/integracion-del-sdk)      |
| **Unity**        | [Guía](/unity-sdk/integracion-del-sdk)    |
| **Flutter**      | [Guía](/flutter-sdk/integracion-del-sdk)  |
| **React Native** | [Guía](/react-native/integracion-del-sdk) |
| **Web**          | [Guía](/web-sdk/integracion-del-sdk)      |


# Ad Units de prueba

Para poder comprobar de manera fácil y sencilla si la integración del SDK funciona correctamente, ofrecemos los siguientes ad units de prueba que siempre entregan un anuncio:

| Formato          | Ad Unit ID          |
| ---------------- | ------------------- |
| **App Open**     | `test-app-open`     |
| **Banner**       | `test-banner`       |
| **Interstitial** | `test-interstitial` |
| **Rewarded**     | `test-rewarded`     |
| **Native**       | `test-native`       |

En caso de no funcionar, contáctanos para que podamos revisar los problemas de la integración y/o comprobar si pudiera haber un problema con alguno de estos ad units.


# Google Data Safety

Si tienes una app publicada en Google Play, debes ser transparente con los usuarios acerca de cómo se manejan sus datos. Esto significa revelar el acceso, recopilación y uso de los datos que realiza tu app, y limitar dicho uso a los propósitos mencionados.

Para cumplir con las políticas de Google Play, es necesario rellenar el formulario que se puede encontrar en la sección "[Seguridad de los datos](https://play.google.com/console/app/app-content/summary)", dentro de la página "[Contenido de la aplicación](https://play.google.com/console/app/app-content/summary)" (Políticas > Contenido de la aplicación).

La información indicada en dicho formulario será mostrada en la ficha de Google Play para ayudar a los usuarios a entender cómo se manejan sus datos.

A continuación, se muestran las respuestas que se deben proporcionar en relación al SDK de Wortise. Recuerda incluir cualquier información adicional respecto al uso de los datos realizado por la propia app u otros partners.

## Recogida de datos y seguridad

| Pregunta / Campo                                                                     | Respuesta |
| ------------------------------------------------------------------------------------ | --------- |
| ¿Tu aplicación recoge o comparte datos de usuario de alguno de los tipos requeridos? | ✅         |
| ¿Los datos de usuario que recoge tu aplicación se cifran en tránsito?                | ✅         |
| ¿Ofreces a los usuarios alguna forma de solicitar que se eliminen sus datos?         | ✅         |

## Tipos de datos

Selecciona todos los tipos de datos recopilados o compartidos por tu app.

| Categoría                                 | Tipo de dato                                        | ¿Se recopila? |
| ----------------------------------------- | --------------------------------------------------- | ------------- |
| Ubicación                                 | <p>Ubicación aproximada</p><p>Ubicación precisa</p> | <p>✅<br>✅</p> |
| Información personal                      | n/a                                                 | No            |
| Información financiera                    | n/a                                                 | No            |
| Salud y fitness                           | n/a                                                 | No            |
| Mensajes                                  | n/a                                                 | No            |
| Fotos y vídeos                            | n/a                                                 | No            |
| Archivos de audio                         | n/a                                                 | No            |
| Archivos y documentos                     | n/a                                                 | No            |
| Calendar                                  | n/a                                                 | No            |
| Contactos                                 | n/a                                                 | No            |
| Actividad en aplicaciones                 | n/a                                                 | No            |
| Navegación web                            | n/a                                                 | No            |
| Información y rendimiento de aplicaciones | n/a                                                 | No            |
| IDs de dispositivo o de otro tipo         | IDs de dispositivo o de otro tipo                   | ✅             |

## Uso y gestión de los datos

En relación a Wortise, las respuestas a todas las preguntas serían las siguientes:

| Pregunta / Campo                                                                                     | Respuesta                                                 |
| ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
| Se recogen                                                                                           | ✅                                                         |
| Se comparten                                                                                         | ✅                                                         |
| ¿Se tratan estos datos de forma temporal?                                                            | No                                                        |
| ¿Son estos datos necesarios para usar tu aplicación o pueden los usuarios elegir si se recogen o no? | Los usuarios pueden elegir si se recogen estos datos o no |

| Propósito                                       | Respuesta |
| ----------------------------------------------- | --------- |
| Funcionalidad de la aplicación                  | No        |
| Análisis                                        | ✅         |
| Comunicaciones del desarrollador                | No        |
| Publicidad o marketing                          | ✅         |
| Prevención de fraudes, seguridad y cumplimiento | ✅         |
| Personalización                                 | No        |
| Gestión de cuentas                              | No        |


# Integración del SDK

## Configurar proyecto

Dependiendo del lenguaje que utilice el proyecto en los scripts Gradle, debes seguir los pasos de la pestaña correspondiente:

{% tabs %}
{% tab title="Groovy" %}
En primer lugar, es necesario añadir los siguientes repositorios Maven dentro del bloque `repositories` del fichero `settings.gradle`:

{% hint style="info" %}
En los proyectos donde todavía se utilice una estructura antigua, el bloque `repositories` se encontrará en el fichero `build.gradle` ubicado a nivel de **app.**
{% endhint %}

```groovy
repositories {
    maven { url 'https://maven.wortise.com/artifactory/public' }

    maven { url 'https://android-sdk.is.com/' }
    maven { url 'https://artifact.bytedance.com/repository/pangle' }
    maven { url 'https://cboost.jfrog.io/artifactory/chartboost-ads/' }
}
```

Una vez añadidos, se puede proceder a integrar el SDK . Para ello, hay que introducir la siguiente línea dentro del bloque `dependencies` del fichero `build.gradle` ubicado a nivel de app:

```groovy
implementation 'com.wortise:android-sdk:1.7.2'
```

En caso de no tenerlo ya, es necesario activar la compatibilidad con Java 8 en el proyecto. Esto se puede lograr añadiendo estas líneas adicionales dentro del bloque `android`, también en el mismo fichero `build.gradle`:

```groovy
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
```

{% endtab %}

{% tab title="Kotlin" %}
En primer lugar, es necesario añadir los siguientes repositorios Maven dentro del bloque `repositories` del fichero `settings.gradle.kts`:

```kotlin
dependencyResolutionManagement {
    repositories {
        maven { url = uri("https://maven.wortise.com/artifactory/public") }

        maven { url = uri("https://android-sdk.is.com/") }
        maven { url = uri("https://artifact.bytedance.com/repository/pangle") }
        maven { url = uri("https://cboost.jfrog.io/artifactory/chartboost-ads/") }
    }
}
```

Una vez añadidos, se puede proceder a integrar el SDK . Para ello, hay que introducir la siguiente línea dentro del bloque `dependencies` del fichero `build.gradle.kts` ubicado a nivel de app:

```kotlin
implementation("com.wortise:android-sdk:1.7.2")
```

En caso de no tenerlo ya, es necesario activar la compatibilidad con Java 8 en el proyecto. Esto se puede lograr añadiendo estas líneas adicionales dentro del bloque `android`, también en el mismo fichero `build.gradle.kts`:

```kotlin
compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}
```

{% endtab %}
{% endtabs %}

## Configurar Manifest

Es necesario agregar el siguiente elemento `<meta-data>` en el fichero `AndroidManifest.xml`, dentro del bloque `<application>`, con el ID de aplicación de Google como valor:

```xml
<manifest>
    ...
    <application>
        ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>
```

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

## Solicitar consentimiento

{% hint style="success" %}
Es **muy recomendable** solicitar consentimiento al usuario para poder mostrar anuncios personalizados. Esto permitirá mostrar contenido que resulte de mayor interés y generar ingresos superiores.
{% endhint %}

Puede consultar el siguiente apartado para implementar esta solicitud y obtener el consentimiento de los usuarios: [Consentimiento del usuario](/android-sdk/consentimiento-del-usuario)

## Inicializar SDK

Nuestra recomendación es inicializar el SDK en la clase `Application` de la app, aunque también se puede realizar en algún `Activity` principal.

Para ello, es necesario integrar el siguiente código en el método `onCreate`:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
WortiseSdk.initialize(this, "tu app key")
```

{% endtab %}

{% tab title="Java" %}

```java
WortiseSdk.initialize(this, "tu app key");
```

{% endtab %}
{% endtabs %}

### Listener de inicialización

Existen dos maneras posibles para conocer cuando el SDK finaliza su inicialización:

#### Pasando un listener como último parámetro del método `WortiseSdk.initialize`

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
WortiseSdk.initialize(this, "tu app key") {
    // Este listener será invocado cuando la inicialización finalice
}
```

{% endtab %}

{% tab title="Java" %}

```java
WortiseSdk.initialize(this, "tu app key", () -> {
    // Este listener será invocado cuando la inicialización finalice
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}

#### Utilizando el método `WortiseSdk.wait`

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
WortiseSdk.wait {
    // Este listener será invocado cuando la inicialización finalice
}
```

{% endtab %}

{% tab title="Java" %}

```java
WortiseSdk.wait(() -> {
    // Este listener será invocado cuando la inicialización finalice
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}

## Modo de prueba

Para verificar la integración, el SDK ofrece un modo de prueba (*test mode*) que permite que la app siempre reciba anuncios.

Además de la opción que hay disponible en nuestro dashboard, es posible activar este modo de prueba programáticamente, desde el propio SDK, utilizando el siguiente código:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
AdSettings.testEnabled = true
```

{% endtab %}

{% tab title="Java" %}

```java
AdSettings.setTestEnabled(true);
```

{% endtab %}
{% endtabs %}


# App Open

Los anuncios de carga de aplicación (App Open) son un formato especial cuyo propósito es permitir la monetización de las pantalla de carga de las aplicaciones.

Estos anuncios se pueden cerrar en cualquier momento y están pensados para ser mostrados cuando la aplicación realiza una transición a primer plano.

## **Integración**

Este formato de anuncio solo se puede integrar a través de código, implementando cualquiera de las dos integraciones posibles que se describen a continuación.

### **Manual**

En este tipo de integración, es necesario crear una instancia de la clase `AppOpenAd` y utilizar los métodos `loadAd()` y `showAd()` para realizar la carga y mostrado del anuncio bajo demanda. El publisher es el responsable de decidir cuándo se debe mostrar el anuncio e implementar la lógica necesaria.

A continuación, se muestra un ejemplo sencillo de integración:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var appOpenAd: AppOpenAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        appOpenAd = AppOpenAd(this, "Ad Unit ID de Wortise").also {
	    it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        appOpenAd?.destroy()
    }
    
    fun showAppOpen() {
        if (appOpenAd?.isAvailable == true) {
            appOpenAd?.showAd(this)
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private AppOpenAd mAppOpenAd;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mAppOpenAd = new AppOpenAd(this, "Ad Unit ID de Wortise");
        mAppOpenAd.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mAppOpenAd.destroy(this);
    }
    
    public void showAppOpen() {
        if (mAppOpenAd.isAvailable()) {
            mAppOpenAd.showAd(this);
        }
    }
}
```

{% endtab %}
{% endtabs %}

Además, la clase `AppOpenAd` ofrece los siguientes métodos adicionales para configurar su comportamiento:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// Establece si se debe cargar un nuevo anuncio tras cerrar el anterior
appOpenAd.autoReload = true

// Muestra un anuncio inmediatamente si está disponible. En caso contrario,
// solicita la carga de un nuevo anuncio
appOpenAd.tryToShowAd(activity)
```

{% endtab %}

{% tab title="Java" %}

```java
// Establece si se debe cargar un nuevo anuncio tras cerrar el anterior
mAppOpenAd.setAutoReload(true);

// Muestra un anuncio inmediatamente si está disponible. En caso contrario,
// solicita la carga de un nuevo anuncio
mAppOpenAd.tryToShowAd(activity);
```

{% endtab %}
{% endtabs %}

### **Vía Manager**

El SDK ofrece una implementación estándar de App Open para facilitar la integración de este formato de anuncios.

Para realizar este tipo de integración, es necesario que la aplicación extienda la clase `Application` y, dentro de ella, crear una instancia de `AppOpenManager`, tal y como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MyApplication : Application() {

    private val appOpenManager by lazy {
        AppOpenManager(this, "Ad Unit ID de Wortise")
    }

    override fun onCreate() {
        ...
        appOpenManager.loadAd()
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MyApplication extends Application {

    private AppOpenManager mAppOpenManager;

    @Override
    public void onCreate() {
        ...
        mAppOpenManager = new AppOpenManager(this, "Ad Unit ID de Wortise");
        mAppOpenManager.loadAd();
    }
}
```

{% endtab %}
{% endtabs %}

Con esta simple integración, la aplicación mostrará anuncios cada vez que se realice una transición de segundo a primer plano.

Igualmente, la clase `AppOpenManager` ofrece los mismos métodos que `AppOpenAd` para configurar su comportamiento y mostrar los anuncios bajo demanda.

## **Configuración del listener**

Como en el resto de formatos, se puede añadir un listener para recibir los diferentes eventos\
que sucedan durante el ciclo de vida del anuncio. Para ello, es necesario implementar la interfaz `AppOpenAd.Listener` como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
appOpenAd.listener = object : AppOpenAd.Listener() {

    override fun onAppOpenClicked(ad: AppOpenAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    override fun onAppOpenDismissed(ad: AppOpenAd) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    override fun onAppOpenFailedToLoad(ad: AppOpenAd, error: AdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    override fun onAppOpenFailedToShow(ad: AppOpenAd, error: AdError) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }
    
    override fun onAppOpenImpression(ad: AppOpenAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }

    override fun onAppOpenLoaded(ad: AppOpenAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    override fun onAppOpenRevenuePaid(ad: AppOpenAd,
                                      data: RevenueData) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
    
    override fun onAppOpenShown(ad: AppOpenAd) {
        // Invocado cuando el anuncio ha sido mostrado
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mAppOpenAd.setListener(new AppOpenAd.Listener() {
    @Override
    public void onAppOpenClicked(@NonNull AppOpenAd ad) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    @Override
    public void onAppOpenDismissed(@NonNull AppOpenAd ad) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    @Override
    public void onAppOpenFailedToLoad(@NonNull AppOpenAd ad,
                                      @NonNull AdError error) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    @Override
    public void onAppOpenFailedToShow(@NonNull AppOpenAd ad,
                                      @NonNull AdError error) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }
    
    @Override
    public void onAppOpenImpression(@NonNull AppOpenAd ad) {
        // Invocado cuando el anuncio ha generado una impresión
    }
    
    @Override
    public void onAppOpenLoaded(@NonNull AppOpenAd ad) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    @Override
    public void onAppOpenRevenuePaid(@NonNull AppOpenAd ad,
                                     @NonNull Revenuedata data) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
    
    @Override
    public void onAppOpenShown(@NonNull AppOpenAd ad) {
        // Invocado cuando el anuncio ha sido mostrado
    }
});
```

{% endtab %}
{% endtabs %}


# Banner

Los anuncios de banner son anuncios de imagen o de texto rectangulares que ocupan un lugar dentro del diseño de una aplicación. Permanecen en la pantalla mientras los usuarios interactúan con la aplicación y pueden actualizarse automáticamente después de un cierto período de tiempo. Si eres nuevo en la publicidad móvil, son una excelente opción para comenzar.

## **Integración**

Existen dos formas diferentes de realizar la integración de un banner: usando código o añadiendo la vista de banner en un layout. A continuación se muestran ejemplos de ambas opciones:

### **Layout XML**

```markup
<com.wortise.ads.banner.BannerAd
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:adSize="HEIGHT_50"
    app:adUnitId="Ad Unit ID de Wortise" />
```

El widget tiene soporte para los siguientes parámetros:

| Parámetro               | Tipo    | Requerido | Descripción                                                                                                                   |
| ----------------------- | ------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **app:adUnitId**        | String  | **Si**    | El ID del ad unit a asignar al banner                                                                                         |
| **app:adSize**          | AdSize  | No        | Tamaño máximo (altura) para el banner. Los posibles valores para este parámetro se encuentran declarados en la clase `AdSize` |
| **app:autoRefreshTime** | Integer | No        | Valor en segundos que representa el tiempo que deberá transcurrir para que se realice la carga de un nuevo anuncio banner     |

### **Código**

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var bannerAd: BannerAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        bannerAd = BannerAd(this).also {
	        it.adSize = AdSize.HEIGHT_50
	        it.adUnitId = "<Ad Unit ID de Wortise>"
	        
	        // Por ejemplo, añadímos el BannerAd en un FrameLayout
	        val frameLayout = findViewById<FrameLayout>(R.id.frame)
	        frameLayout.addView(it)
	        
	        it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        bannerAd?.destroy()
    }
    
    override fun onPause() {
        ...
        bannerAd?.pause()
    }
    
    override fun onResume() {
        ...
        bannerAd?.resume()
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private BannerAd mBannerAd;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mBannerAd = new BannerAd(this);
        mBannerAd.setAdSize(AdSize.HEIGHT_50);
        mBannerAd.setAdUnitId("Ad Unit ID de Wortise");
        
        // Por ejemplo, añadímos el BannerAd en un FrameLayout
        FrameLayout frameLayout = findViewById(R.id.frame);
        frameLayout.addView(mAdView);

        mBannerAd.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mBannerAd.destroy();
    }
    
    @Override
    public void onPause() {
        ...
        mBannerAd.pause();
    }
    
    @Override
    public void onResume() {
        ...
        mBannerAd.resume();
    }
}
```

{% endtab %}
{% endtabs %}

La clase `BannerAd` ofrece los siguientes métodos para configurar la instancia:

| Método                               | Requerido | Descripción                                                                                                                   |
| ------------------------------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `setAdUnitId(String)`                | **Si**    | Asigna un ad unit al banner                                                                                                   |
| `setAdSize(AdSize)`                  | No        | Tamaño máximo (altura) para el banner. Los posibles valores para este parámetro se encuentran declarados en la clase `AdSize` |
| `setAutoRefreshTime(long)`           | No        | Valor en milisegundos que representa el tiempo que deberá transcurrir para que se realice la carga de un nuevo anuncio banner |
| `setAutoRefreshTime(long, TimeUnit)` | No        | Igual que el método anterior, pero permitiendo especificar la unidad de tiempo del valor indicado                             |

## **Banners adaptativos**

Los banners adaptativos son un nuevo formato de banner que se caracteriza por adaptar el tamaño de los anuncios según el dispositivo y la interfaz de la aplicación, para lograr maximizar el rendimiento.

Actualmente existe soporte para dos tipos de banners adaptativos:

### Anclados

Este tipo de banner está diseñado para reemplazar a los banners tradicionales de 320x50 y ser posicionado en la parte superior o inferior de la pantalla.

Para hacer uso de este formato, se debe utilizar el siguiente código para configurar un tamaño adaptativo, indicando la anchura del banner:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// Es necesario especificar la anchura del banner
val adSize = AdSize.getAnchoredAdaptiveBannerAdSize(context, width)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
// Es necesario especificar la anchura del banner
AdSize adSize = AdSize.getAnchoredAdaptiveBannerAdSize(context, width);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

Alternativamente, se puede implementar esta otra opción para que el SDK calcule automáticamente la anchura del banner, donde se deberá pasar la propia instancia del `BannerAd` o el `View` que va a contener a dicho banner:

{% hint style="warning" %}
En esta opción, es **muy recomendable** que el `View` que se pase al método ya se encuentre agregado al layout de la app, para que el SDK pueda calcular correctamente todas las dimensiones.
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val adSize = AdSize.getAnchoredAdaptiveBannerAdSize(view)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
AdSize adSize = AdSize.getAnchoredAdaptiveBannerAdSize(view);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

### Inline

Este otro tipo de banner, en comparación con los anclados, está diseñado para tener una altura variable y ser posicionado dentro de un contenido desplazable.

En este caso, se debe utilizar un código como el siguiente para configurar un tamaño adaptativo apropiado:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val maxHeight = 200

// Es necesario especificar la anchura del banner. La altura máxima es un
// parámetro opcional
val adSize = AdSize.getInlineAdaptiveBannerAdSize(context, width, maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
int maxHeight = 200;

// Es necesario especificar la anchura del banner. La altura máxima es un
// parámetro opcional
AdSize adSize = AdSize.getInlineAdaptiveBannerAdSize(
    context, width, maxHeight
);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

Alternativamente, se puede implementar esta otra opción para que el SDK calcule automáticamente la anchura del banner, donde se deberá pasar la propia instancia del `BannerAd` o el `View` que va a contener a dicho banner:

{% hint style="warning" %}
En esta opción, es **muy recomendable** que el `View` que se pase al método ya se encuentre agregado al layout de la app, para que el SDK pueda calcular correctamente todas las dimensiones.
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val maxHeight = 200

val adSize = AdSize.getInlineAdaptiveBannerAdSize(view, maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
int maxHeight = 200;

AdSize adSize = AdSize.getInlineAdaptiveBannerAdSize(view, maxHeight);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

## **Configuración del listener**

Se puede añadir un listener a cualquier instancia de `BannerAd` para recibir los diferentes eventos que sucedan durante su ciclo de vida. Para ello, es necesario implementar la interfaz `BannerAd.Listener`, como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
bannerAd.listener = object : BannerAd.Listener() {

    override fun onBannerClicked(ad: BannerAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    override fun onBannerFailedToLoad(ad: BannerAd, error: AdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    override fun onBannerImpression(ad: BannerAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }
    
    override fun onBannerLoaded(ad: BannerAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    override fun onBannerRevenuePaid(ad: BannerAd, data: Revenuedata) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mBannerAd.setListener(new BannerAd.Listener() {
    @Override
    public void onBannerClicked(@NonNull BannerAd ad) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    @Override
    public void onBannerFailedToLoad(@NonNull BannerAd ad,
                                     @NonNull AdError error) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    @Override
    public void onBannerImpression(@NonNull BannerAd ad) {
        // Invocado cuando el anuncio ha generado una impresión
    }
    
    @Override
    public void onBannerLoaded(@NonNull BannerAd ad) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    @Override
    public void onBannerRevenuePaid(@NonNull BannerAd ad,
                                    @NonNull Revenuedata data) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
});
```

{% endtab %}
{% endtabs %}


# Interstitial

## Integración

Al contrario que los banners, los intersticiales únicamente se pueden integrar a través de código. A continuación se muestra un sencillo ejemplo para entender su funcionamiento:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var interstitialAd: InterstitialAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        interstitialAd = InterstitialAd(this, "Ad Unit ID de Wortise").also {
	    it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        interstitialAd?.destroy()
    }
    
    fun showInterstitial() {
        if (interstitialAd?.isAvailable == true) {
            interstitialAd?.showAd(this)
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private InterstitialAd mInterstitial;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mInterstitial = new InterstitialAd(this, "Ad Unit ID de Wortise");
        mInterstitial.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mInterstitial.destroy();
    }
    
    public void showInterstitial() {
        if (mInterstitial.isAvailable()) {
            mInterstitial.showAd(this);
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Configuración del listener**

Al igual que en el caso de los banners, se puede añadir un listener para recibir los diferentes eventos que sucedan durante el ciclo de vida del intersticial. Para ello, es necesario implementar la interfaz `InterstitialAd.Listener` como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
interstitialAd.listener = object : InterstitialAd.Listener() {

    override fun onInterstitialClicked(ad: InterstitialAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    override fun onInterstitialDismissed(ad: InterstitialAd) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    override fun onInterstitialFailedToLoad(ad: InterstitialAd,
                                            error: AdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    override fun onInterstitialFailedToShow(ad: InterstitialAd,
                                            error: AdError) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }

    override fun onInterstitialImpression(ad: InterstitialAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }

    override fun onInterstitialLoaded(ad: InterstitialAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    override fun onInterstitialRevenuePaid(ad: InterstitialAd,
                                           data: Revenuedata) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
    
    override fun onInterstitialShown(ad: InterstitialAd) {
        // Invocado cuando el anuncio ha sido mostrado
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mInterstitial.setListener(new InterstitialAd.Listener() {
    @Override
    public void onInterstitialClicked(@NonNull InterstitialAd ad) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    @Override
    public void onInterstitialDismissed(@NonNull InterstitialAd ad) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    @Override
    public void onInterstitialFailedToLoad(@NonNull InterstitialAd ad,
                                           @NonNull AdError error) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    @Override
    public void onInterstitialFailedToShow(@NonNull InterstitialAd ad,
                                           @NonNull AdError error) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }
    
    @Override
    public void onInterstitialImpression(@NonNull InterstitialAd ad) {
        // Invocado cuando el anuncio ha generado una impresión
    }
    
    @Override
    public void onInterstitialLoaded(@NonNull InterstitialAd ad) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    @Override
    public void onInterstitialRevenuePaid(@NonNull InterstitialAd ad,
                                      @NonNull Revenuedata data) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
    
    @Override
    public void onInterstitialShown(@NonNull InterstitialAd ad) {
        // Invocado cuando el anuncio ha sido mostrado
    }
});
```

{% endtab %}
{% endtabs %}


# Rewarded

## Integración

Los anuncios recompensados (rewarded), al igual que los intersticiales, únicamente se pueden integrar a través de código. A continuación se muestra un sencillo ejemplo para entender su funcionamiento:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var rewardedAd: RewardedAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        rewardedAd = RewardedAd(this, "Ad Unit ID de Wortise").also {
	          it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        rewardedAd?.destroy()
    }
    
    fun showInterstitial() {
        if (rewardedAd?.isAvailable == true) {
            rewardedAd?.showAd(this)
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private RewardedAd mRewarded;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mRewarded = new RewardedAd(this, "Ad Unit ID de Wortise");
        mRewarded.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mRewarded.destroy();
    }
    
    public void showInterstitial() {
        if (mRewardedrstitial.isAvailable()) {
            mRewarded.showAd(this);
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Configuración del listener**

Como en el resto de formatos, se puede añadir un listener para recibir los diferentes eventos\
que sucedan durante el ciclo de vida del anuncio recompensado. Para ello, es necesario implementar la interfaz `RewardedAd.Listener` como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
rewardedAd.listener = object : RewardedAd.Listener() {

    override fun onRewardedClicked(ad: RewardedAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    override fun onRewardedCompleted(ad: RewardedAd, reward: Reward) {
        // Invocado cuando el anuncio ha sido completado
    }
    
    override fun onRewardedDismissed(ad: RewardedAd) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    override fun onRewardedFailedToLoad(ad: RewardedAd, error: AdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    override fun onRewardedFailedToShow(ad: RewardedAd, error: AdError) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }
    
    override fun onRewardedImpression(ad: RewardedAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }

    override fun onRewardedLoaded(ad: RewardedAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    override fun onRewardedRevenuePaid(ad: RewardedAd,
                                       data: Revenuedata) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
    
    override fun onRewardedShown(ad: RewardedAd) {
        // Invocado cuando el anuncio ha sido mostrado
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mRewarded.setListener(new RewardedAd.Listener() {
    @Override
    public void onRewardedClicked(@NonNull RewardedAd ad) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    @Override
    public void onRewardedCompleted(@NonNull RewardedAd ad,
                                    @NonNull Reward reward) {
        // Invocado cuando el anuncio ha sido completado
    }
    
    @Override
    public void onRewardedDismissed(@NonNull RewardedAd ad) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    @Override
    public void onRewardedFailedToLoad(@NonNull RewardedAd ad,
                                       @NonNull AdError error) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }
    
    @Override
    public void onRewardedFailedToShow(@NonNull RewardedAd ad,
                                       @NonNull AdError error) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }
    
    @Override
    public void onRewardedImpression(@NonNull Rewar ad) {
        // Invocado cuando el anuncio ha generado una impresión
    }
    
    @Override
    public void onRewardedLoaded(@NonNull RewardedAd ad) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    @Override
    public void onRewardedRevenuePaid(@NonNull RewardedAd ad,
                                      @NonNull Revenuedata data) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
    
    @Override
    public void onRewardedShown(@NonNull RewardedAd ad) {
        // Invocado cuando el anuncio ha sido mostrado
    }
});
```

{% endtab %}
{% endtabs %}


# Native (Google)

Los anuncios nativos son un tipo de anuncio que puede ser mostrado con el mismo estilo visual del resto de la app, lo que permite una integración natural y no-intrusiva con la interfaz de usuario.

Actualmente, desde Wortise ofrecemos la posibilidad de utilizar los anuncios nativos de la plataforma de anuncios de Google ("*Native Advanced*"), de una manera directa y sencilla.

## Integración

Para solicitar un anuncio nativo, es necesario realizar una integración por código tal y como se muestra en el ejemplo a continuación:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var googleNativeAd: GoogleNativeAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        googleNativeAd = GoogleNativeAd(
                         this, "Wortise Ad Unit ID", nativeListener).also {
            it.load()
        }
    }
    
    override fun onDestroy() {
        ...
        googleNativeAd?.destroy();
    }
    
    private val nativeListener = object : GoogleNativeAd.Listener() {
            
        override fun onNativeClicked(ad: GoogleNativeAd) {
            // Invocado cuando el anuncio ha sido clickeado
        }
        
        override fun onNativeFailedToLoad(ad: GoogleNativeAd, error: AdError) {
            // Invocado cuando el anuncio no se ha podido cargar
            // (por error o falta de inventario)
        }
        
        override fun onNativeImpression(ad: GoogleNativeAd) {
            // Invocado cuando el anuncio ha generado una impresión
        }
        
        override fun onNativeLoaded(ad: GoogleNativeAd, nativeAd: NativeAd) {
            // Invocado cuando el anuncio ha sido cargado
        }
        
        override fun onNativeRevenuePaid(ad: GoogleNativeAd,
                                         data: Revenuedata) {
            // Invocado cuando el anuncio ha generado un ingreso
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private GoogleNativeAd mGoogleNativeAd;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mGoogleNativeAd = new GoogleNativeAd(
                this, "Ad Unit ID de Wortise", mNativeListener);
        mGoogleNativeAd.load();
    }
    
    @Override
    public void onDestroy() {
        ...
        mGoogleNativeAd.destroy();
    }
    
    private GoogleNativeAd.Listener mNativeListener
            = new GoogleNativeAd.Listener() {
            
        @Override
        public void onNativeClicked(@NonNull GoogleNativeAd ad) {
            // Invocado cuando el anuncio ha sido clickeado
        }
        
        @Override
        public void onNativeFailedToLoad(@NonNull GoogleNativeAd ad,
                                         @NonNull AdError error) {
            // Invocado cuando el anuncio no se ha podido cargar
            // (por error o falta de inventario)
        }
        
        @Override
        public void onNativeImpression(@NonNull GoogleNativeAd ad) {
            // Invocado cuando el anuncio ha generado una impresión
        }
        
        @Override
        public void onNativeLoaded(@NonNull GoogleNativeAd ad,
                                   @NonNull NativeAd nativeAd) {
            // Invocado cuando el anuncio ha sido cargado
        }
        
        @Override
        public void onNativeRevenuePaid(@NonNull GoogleNativeAd ad,
                                        @NonNull Revenuedata data) {
            // Invocado cuando el anuncio ha generado un ingreso
        }
    }
}
```

{% endtab %}
{% endtabs %}

Una vez el anuncio nativo ha sido cargado con éxito, obtenido como resultado una instancia de `NativeAd`, es necesario completar la integración siguiendo la documentación de Google al respecto: <https://developers.google.com/ad-manager/mobile-ads-sdk/android/native/advanced?hl=es#display_a_unifiednativead>

### Especificar opciones

La clase `GoogleNativeAd` incluye un método llamado `withNativeAdOptions`, el cual permite indicar opciones personalizadas haciendo uso de la clase `NativeAdOptions` de Google. Este método debe ser llamado antes de realizar la carga del anuncio.

A continuación se muestra un breve ejemplo de uso:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val adOptions = NativeAdOptions.Builder()
    // Se establecen las opciones
    .build();

googleNativeAd.withNativeAdOptions(adOptions)
```

{% endtab %}

{% tab title="Java" %}

<pre class="language-java"><code class="lang-java">NativeAdOptions adOptions = new NativeAdOptions.Builder()
<strong>    // Se establecen las opciones
</strong>    .build();

mGoogleNativeAd.withNativeAdOptions(adOptions);
</code></pre>

{% endtab %}
{% endtabs %}


# Targeting

## Solicitar permisos

{% hint style="info" %}
Este paso es **totalmente opcional** y solo se debe implementar si resulta conveniente para la finalidad de la aplicación.
{% endhint %}

La aplicación puede solicitar los permisos de ubicación para que nuestro SDK pueda obtener la localización actual del usuario y mostrar anuncios de mayor interés en base a dicho dato.

Para ello, es necesario añadir los siguientes permisos en el fichero `AndroidManifest.xml`:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

A continuación, la aplicación deberá realizar la solicitud de los permisos para que los usuarios puedan otorgar su autorización.&#x20;

### Ejemplo

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
private val PERMISSIONS = arrayOf(
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
)

ActivityCompat.requestPermissions(this, PERMISSIONS, 100)
```

{% endtab %}

{% tab title="Java" %}

```java
private static final String[] PERMISSIONS = {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
};

ActivityCompat.requestPermissions(this, PERMISSIONS, 100);
```

{% endtab %}
{% endtabs %}


# Reporte de ingresos

## Implementación

Desde la versión **1.7.0**, las apps pueden recibir un reporte estimado del ingreso que previsiblemente ha sido generado por un anuncio.

Para ello, simplemente hay que implementar el listener correspondiente para cada formato de anuncio, como se muestra en el ejemplo a continuación:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val bannerAd: BannerAd

bannerAd.listener = object : BannerAd.Listener() {
    override fun onBannerRevenuePaid(ad: BannerAd, data: Revenuedata) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
BannerAd mBannerAd;

mBannerAd.setListener(new BannerAd.Listener() {
    @Override
    public void onBannerRevenuePaid(@NonNull BannerAd ad,
                                    @NonNull Revenuedata data) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
});
```

{% endtab %}
{% endtabs %}

El listener recibe un objeto de tipo `RevenueData` que contiene los siguientes campos:

<table><thead><tr><th width="139.62109375">Campo</th><th width="140.36328125">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>AdValue</code></td><td>El ingreso generado por el anuncio</td></tr><tr><td><code>source</code></td><td><code>String</code></td><td>La fuente del ingreso</td></tr></tbody></table>

Además, la clase `AdValue` contiene los siguientes campos que representan al ingreso:

<table><thead><tr><th width="140.49609375">Campo</th><th width="190.46484375">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>String</code></td><td>La divisa correspondiente al ingreso </td></tr><tr><td><code>precision</code></td><td><code>AdValue.Precision</code></td><td>La precisión de la información. Puede ser <code>ESTIMATED</code>, <code>PRECISE</code> o <code>PUBLISHER_DEFINED</code></td></tr><tr><td><code>value</code></td><td><code>Double</code></td><td>El valor del ingreso</td></tr></tbody></table>

## Integración con Firebase

A continuación, se muestra un ejemplo básico para reportar la información de los ingresos a Firebase:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
override func onBannerRevenuePaid(ad: BannerAd, data: RevenueData) {
    val bundle = Bundle().apply {
        putString("currency",   data.revenue.currency)
        putString("precision",  data.revenue.precision?.name)
        putString("source",     data.source)
        putDouble("value",      data.revenue.value)
    }

    Firebase.analytics.logEvent("ad_revenue", bundle)
}
```

{% endtab %}

{% tab title="Java" %}

<pre class="language-java"><code class="lang-java">@Override
public void onBannerRevenuePaid(@NonNull BannerAd ad,
                                @NonNull RevenueData data) {
<strong>    Bundle bundle = new Bundle();
</strong>
    bundle.putString("source", data.getSource());
    
    AdValue revenue = data.getRevenue();

    bundle.putString("currency",  revenue.getCurrency());
    bundle.putDouble("value",     revenue.getValue());
    
    AdValue.Precision precision = revenue.getPrecision();
    
    if (precision != null) {
        bundle.putString("precision", precision.name());
    }

    FirebaseAnalytics.getInstance(context).logEvent("ad_revenue", bundle);
}
</code></pre>

{% endtab %}
{% endtabs %}


# Consentimiento del usuario

El SDK de Wortise incluye soporte para el gestor de consentimiento (también llamado **Consent Manager** o **CMP**) de Google Ads para solicitar el consentimiento de cada usuario.

Obtener el consentimiento del usuario es importante para cumplir con las políticas de privacidad y optar a mayores CPM.

## Solicitar consentimiento

Para solicitar el consentimiento del usuario, es necesario llamar al método `ConsentManager.requestIfRequired` en un momento apropiado de la app. Esto mostrará un diálogo, solamente cuando sea totalmente necesario (normalmente en el primer arranque de la app), para que el usuario otorgue o deniegue su consentimiento.

También está disponible el método `ConsentManager.request` si se desea mostrar el diálogo siempre, y no exclusivamente cuando resulte necesario (por ejemplo, para ofrecer una opción en la pantalla de ajustes de la app que permita al usuario cambiar su consentimiento en cualquier momento).

### Ejemplo

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// Ejemplo con WortiseSdk.initialize
WortiseSdk.initialize(this, "tu app key") {
    ConsentManager.requestIfRequired(this);
}

// Ejemplo con WortiseSdk.wait
WortiseSdk.wait {
    ConsentManager.requestIfRequired(this);
}
```

{% endtab %}

{% tab title="Java" %}

```java
// Ejemplo con WortiseSdk.initialize
WortiseSdk.initialize(this, "tu app key", () -> {
    ConsentManager.requestIfRequired(this);
    return Unit.INSTANCE;
});

// Ejemplo con WortiseSdk.wait
WortiseSdk.wait(() -> {
    ConsentManager.requestIfRequired(this);
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}

### Configuración de listener

Es posible pasar un listener, tanto a `request` como `requestIfRequired`, para conocer cuando la solicitud de consentimiento ha finalizado (y si la solicitud ha sido mostrada). Para ello, simplemente es necesario pasar un listener como último parámetro de ambos métodos:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
ConsentManager.requestIfRequired(this) { shown ->
    // Este listener será invocado cuando la solicitud finalice 
}
```

{% endtab %}

{% tab title="Java" %}

```java
ConsentManager.requestIfRequired(this, (shown) -> {
    // Este listener será invocado cuando la solicitud finalice 
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}


# Privacidad

## Política de Familias (Families Policy)

Si tu aplicación está dirigida (exclusivamente o no) a usuarios menores de edad, es necesario cumplir con los requisitos establecidos por la [Política de Familias](https://support.google.com/googleplay/android-developer/answer/9900633) de Google Play.

Para facilitar el cumplimiento de estas políticas, el SDK permite especificar si las solicitudes de anuncios están dirigidas a menores de edad, además de poder establecer la clasificación de edad máxima permitida.

Es importante cumplir con estos requisitos, y revisar detenidamente las políticas asociadas, para evitar problemas con Google Play.

### Contenido dirigido a menores

Para indicar si un usuario es menor de edad o no, es necesario incluir el siguiente código **antes** de inicializar el SDK:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// true  -> El usuario es menor de edad o la edad es desconocida
// false -> El usuario es mayor de edad
AdSettings.setChildDirected(context, true)
```

{% endtab %}

{% tab title="Java" %}

```java
// true  -> El usuario es menor de edad o desconocido
// false -> El usuario es mayor de edad
AdSettings.setChildDirected(context, true);
```

{% endtab %}
{% endtabs %}

Si se desconoce la edad del usuario, la app debe tratar a dicho usuario como si fuese menor de edad.

### Clasificación de edad

Para especificar la clasificación de edad máxima, se debe añadir el siguiente código antes de inicializar el SDK:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
AdSettings.setMaxAdContentRating(context, AdContentRating.G)
```

{% endtab %}

{% tab title="Java" %}

```java
AdSettings.setMaxAdContentRating(context, AdContentRating.G);
```

{% endtab %}
{% endtabs %}

Los siguientes valores están disponibles a la hora de indicar la clasificación de edad:

| Valor                | Descripción                                                                   |
| -------------------- | ----------------------------------------------------------------------------- |
| `AdContentRating.G`  | Contenido adecuado para todas las audiencias                                  |
| `AdContentRating.PG` | Contenido adecuado para la mayoría de las audiencias con supervisión parental |
| `AdContentRating.T`  | Contenido adecuado para adolescentes                                          |
| `AdContentRating.MA` | Contenido adecuado únicamente para adultos                                    |

{% hint style="info" %}
Si la app está dirigida principalmente a niños, es completamente necesario especificar la clasificación `G`.

En cambio, si la audiencia de la app es mixta, se debe especificar una clasificación `G` o `PG`.
{% endhint %}

### Requisitos adicionales

Si tu aplicación está dirigida a niños, sea exclusivamente o no, es necesario eliminar el adaptador de Facebook que viene incluido en nuestro SDK debido a que todavía no se encuentra certificado por Google Play para su uso con niños.

Para ello, es necesario modificar la integración del SDK en el fichero `build.gradle` para especificar la exclusión del adaptador, tal y como se muestra a continuación:

```groovy
implementation('com.wortise:android-sdk:x.y.z') {
    exclude group: 'com.google.ads.mediation', module: 'facebook'
}
```


# ProGuard

No es necesario realizar ninguna acción al respecto ya que el SDK de Wortise incluye las reglas ProGuard necesarias para su correcto funcionamiento.


# Integración del SDK

## Requisitos

* Xcode: **15.0** o superior
* Target deployment: **iOS 12.0** o superior

## Configurar proyecto

Para comenzar con la integración de nuestro SDK, es necesario añadir la siguiente dependencia en el fichero `Podfile` del proyecto, tal y como se muestra a continuación:

```ruby
source 'https://cdn.cocoapods.org/'
platform :ios, '12.0'

...

target 'MyTarget' do
    use frameworks!
    ...
    pod 'WortiseSDK' '>= 1.7.3'
end
```

{% hint style="info" %}
Actualmente, el SDK de Wortise solo se distribuye a través de Cocoapods. En un futuro, se agregará soporte para su integración con Swift Package Manager (SPM).
{% endhint %}

## Configurar Info.plist

Es necesario agregar el siguiente parámetro en el fichero `Info.plist`, con el ID de aplicación de Google como valor:

```xml
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxxxx</string>
```

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

A continuación, solo faltaría añadir el siguiente bloque, en el mismo fichero, para finalizar la correcta integración con Google:

<pre class="language-xml"><code class="lang-xml"><strong>&#x3C;key>SKAdNetworkItems&#x3C;/key>
</strong>&#x3C;array>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>cstr6suwn9.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4fzdc2evr5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4pfyvq9l8r.skadnetwork &#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>2fnua5tdw4.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ydx93a7ass.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>5a6flpkh64.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>p78axxw29g.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v72qych5uu.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ludvb6z3bs.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>cp8zw746q7.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>c6k4g5qg8m.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>s39g8k73mm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3qy4746246.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3sh42y64q3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>f38h382jlk.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>hs6bdukanm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>prcb7njmu6.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v4nxqhlyqp.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>wzmmz9fp6w.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>yclnxrl5pm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>t38b2kh725.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>7ug5zh24hu.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>9rd848q2bz.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>y5ghdn5j9k.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>n6fk4nfna4.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v9wttpbfk9.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>n38lu8286q.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>47vhws6wlr.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>kbd757ywx3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>9t245vhmpl.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>a2p9lx4jpn.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>22mmun2rn5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4468km3ulz.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>2u9pt9hc89.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>8s468mfl3y.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>av6w8kgt66.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>klf5c3l5u5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ppxm28t8ap.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>424m5254lk.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ecpz2srf59.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>uw77j35x4d.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>mlmmfzh3r3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>578prtvx9j.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4dzt52r2t5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>gta9lk7p23.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>e5fvkxwrpn.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>8c4e2ghe7u.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>zq492l623r.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3rd42ekr43.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3qcr597p9d.skadnetwork&#x3C;/string>
    &#x3C;/dict>
&#x3C;/array>
</code></pre>

## Solicitar consentimiento

{% hint style="success" %}
Es **muy recomendable** solicitar consentimiento al usuario para poder mostrar anuncios personalizados. Esto permitirá mostrar contenido que resulte de mayor interés y generar ingresos superiores.
{% endhint %}

Puede consultar el siguiente apartado para implementar esta solicitud y obtener el consentimiento de los usuarios: [Consentimiento del usuario](/ios-sdk/consentimiento-del-usuario)

## Inicializar SDK

Nuestra recomendación es inicializar el SDK en la clase `AppDelegate` de la app, aunque también se puede realizar en algún `ViewController` principal.

Para ello, es necesario integrar el siguiente código en el método `application(didFinishLaunchingWithOptions:)`:

{% tabs %}
{% tab title="Swift" %}

```swift
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    ...
    WortiseAds.shared.initialize(assetKey: "tu app key")
}
```

{% endtab %}
{% endtabs %}

### Delegado de inicialización

Existen dos maneras posibles para conocer cuando el SDK finaliza su inicialización:

#### Pasando un delegate como último parámetro del método `WortiseAds.shared.initialize`

{% tabs %}
{% tab title="Swift" %}

```swift
WortiseAds.shared.initialize(assetKey: "tu app key") {
    // Este delegate será invocado cuando la inicialización finalice
}
```

{% endtab %}
{% endtabs %}

#### Utilizando el método `WortiseAds.shared.wait`

{% tabs %}
{% tab title="Swift" %}

```swift
WortiseAds.shared.wait {
    // Este delegate será invocado cuando la inicialización finalice
}
```

{% endtab %}
{% endtabs %}

## Modo de prueba

Para verificar la integración, el SDK ofrece un modo de prueba (*test mode*) que permite que la app siempre reciba anuncios.

Además de la opción que hay disponible en nuestro dashboard, es posible activar este modo de prueba programáticamente, desde el propio SDK, utilizando el siguiente código:

{% tabs %}
{% tab title="Swift" %}

```swift
WAAdSettings.testEnabled = true
```

{% endtab %}
{% endtabs %}


# App Open

Los anuncios de carga de aplicación (App Open) son un formato especial cuyo propósito es permitir la monetización de las pantalla de carga de las aplicaciones.

Estos anuncios se pueden cerrar en cualquier momento y están pensados para ser mostrados cuando la aplicación realiza una transición a primer plano.

## **Integración**

Este formato de anuncio solo se puede integrar a través de código, implementado cualquiera de las dos integraciones posibles que se describen a continuación.

### **Manual**

En este tipo de integración, es necesario crear una instancia de la clase `WAAppOpenAd` y utilizar los métodos `loadAd()` y `showAd()` para realizar la carga y mostrado del anuncio bajo demanda. El publisher es el responsable de decidir cuándo se debe mostrar el anuncio e implementar la lógica necesaria.

A continuación, se muestra un ejemplo sencillo de integración:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {

    private var appOpenAd: WAAppOpenAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        appOpenAd = WAAppOpenAd(adUnitId: "test-app-open")
        appOpenAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        appOpenAd.destroy()
    }
    
    func showAppOpen() {
        if appOpenAd.isAvailable {
            appOpenAd.showAd(from: self)
        }
    }
}
```

{% endtab %}
{% endtabs %}

Además, la clase `WAAppOpenAd` ofrece los siguientes métodos adicionales para configurar su comportamiento:

{% tabs %}
{% tab title="Swift" %}

```swift
// Establece si se debe cargar un nuevo anuncio tras cerrar el anterior
appOpenAd.autoReload = true

// Muestra un anuncio inmediatamente si está disponible. En caso contrario,
// solicita la carga de un nuevo anuncio
appOpenAd.tryToShowAd(from: self)
```

{% endtab %}
{% endtabs %}

### **Vía Manager**

El SDK ofrece una implementación estándar de App Open para facilitar la integración de este formato de anuncios.

Para realizar este tipo de integración, es necesario  crear una instancia de `WAAppOpenManager` dentro de la clase `AppDelegate`, tal y como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class AppDelegate: UIResponder, UIApplicationDelegate {

    private var appOpenManager: WAAppOpenManager!

    func application(_
        application: UIApplication, didFinishLaunchingWithOptions
        launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        ...
        appOpenManager = WAAppOpenManager(adUnitId: "test-app-open")
        appOpenManager.loadAd()
    }
}
```

{% endtab %}
{% endtabs %}

Con esta simple integración, la aplicación mostrará anuncios cada vez que se realice una transición de segundo a primer plano.

Igualmente, la clase `WAAppOpenManager` ofrece los mismos métodos que `AppOpenAd` para configurar su comportamiento y mostrar los anuncios bajo demanda.

## **Configuración del delegado**

Como en el resto de formatos, se puede añadir un delegate para recibir los diferentes eventos\
que sucedan durante el ciclo de vida del anuncio. Para ello, es necesario implementar la interfaz `WAAppOpenDelegate` como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Swift" %}

```swift
extension AppDelegate : WAAppOpenDelegate {

    func didClick(appOpenAd: WAAppOpenAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }

    func didDismiss(appOpenAd: WAAppOpenAd) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    func didFailToLoad(appOpenAd: WAAppOpenAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }

    func didFailToShow(appOpenAd: WAAppOpenAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }

    func didImpress(appOpenAd: WAAppOpenAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }

    func didLoad(appOpenAd: WAAppOpenAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    func didPayRevenue(appOpenAd: WAAppOpenAd, data: WARevenueData) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
 
    func didShow(appOpenAd: WAAppOpenAd) {
        // Invocado cuando el anuncio ha sido mostrado
    }
}
```

Una vez implementada la interfaz, se asigna el delegate a la instancia del anuncio:

```swift
appOpenAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Banner

Los anuncios de banner son anuncios de imagen o de texto rectangulares que ocupan un lugar dentro del diseño de una aplicación. Permanecen en la pantalla mientras los usuarios interactúan con la aplicación y pueden actualizarse automáticamente después de un cierto período de tiempo. Si eres nuevo en la publicidad móvil, son una excelente opción para comenzar.

## **Integración**

Para realizar la integración de un banner, es necesario añadir un componente de clase `WABannerAd` en la interfaz de la app.

A continuación, se debe solicitar la carga de un anuncio como en el ejemplo que se muestra a continuación:

{% tabs %}
{% tab title="Swift" %}

<pre class="language-swift"><code class="lang-swift"><strong>import UIKit
</strong>import WortiseSDK

class ViewController: UIViewController {
    @IBOutlet
    weak var bannerAd: WABannerAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        bannerAd.adUnitId = "Ad Unit ID de Wortise"
        bannerAd.adSize = WAAdSize.height50
        bannerAd.rootViewController = self
        // Opcional: valor en segundos para auto-refrescar el anuncio
        bannerAd.autoRefreshTime = 60.0
        bannerAd.loadAd()
    }
}
</code></pre>

{% endtab %}
{% endtabs %}

## **Banners adaptativos**

Los banners adaptativos son un nuevo formato de banner que se caracteriza por adaptar el tamaño de los anuncios según el dispositivo y la interfaz de la aplicación, para lograr maximizar el rendimiento.

Actualmente existe soporte para dos tipos de banners adaptativos:

### Anclados

Este tipo de banner está diseñado para reemplazar a los banners tradicionales de 320x50 y ser posicionado en la parte superior o inferior de la pantalla.

Para hacer uso de este formato, se debe utilizar el siguiente código para configurar un tamaño adaptativo, indicando la anchura del banner:

{% tabs %}
{% tab title="Swift" %}

```swift
// Es necesario especificar la anchura del banner
let adSize = WAAdSize.getAnchoredAdaptiveBannerAdSize(width: width)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

Alternativamente, se puede implementar esta otra opción para que el SDK calcule automáticamente la anchura del banner, donde se deberá pasar la propia instancia del `WABannerAd` o el `UIView` que va a contener a dicho banner:

{% hint style="warning" %}
En esta opción, es **muy recomendable** que el `UIView` que se pase al método ya se encuentre agregado al layout de la app, para que el SDK pueda calcular correctamente todas las dimensiones.
{% endhint %}

{% tabs %}
{% tab title="Swift" %}

```swift
let adSize = WAAdSize.getAnchoredAdaptiveBannerAdSize(container: view)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

### Inline

Este otro tipo de banner, en comparación con los anclados, está diseñado para tener una altura variable y ser posicionado dentro de un contenido desplazable.

En este caso, se debe utilizar un código como el siguiente para configurar un tamaño adaptativo apropiado:

{% tabs %}
{% tab title="Swift" %}

```swift
let maxHeight = 200

// Es necesario especificar la anchura del banner. La altura máxima es un
// parámetro opcional
let adSize = WAAdSize.getInlineAdaptiveBannerAdSize(width: width,
                                                    maxHeight: maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

Alternativamente, se puede implementar esta otra opción para que el SDK calcule automáticamente la anchura del banner, donde se deberá pasar la propia instancia del `WABannerAd` o el `UIView` que va a contener a dicho banner:

{% hint style="warning" %}
En esta opción, es **muy recomendable** que el `UIView` que se pase al método ya se encuentre agregado al layout de la app, para que el SDK pueda calcular correctamente todas las dimensiones.
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```swift
let maxHeight = 200

let adSize = AdSize.getInlineAdaptiveBannerAdSize(container: view,
                                                  maxHeight: maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

## **Configuración del delegado**

Se puede añadir un delegate a cualquier instancia de `WABannerAd` para recibir los diferentes eventos que sucedan durante su ciclo de vida. Para ello, es necesario implementar la interfaz `WABannerDelegate`, como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Swift" %}

```swift
extension ViewController : WABannerDelegate {

    func didClick(bannerAd: WABannerAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }
    
    func didFailToLoad(bannerAd: WABannerAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }

    func didImpress(bannerAd: WABannerAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }

    func didLoad(bannerAd: WABannerAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    func didPayRevenue(bannerAd: WABannerAd, data: WARevenueData) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
}
```

Una vez implementada la interfaz, se asigna el delegate a la instancia del anuncio:

```swift
bannerAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Interstitial

## Integración

Al contrario que los banners, los intersticiales únicamente se pueden integrar a través de código. A continuación se muestra un sencillo ejemplo para entender su funcionamiento:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {

    private var interstitialAd: WAInterstitialAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        interstitialAd = WAInterstitialAd(adUnitId: "test-interstitial")
        interstitialAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        interstitialAd.destroy()
    }

    func showInterstitial() {
        if interstitialAd.isAvailable {
            interstitialAd.showAd(from: self)
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Configuración del delegado**

Al igual que en el caso de los banners, se puede añadir un delegate para recibir los diferentes eventos que sucedan durante el ciclo de vida del intersticial. Para ello, es necesario implementar la interfaz `WAInterstitialDelegate` como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Swift" %}

```swift
extension ViewController : WAInterstitialDelegate {

    func didClick(interstitialAd: WAInterstitialAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }

    func didDismiss(interstitialAd: WAInterstitialAd) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    func didFailToLoad(interstitialAd: WAInterstitialAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }

    func didFailToShow(interstitialAd: WAInterstitialAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }

    func didImpress(interstitialAd: WAInterstitialAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }

    func didLoad(interstitialAd: WAInterstitialAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    func didPayRevenue(interstitialAd: WAInterstitialAd, data: WARevenueData) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
 
    func didShow(interstitialAd: WAInterstitialAd) {
        // Invocado cuando el anuncio ha sido mostrado
    }
}
```

Una vez implementada la interfaz, se asigna el delegate a la instancia del anuncio:

```swift
interstitialAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Rewarded

## Integración

Los anuncios recompensados (rewarded), al igual que los intersticiales, únicamente se pueden integrar a través de código. A continuación se muestra un sencillo ejemplo para entender su funcionamiento:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {

    private var rewardedAd: WARewardedAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        rewardedAd = WARewardedAd(adUnitId: "test-rewarded")
        rewardedAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        rewardedAd.destroy()
    }

    func showRewarded() {
        if rewardedAd.isAvailable {
            rewardedAd.showAd(from: self)
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Configuración del delegado**

Como en el resto de formatos, se puede añadir un delegate para recibir los diferentes eventos\
que sucedan durante el ciclo de vida del anuncio recompensado. Para ello, es necesario implementar la interfaz `WARewardedDelegate` como se muestra en el siguiente ejemplo:

{% tabs %}
{% tab title="Kotlin" %}

```swift
extension ViewController : WARewardedDelegate {

    func didClick(rewardedAd: WARewardedAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }

    func didComplete(rewardedAd: WARewardedAd, reward: WAReward) {
        // Invocado cuando el anuncio ha sido completado
    }

    func didDismiss(rewardedAd: WARewardedAd) {
        // Invocado cuando el anuncio ha sido cerrado
    }
    
    func didFailToLoad(rewardedAd: WARewardedAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }

    func didFailToShow(rewardedAd: WARewardedAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido mostrar
    }

    func didImpress(rewardedAd: WARewardedAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }

    func didLoad(rewardedAd: WARewardedAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    func didPayRevenue(rewardedAd: WARewardedAd, data: WARevenueData) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
 
    func didShow(rewardedAd: WARewardedAd) {
        // Invocado cuando el anuncio ha sido mostrado
    }
}
```

Una vez implementada la interfaz, se asigna el delegate a la instancia del anuncio:

```swift
rewardedAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Native (Google)

Los anuncios nativos son un tipo de anuncio que puede ser mostrado con el mismo estilo visual del resto de la app, lo que permite una integración natural y no-intrusiva con la interfaz de usuario.

Actualmente, desde Wortise ofrecemos la posibilidad de utilizar los anuncios nativos de la plataforma de anuncios de Google ("*Native Advanced*"), de una manera directa y sencilla.

## Integración

Para solicitar un anuncio nativo, es necesario realizar una integración por código tal y como se muestra en el ejemplo a continuación:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {
    private var nativeAd: WAGoogleNativeAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        nativeAd = WAGoogleNativeAd(adUnitId: "test-native",
                                    rootViewController: self,
                                    delegate: self)
        nativeAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        nativeAd.destroy()
    }
}

extension ViewController: WAGoogleNativeDelegate {

    func didClick(nativeAd: WAGoogleNativeAd) {
        // Invocado cuando el anuncio ha sido clickeado
    }

    func didFailToLoad(nativeAd: WAGoogleNativeAd, error: WAAdError) {
        // Invocado cuando el anuncio no se ha podido cargar
        // (por error o falta de inventario)
    }

    func didLoad(nativeAd: WAGoogleNativeAd, googleNativeAd: GADNativeAd) {
        // Invocado cuando el anuncio ha sido cargado
    }
    
    func didPayRevenue(nativeAd: WAGoogleNativeAd, data: WARevenueData) {
        // Invocado cuando el anuncio ha generado un ingreso
    }

    func didRecord(impression: WAGoogleNativeAd) {
        // Invocado cuando el anuncio ha generado una impresión
    }
}
```

{% endtab %}
{% endtabs %}

Una vez el anuncio nativo ha sido cargado con éxito, obtenido como resultado una instancia de `GADNativeAd`, es necesario completar la integración siguiendo la documentación de Google al respecto: <https://developers.google.com/ad-manager/mobile-ads-sdk/ios/native/advanced?hl=es#display_a_unifiednativead>

### Especificar opciones

La clase `WAGoogleNativeAd` incluye un atributo llamado `options`, el cual permite indicar opciones personalizadas haciendo uso de la clase `GADAdLoaderOptions` de Google. Este atributo debe ser establecido antes de realizar la carga del anuncio.

A continuación se muestra un breve ejemplo de uso:

{% tabs %}
{% tab title="Swift" %}

```swift
let adOptions = GADNativeAdViewAdOptions()

// Establecer las opciones a través de "adOptions"

googleNativeAd.options = adOptions
```

{% endtab %}
{% endtabs %}


# Reporte de ingresos

## Implementación

Desde la versión **1.7.0**, las apps pueden recibir un reporte estimado del ingreso que previsiblemente ha sido generado por un anuncio.

Para ello, simplemente hay que implementar el delegate correspondiente para cada formato de anuncio, como se muestra en el ejemplo a continuación:

{% tabs %}
{% tab title="Swift" %}

```swift
extension ViewController : WABannerDelegate {   
    func didPayRevenue(bannerAd: WABannerAd, data: WARevenueData) {
        // Invocado cuando el anuncio ha generado un ingreso
    }
}
```

{% endtab %}
{% endtabs %}

El delegate recibe un objeto de tipo `WARevenueData` que contiene los siguientes campos:

<table><thead><tr><th width="139.62109375">Campo</th><th width="140.36328125">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>WAAdValue</code></td><td>El ingreso generado por el anuncio</td></tr><tr><td><code>source</code></td><td><code>String</code></td><td>La fuente del ingreso</td></tr></tbody></table>

Además, la clase `WAAdValue` contiene los siguientes campos que representan al ingreso:

<table><thead><tr><th width="140.49609375">Campo</th><th width="200.12890625">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>String</code></td><td>La divisa correspondiente al ingreso </td></tr><tr><td><code>precision</code></td><td><code>WAAdValue.Precision</code></td><td>La precisión de la información. Puede ser <code>estimated</code>, <code>precise</code> o <code>publisherDefined</code></td></tr><tr><td><code>value</code></td><td><code>Double</code></td><td>El valor del ingreso</td></tr></tbody></table>

## Integración con Firebase

A continuación, se muestra un ejemplo básico para reportar la información de los ingresos a Firebase:

{% tabs %}
{% tab title="Swift" %}

```swift
import FirebaseAnalytics

func didPayRevenue(bannerAd: WABannerAd, data: WARevenueData) {
    let params = [
        "currency":  data.revenue.currency,
        "precision": data.precision?.name,
        "source":    data.source,
        "value":     data.revenue.value
    ]

    Analytics.logEvent("ad_revenue", parameters: params)
}
```

{% endtab %}
{% endtabs %}


# Consentimiento del usuario

El SDK de Wortise incluye soporte para el gestor de consentimiento (también llamado **Consent Manager** o **CMP**) de Google Ads para solicitar el consentimiento de cada usuario.

Obtener el consentimiento del usuario es importante para cumplir con las políticas de privacidad y optar a mayores CPM.

## Solicitar consentimiento

Para solicitar el consentimiento del usuario, es necesario llamar al método `WAConsentManager.shared.request(ifRequired:)` en un momento apropiado de la app. Esto mostrará un diálogo, solamente cuando sea totalmente necesario (normalmente en el primer arranque de la app), para que el usuario otorgue o deniegue su consentimiento.

También está disponible el método `WAConsentManager.request` si se desea mostrar el diálogo siempre, y no exclusivamente cuando resulte necesario (por ejemplo, para ofrecer una opción en la pantalla de ajustes de la app que permita al usuario cambiar su consentimiento en cualquier momento).

### Ejemplo

{% tabs %}
{% tab title="Swift" %}

```swift
// Ejemplo con WortiseAds.shared.initialize
WortiseAds.shared.initialize(assetKey: "tu app key") {
    WAConsentManager.request(ifRequired: self)
}

// Ejemplo con WortiseAds.shared.wait
WortiseAds.shared.wait {
    WAConsentManager.request(ifRequired: self)
}
```

{% endtab %}
{% endtabs %}

### Configuración de delegado

Es posible pasar un delegate, tanto a `request` como `request(ifRequired:)`, para conocer cuando la solicitud de consentimiento ha finalizado (y si la solicitud ha sido mostrada). Para ello, simplemente es necesario pasar un listener como último parámetro de ambos métodos:

{% tabs %}
{% tab title="Swift" %}

```swift
WAConsentManager.request(ifRequired: self) {
    // Este delegate será invocado cuando la solicitud finalice 
}
```

{% endtab %}
{% endtabs %}


# Privacidad

## Política de Privacidad

Si tu aplicación está dirigida (exclusivamente o no) a usuarios menores de edad, es necesario cumplir con los requisitos establecidos por Apple.

Para facilitar el cumplimiento de estos requisitos, el SDK permite especificar si las solicitudes de anuncios están dirigidas a menores de edad, además de poder establecer la clasificación de edad máxima permitida.

Es importante cumplir con estos requisitos, y revisar detenidamente las políticas asociadas, para evitar problemas con Apple.

### Contenido dirigido a menores

Para indicar si un usuario es menor de edad o no, es necesario incluir el siguiente código **antes** de inicializar el SDK:

{% tabs %}
{% tab title="Swift" %}

<pre class="language-swift"><code class="lang-swift">// true  -> El usuario es menor de edad o la edad es desconocida
// false -> El usuario es mayor de edad
<strong>WAAdSettings.childDirected = true
</strong></code></pre>

{% endtab %}
{% endtabs %}

Si se desconoce la edad del usuario, la app debe tratar a dicho usuario como si fuese menor de edad.

### Clasificación de edad

Para especificar la clasificación de edad máxima, se debe añadir el siguiente código antes de inicializar el SDK:

{% tabs %}
{% tab title="Swift" %}

```swift
WAAdSettings.maxAdContentRating = WAAdContentRating.G
```

{% endtab %}
{% endtabs %}

Los siguientes valores están disponibles a la hora de indicar la clasificación de edad:

| Valor                  | Descripción                                                                   |
| ---------------------- | ----------------------------------------------------------------------------- |
| `WAAdContentRating.G`  | Contenido adecuado para todas las audiencias                                  |
| `WAAdContentRating.PG` | Contenido adecuado para la mayoría de las audiencias con supervisión parental |
| `WAAdContentRating.T`  | Contenido adecuado para adolescentes                                          |
| `WAAdContentRating.MA` | Contenido adecuado únicamente para adultos                                    |

{% hint style="info" %}
Si la app está dirigida principalmente a niños, es completamente necesario especificar la clasificación `G`.

En cambio, si la audiencia de la app es mixta, se debe especificar una clasificación `G` o `PG`.
{% endhint %}


# Integración del SDK

## Requisitos

Esta documentación ha sido escrita para Unity **2022 o superior**. Se recomienda utilizar estas versiones a la hora de integrar el SDK.

## Importar paquete Unity

En primer lugar, es necesario descargar el paquete para Unity desde el siguiente enlace:

<p align="center"><a href="https://cdn.resources.wortise.com/sdk/unity/Wortise-Unity-1.7.3.unitypackage" class="button primary" data-icon="arrow-down-to-line">Descargar paquete Unity de Wortise</a></p>

Una vez descargado, haz doble click en el fichero para importarlo en el proyecto.

## Configurar SDK

Para configurar el SDK, hay que ir a la opción **Wortise -> Settings** que aparece en la barra de menús de Unity. Tras seleccionar la opción, se abrirá la ventana de configuración donde se deben de especificar los ID de aplicación de Google para cada plataforma:

<figure><img src="/files/fGdv56q3jD3mD4NuDaIa" alt="" width="563"><figcaption><p>Captura de la ventana</p></figcaption></figure>

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

## Solicitar consentimiento

{% hint style="success" %}
Es **muy recomendable** solicitar consentimiento al usuario para poder mostrar anuncios personalizados. Esto permitirá mostrar contenido que resulte de mayor interés y generar ingresos superiores.
{% endhint %}

Puede consultar el siguiente apartado para implementar esta solicitud y obtener el consentimiento de los usuarios: [Consentimiento del usuario](/unity-sdk/consentimiento-del-usuario)

## Inicializar SDK

Para inicializar el SDK, es necesario añadir las siguientes líneas en el método `Start()` del primer `Scene` del proyecto. Además, recomendamos implementar el evento `OnInitialized` para solicitar el consentimiento una vez la inicialización se ha completado:

```csharp
void Start() {
    ...
    
    WortiseSdk.OnInitialized += () => {
        WortiseConsentManager.RequestIfRequired();
    };
    
    WortiseSdk.Initialize("tu app key");
}
```

## Modo de prueba

Para verificar la integración, el SDK ofrece un modo de prueba (*test mode*) que permite que la app siempre reciba anuncios.

Además de la opción que hay disponible en nuestro dashboard, es posible activar este modo de prueba programáticamente, desde el propio SDK, utilizando el siguiente código:

```csharp
WortiseAdSettings.IsTestEnabled = true;
```


# App Open

## Integración

Para hacer uso de los anuncios App Open, es necesario solicitar su carga en algún momento de la app, siendo recomendable hacerlo lo más pronto posible.

A continuación, se muestra un ejemplo de como cargar y mostrar un anuncio:

```csharp
// Se crea un App Open
WortiseAppOpen appOpenAd = new WortiseAppOpen(
    "Ad Unit ID de Wortise"
);

// Se solicita la carga de un anuncio
appOpenAd.LoadAd();

// Se muestra el anuncio si está disponible
if (appOpenAd.IsAvailable) {
    appOpenAd.ShowAd();
}
```

Además, la clase `WortiseAppOpen` ofrece los siguientes métodos adicionales para configurar su comportamiento:

```csharp
// Establece si se debe cargar un nuevo anuncio tras cerrar el anterior
appOpenAd.AutoReload = true;

// Muestra un anuncio inmediatamente si está disponible. En caso contrario,
// solicita la carga de un nuevo anuncio
appOpenAd.TryToShowAd();
```

## **Configuración de listeners**

Se pueden añadir listeners para recibir los diferentes eventos que sucedan durante el ciclo de vida del anuncio. Para ello, puede hacer uso de los siguientes atributos disponibles en la clase `WortiseAppOpen`:

* `OnClicked`
* `OnDismissed`
* `OnFailedToLoad`&#x20;
* `OnFailedToShow`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`
* `OnShown`

### Ejemplo

```csharp
appOpenAd.OnClicked      += () => Debug.Log('App open clicked');
appOpenAd.OnDismissed    += () => Debug.Log('App open dismissed');
appOpenAd.OnFailedToLoad += () => Debug.Log('App open failed to load');
appOpenAd.OnFailedToShow += () => Debug.Log('App open failed to show');
appOpenAd.OnImpression   += () => Debug.Log('App open impression');
appOpenAd.OnLoaded       += () => Debug.Log('App open loaded');
appOpenAd.OnRevenuePaid  += (data) => Debug.Log('App open revenue paid');
appOpenAd.OnShown        += () => Debug.Log('App open shown');
```


# Banner

Los anuncios de banner son anuncios de imagen o de texto rectangulares que ocupan un lugar dentro del diseño de una aplicación. Permanecen en la pantalla mientras los usuarios interactúan con la aplicación y pueden actualizarse automáticamente después de un cierto período de tiempo. Si eres nuevo en la publicidad móvil, son una excelente opción para comenzar.

## **Integración**

Para realizar la integración de un banner, es necesario implementar un código similar al del ejemplo que se muestra a continuación:

```csharp
// Se crea un banner
WortiseBanner bannerAd = new WortiseBanner(
    "Ad Unit ID de Wortise",
    WortiseAdSize.Height50,
    WortiseAdPosition.Top
);

// Opcional: Se establece el tiempo de auto-refresco en milisegundos
bannerAd.AutoRefreshTime = 60000;

// Se solicita la carga de un anuncio
banner.LoadAd();
```

## **Banners adaptativos**

Los banners adaptativos son un nuevo formato de banner que se caracteriza por adaptar el tamaño de los anuncios según el dispositivo y la interfaz de la aplicación, para lograr maximizar el rendimiento.

Actualmente existe soporte para dos tipos de banners adaptativos:

### Anclados

Este tipo de banner está diseñado para reemplazar a los banners tradicionales de 320x50 y ser posicionado en la parte superior o inferior de la pantalla.

Para hacer uso de este formato, se debe pasar un `WortiseAdSize` a la instancia `BannerAd` generado de la siguiente manera:

```dart
// Es necesario especificar la anchura del banner
WortiseAdSize.GetAnchoredAdaptiveBannerAdSize(width);
```

### Inline

Este otro tipo de banner, en comparación con los anclados, está diseñado para tener una altura variable y ser posicionado dentro de un contenido desplazable.

En este caso, se debe generar un `WortiseAdSize` como se muestra a continuación:

```dart
// Es necesario especificar la anchura del banner. La altura máxima es un
// parámetro opcional (pasando valor 0 o negativo)
WortiseAdSize.GetInlineAdaptiveBannerAdSize(width, maxHeight);
```

## **Configuración de listeners**

Se pueden añadir listeners para recibir los diferentes eventos que sucedan durante el ciclo de vida del intersticial. Para ello, puede hacer uso de los siguientes atributos disponibles en la clase `WortiseBanner`:

* `OnClicked`
* `OnFailedToLoad`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`

### Ejemplo

```csharp
bannerAd.OnClicked      += () => Debug.Log('Banner clicked');
bannerAd.OnFailedToLoad += () => Debug.Log('Banner failed to load');
bannerAd.OnImpression   += () => Debug.Log('Banner impression');
bannerAd.OnLoaded       += () => Debug.Log('Banner loaded');
bannerAd.OnRevenuePaid  += (data) => Debug.Log('Banner revenue paid');
```


# Interstitial

## Integración

Para hacer uso de los anuncios intersticiales, es necesario solicitar su carga en algún momento de la app, siendo recomendable hacerlo lo más pronto posible.

A continuación, se muestra un ejemplo de como cargar y mostrar un anuncio intersticial:

```csharp
// Se crea un intersticial
WortiseInterstitial interstitialAd = new WortiseInterstitial(
    "Ad Unit ID de Wortise"
);

// Se solicita la carga de un anuncio
interstitialAd.LoadAd();

// Se muestra el anuncio si está disponible
if (interstitialAd.IsAvailable) {
    interstitialAd.ShowAd();
}
```

## **Configuración de listeners**

Se pueden añadir listeners para recibir los diferentes eventos que sucedan durante el ciclo de vida del intersticial. Para ello, puede hacer uso de los siguientes atributos disponibles en la clase `WortiseInterstitial`:

* `OnClicked`
* `OnDismissed`
* `OnFailedToLoad`
* `OnFailedToShow`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`
* `OnShown`

### Ejemplo

```csharp
interstitialAd.OnClicked      += () => Debug.Log('Interstitial clicked');
interstitialAd.OnDismissed    += () => Debug.Log('Interstitial dismissed');
interstitialAd.OnFailedToLoad += () => Debug.Log('Interstitial failed to load');
interstitialAd.OnFailedToShow += () => Debug.Log('Interstitial failed to show');
interstitialAd.OnImpression.  += () => Debug.Log('Interstitial impression');
interstitialAd.OnLoaded       += () => Debug.Log('Interstitial loaded');
interstitialAd.OnRevenuePaid  += (data) => Debug.Log('Interstitial revenue paid');
interstitialAd.OnShown        += () => Debug.Log('Interstitial shown');
```


# Rewarded

## Integración

Para hacer uso de los anuncios recompensados, es necesario solicitar su carga en algún momento de la app, siendo recomendable hacerlo lo más pronto posible.

A continuación, se muestra un ejemplo de como cargar y mostrar un anuncio recompensado:

```csharp
// Se crea un anuncio recompensado
WortiseRewarded rewardedAd = new WortiseRewarded(
    "Ad Unit ID de Wortise"
);

// Se solicita la carga de un anuncio
rewardedAd.LoadAd();

// Se muestra el anuncio si está disponible
if (rewardedAd.IsAvailable) {
    rewardedAd.ShowAd();
}
```

## **Configuración de listeners**

Se pueden añadir listeners para recibir los diferentes eventos que sucedan durante el ciclo de vida del recompensado. Para ello, puede hacer uso de los siguientes atributos disponibles en la clase `WortiseRewarded`:

* `OnClicked`
* `OnCompleted`
* `OnDismissed`
* `OnFailedToLoad`
* `OnFailedToShow`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`
* `OnShown`

### Ejemplo

```csharp
rewardedAd.OnClicked      += () => Debug.Log('Rewarded clicked');
rewardedAd.OnCompleted    += (reward) => Debug.Log('Rewarded completed');
rewardedAd.OnDismissed    += () => Debug.Log('Rewarded dismissed');
rewardedAd.OnFailedToLoad += () => Debug.Log('Rewarded failed to load');
rewardedAd.OnFailedToShow += () => Debug.Log('Rewarded failed to show');
rewardedAd.OnImpression.  += () => Debug.Log('Rewarded impression');
rewardedAd.OnLoaded       += () => Debug.Log('Rewarded loaded');
rewardedAd.OnRevenuePaid  += (data) => Debug.Log('Rewarded revenue paid');
rewardedAd.OnShown        += () => Debug.Log('Rewarded shown');
```


# Targeting

## Solicitar permisos&#x20;

{% hint style="info" %}
Este paso es **totalmente opcional** y solo se debe implementar si resulta conveniente para la finalidad de la aplicación.
{% endhint %}

La aplicación puede solicitar los permisos de ubicación para que nuestro SDK pueda obtener la localización actual del usuario y mostrar anuncios de mayor interés en base a dicho dato.

Para ello, es necesario añadir los siguientes permisos en el fichero `AndroidManifest.xml`:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

A continuación, se debe realizar la solicitud de los permisos para que los usuarios puedan otorgar su autorización, tal y como se indica en la [documentación oficial](https://docs.unity3d.com/Manual/android-RequestingPermissions.html) de Unity.&#x20;


# Reporte de ingresos

## Implementación

Desde la versión **1.7.0**, las apps pueden recibir un reporte estimado del ingreso que previsiblemente ha sido generado por un anuncio.

Para ello, simplemente hay que implementar el listener correspondiente para cada formato de anuncio, como se muestra en el ejemplo a continuación:

```csharp
WortiseBannerAd bannerAd;

bannerAd.OnRevenuePaid += (data) => {
    Debug.Log('Banner revenue paid');
};
```

El listener recibe un objeto de tipo `WortiseRevenueData` que contiene los siguientes campos:

<table><thead><tr><th width="139.62109375">Campo</th><th width="175.3203125">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>WortiseAdValue</code></td><td>El ingreso generado por el anuncio</td></tr><tr><td><code>source</code></td><td><code>string</code></td><td>La fuente del ingreso</td></tr></tbody></table>

Además, la clase `WortiseAdValue` contiene los siguientes campos que representan al ingreso:

<table><thead><tr><th width="140.49609375">Campo</th><th width="174.91796875">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>string</code></td><td>La divisa correspondiente al ingreso </td></tr><tr><td><code>precision</code></td><td><code>WortisePrecision</code></td><td>La precisión de la información. Puede ser <code>Estimated</code>, <code>Precise</code> o <code>PublisherDefined</code></td></tr><tr><td><code>value</code></td><td><code>double</code></td><td>El valor del ingreso</td></tr></tbody></table>

## Integración con Firebase

A continuación, se muestra un ejemplo básico para reportar la información de los ingresos a Firebase:

```csharp
using Firebase.Analytics;

bannerAd.OnRevenuePaid += (data) => {
    FirebaseAnalytics.LogEvent(
        "ad_revenue",
        new Parameter("currency",  data.revenue.currency),
        new Parameter("precision", data.revenue.precision?.ToString()),
        new Parameter("source",    data.source),
        new Parameter("value",     data.revenue.value)
    );
};
```


# Consentimiento del usuario

El SDK de Wortise incluye soporte para el gestor de consentimiento (también llamado **Consent Manager** o **CMP**) de Google Ads para solicitar el consentimiento de cada usuario.

Obtener el consentimiento del usuario es importante para cumplir con las políticas de privacidad y optar a mayores CPM.

## Solicitar consentimiento

Para solicitar el consentimiento del usuario, es necesario llamar al método `WortiseConsentManager.RequestIfRequired` en un momento apropiado de la app. Esto mostrará un diálogo, solamente cuando sea totalmente necesario (normalmente en el primer arranque de la app), para que el usuario otorgue o deniegue su consentimiento.

También está disponible el método `WortiseConsentManager.Request` si se desea mostrar el diálogo siempre, y no exclusivamente cuando resulte necesario (por ejemplo, para ofrecer una opción en la pantalla de ajustes de la app que permita al usuario cambiar su consentimiento en cualquier momento).

### Ejemplo

```csharp
WortiseSdk.OnInitialized += () => {
    WortiseConsentManager.RequestIfRequired();
};
```


# Privacidad

## Política de Familias (Families Policy)

Si tu aplicación está dirigida (exclusivamente o no) a usuarios menores de edad, es necesario cumplir con los requisitos establecidos por la [Política de Familias](https://support.google.com/googleplay/android-developer/answer/9900633) de Google Play.

Para facilitar el cumplimiento de estas políticas, el SDK permite especificar si las solicitudes de anuncios están dirigidas a menores de edad, además de poder establecer la clasificación de edad máxima permitida.

Es importante cumplir con estos requisitos, y revisar detenidamente las políticas asociadas, para evitar problemas con Google Play.

### Contenido dirigido a menores

Para indicar si un usuario es menor de edad o no, es necesario incluir el siguiente código **antes** de inicializar el SDK:

```csharp
// true  -> El usuario es menor de edad o la edad es desconocida
// false -> El usuario es mayor de edad
WortiseAdSettings.IsChildDirected = true;
```

Si se desconoce la edad del usuario, la app debe tratar a dicho usuario como si fuese menor de edad.

### Clasificación de edad

Para especificar la clasificación de edad máxima, se debe añadir el siguiente código antes de inicializar el SDK:

```csharp
WortiseAdSettings.MaxAdContentRating = WortiseAdContentRating.G;
```

Los siguientes valores están disponibles a la hora de indicar la clasificación de edad:

| Valor                       | Descripción                                                                   |
| --------------------------- | ----------------------------------------------------------------------------- |
| `WortiseAdContentRating.G`  | Contenido adecuado para todas las audiencias                                  |
| `WortiseAdContentRating.PG` | Contenido adecuado para la mayoría de las audiencias con supervisión parental |
| `WortiseAdContentRating.T`  | Contenido adecuado para adolescentes                                          |
| `WortiseAdContentRating.MA` | Contenido adecuado únicamente para adultos                                    |

{% hint style="info" %}
Si la app está dirigida principalmente a niños, es completamente necesario especificar la clasificación `G`.

En cambio, si la audiencia de la app es mixta, se debe especificar una clasificación `G` o `PG`.
{% endhint %}

### Requisitos adicionales

Si tu aplicación está dirigida a niños, sea exclusivamente o no, es necesario eliminar el adaptador de Facebook que viene incluido en nuestro SDK debido a que todavía no se encuentra certificado por Google Play para su uso con niños.

Para ello, es necesario modificar la integración del SDK en el fichero `mainTemplate.gradle` para especificar la exclusión del adaptador, tal y como se muestra a continuación:

```groovy
implementation('com.wortise:android-sdk:x.y.z') {
    exclude group: 'com.google.ads.mediation', module: 'facebook'
}
```


# Integración del SDK

## Configurar proyecto

Para integrar nuestro SDK para Flutter, es necesario añadir la siguiente línea dentro del bloque `dependencies` del fichero `pubspec.yaml` de tu aplicación:

```yaml
dependencies:
  wortise: ^1.7.5
```

A continuación, hay que ejecutar el siguiente comando para realizar la instalación de nuestro SDK:

```bash
$ flutter pub get
```

Ahora, podrás hacer uso de las siguientes sentencias `import` para acceder a las diferentes clases que ofrece el SDK:

```dart
import 'package:wortise/ad_content_rating.dart';
import 'package:wortise/ad_settings.dart';
import 'package:wortise/ad_size.dart';
import 'package:wortise/banner_ad.dart';
import 'package:wortise/consent_manager.dart';
import 'package:wortise/data_manager.dart';
import 'package:wortise/interstitial_ad.dart';
import 'package:wortise/rewarded_ad.dart';
import 'package:wortise/user_gender.dart';
import 'package:wortise/wortise_sdk.dart';
```

## Configurar Manifest (Android)

Es necesario agregar el siguiente elemento `<meta-data>` en el fichero `android/app/src/main/AndroidManifest.xml`, dentro del bloque `<application>`, con el ID de aplicación de Google como valor:

```xml
<manifest>
    ...
    <application>
        ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>
```

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

## Configurar Info.plist (iOS)

Es necesario agregar el siguiente parámetro en el fichero `Info.plist`, con el ID de aplicación de Google como valor:

```xml
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxxxx</string>
```

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

A continuación, solo faltaría añadir el siguiente bloque, en el mismo fichero, para finalizar la correcta integración con Google:

<pre class="language-xml"><code class="lang-xml"><strong>&#x3C;key>SKAdNetworkItems&#x3C;/key>
</strong>&#x3C;array>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>cstr6suwn9.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4fzdc2evr5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4pfyvq9l8r.skadnetwork &#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>2fnua5tdw4.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ydx93a7ass.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>5a6flpkh64.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>p78axxw29g.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v72qych5uu.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ludvb6z3bs.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>cp8zw746q7.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>c6k4g5qg8m.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>s39g8k73mm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3qy4746246.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3sh42y64q3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>f38h382jlk.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>hs6bdukanm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>prcb7njmu6.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v4nxqhlyqp.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>wzmmz9fp6w.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>yclnxrl5pm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>t38b2kh725.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>7ug5zh24hu.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>9rd848q2bz.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>y5ghdn5j9k.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>n6fk4nfna4.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v9wttpbfk9.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>n38lu8286q.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>47vhws6wlr.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>kbd757ywx3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>9t245vhmpl.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>a2p9lx4jpn.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>22mmun2rn5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4468km3ulz.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>2u9pt9hc89.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>8s468mfl3y.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>av6w8kgt66.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>klf5c3l5u5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ppxm28t8ap.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>424m5254lk.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ecpz2srf59.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>uw77j35x4d.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>mlmmfzh3r3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>578prtvx9j.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4dzt52r2t5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>gta9lk7p23.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>e5fvkxwrpn.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>8c4e2ghe7u.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>zq492l623r.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3rd42ekr43.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3qcr597p9d.skadnetwork&#x3C;/string>
    &#x3C;/dict>
&#x3C;/array>
</code></pre>

## Solicitar consentimiento

{% hint style="success" %}
Es **muy recomendable** solicitar consentimiento al usuario para poder mostrar anuncios personalizados. Esto permitirá mostrar contenido que resulte de mayor interés y generar ingresos superiores.
{% endhint %}

Puede consultar el siguiente apartado para implementar esta solicitud y obtener el consentimiento de los usuarios: [Consentimiento del usuario](/flutter-sdk/consentimiento-del-usuario)

## Inicializar SDK

Para inicializar el SDK, es necesario añadir el siguiente código dentro del método `initState()` de tu aplicación:

```dart
await WortiseSdk.initialize('tu app key');
```

## Modo de prueba

Para verificar la integración, el SDK ofrece un modo de prueba (*test mode*) que permite que la app siempre reciba anuncios.

Además de la opción que hay disponible en nuestro dashboard, es posible activar este modo de prueba programáticamente, desde el propio SDK, utilizando el siguiente código:

```dart
import 'package:wortise/ad_settings.dart';

await AdSettings.setTestEnabled(true);
```


# App Open

## Integración

A continuación se muestran unos sencillos ejemplos para realizar la implementación de los anuncios App Open siguiendo las dos posibles vías de integración:

### Manual

```dart
import 'package:wortise/app_open_ad.dart';

AppOpenAd _appOpenAd;

// Se crea un anuncio App Open
_appOpenAd = AppOpenAd('Ad Unit ID de Wortise', listener: (event, args) {
  // Este listener será invocado cuando se produzca algún evento
});

// Se solicita la carga de un anuncio
await _appOpenAd.loadAd();

/* ... */

// Se muestra el anuncio si está disponible
if (await _appOpenAd.isAvailable) {
  await _appOpenAd.showAd();
}
```

El constructor de la clase `AppOpenAd` permite especificar los siguientes parámetros opcionales para configurar su comportamiento:

```dart
// Establece si se debe cargar un nuevo anuncio tras cerrar el anterior 
autoReload: true
```

Alternativamente, se puede utilizar el método `tryToShowAd()` para realizar el mostrado del anuncio con la diferencia que, si no hay uno disponible, automáticamente se solicita la carga de un nuevo anuncio:

```dart
await _appOpenAd.tryToShowAd();
```

### Vía Manager

```dart
import 'package:wortise/app_open_ad.dart';
import 'package:wortise/app_open_manager.dart';

// Se crea un anuncio App Open
AppOpenAd appOpenAd = AppOpenAd('Ad Unit ID de Wortise')..loadAd();

// Se registra el anuncio en el manager
AppOpenManager.register(appOpenAd);
```

En esta integración, los anuncios serán mostrados automáticamente cuando se produzca una transición de la aplicación de segundo a primer plano. Igualmente, se puede seguir haciendo uso de los métodos ofrecidos por `AppOpenAd` para realizar un mostrado manual.

## **Eventos del listener**

El listener asignado a un `AppOpenAd` puede recibir los siguientes eventos:

```dart
// El anuncio ha sido clickeado
AppOpenAdEvent.CLICKED
// El anuncio ha sido cerrado
AppOpenAdEvent.DISMISSED
// El anuncio no se ha podido cargar
AppOpenAdEvent.FAILED_TO_LOAD
// El anuncio no se ha podido mostrar
AppOpenAdEvent.FAILED_TO_SHOW
// El anuncio ha generado una impresión
AppOpenAdEvent.IMPRESSION
// El anuncio ha sido cargado
AppOpenAdEvent.LOADED
// El anuncio ha generado un ingreso
AppOpenAdEvent.REVENUE_PAID
// El anuncio ha sido mostrado
AppOpenAdEvent.SHOWN
```


# Banner

Los anuncios de banner son anuncios de imagen o de texto rectangulares que ocupan un lugar dentro del diseño de una aplicación. Permanecen en la pantalla mientras los usuarios interactúan con la aplicación y pueden actualizarse automáticamente después de un cierto período de tiempo. Si eres nuevo en la publicidad móvil, son una excelente opción para comenzar.

## **Integración**

La integración de los banners se realiza añadiendo el widget `BannerAd` en el layout de la aplicación. A continuación, se muestra un sencillo ejemplo de integración:

```dart
import 'package:wortise/ad_size.dart';
import 'package:wortise/banner_ad.dart';

/* ... */

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: const Text('Wortise Flutter Example'),
      ),
      body: ListView(
        padding: EdgeInsets.all(20),
        children: [
          /* El banner debe estar dentro de un contenedor */
          Container(
            height: 50,
            child: BannerAd(
              adSize: AdSize.HEIGHT_50,
              adUnitId: 'Ad Unit ID de Wortise',
            ),
          )
        ]
      ),
    ),
  );
}
```

El widget tiene soporte para los siguientes parámetros:

| Parámetro           | Tipo     | Requerido | Descripción                                                                                                                   |
| ------------------- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **adUnitId**        | String   | **Si**    | El ID del ad unit a asignar al banner                                                                                         |
| **adSize**          | AdSize   | No        | Tamaño máximo (altura) para el banner. Los posibles valores para este parámetro se encuentran declarados en la clase `AdSize` |
| **autoRefreshTime** | Integer  | No        | Valor en segundos que representa el tiempo que deberá transcurrir para que se realice la carga de un nuevo anuncio banner     |
| **keepAlive**       | Boolean  | No        | Indica si la instancia del banner debe mantenerse "viva" en todo momento                                                      |
| **listener**        | Function | No        | Listener para recibir los eventos del banner (`BannerAdEvent`)                                                                |

## **Banners adaptativos**

Los banners adaptativos son un nuevo formato de banner que se caracteriza por adaptar el tamaño de los anuncios según el dispositivo y la interfaz de la aplicación, para lograr maximizar el rendimiento.

Actualmente existe soporte para dos tipos de banners adaptativos:

### Anclados

Este tipo de banner está diseñado para reemplazar a los banners tradicionales de 320x50 y ser posicionado en la parte superior o inferior de la pantalla.

Para hacer uso de este formato, se debe pasar un `AdSize` al widget `BannerAd` generado de la siguiente manera:

```dart
// Es necesario especificar la anchura del banner
AdSize.getAnchoredAdaptiveBannerAdSize(width);
```

### Inline

Este otro tipo de banner, en comparación con los anclados, está diseñado para tener una altura variable y ser posicionado dentro de un contenido desplazable.

En este caso, se debe generar un `AdSize` como se muestra a continuación:

```dart
// Es necesario especificar la anchura del banner. La altura máxima es un
// parámetro opcional (pasando valor 0 o negativo)
AdSize.getInlineAdaptiveBannerAdSize(width, maxHeight);
```

## **Configuración del listener**

Se puede añadir un listener a cualquier instancia de `BannerAd` para recibir los diferentes eventos que\
sucedan durante su ciclo de vida. Para ello, es necesario asignar una función al parámetro `listener` del widget, tal y como se muestra a continuación:

```dart
BannerAd(
  adSize: AdSize.HEIGHT_50,
  adUnitId: 'Ad Unit ID de Wortise',
  listener: (event, args) {
    switch (event) {
      case BannerAdEvent.CLICKED: {
        // El anuncio ha sido clickeado
      }
      break;
      
      case BannerAdEvent.FAILED_TO_LOAD: {
        // El anuncio no se ha podido cargar
      }
      break;

      case BannerAdEvent.IMPRESSION: {
        // El anuncio ha generado una impresión 
      }
      break;
      
      case BannerAdEvent.LOADED: {
        // El anuncio ha sido cargado
      }
      break;
      
      case BannerAdEvent.REVENUE_PAID: {
        // El anuncio ha sido generado un ingreso
      }
      break;
    }
  },
)
```


# Interstitial

## Integración

A continuación se muestra un sencillo ejemplo para entender el funcionamiento de los intersticiales:

```dart
import 'package:wortise/interstitial_ad.dart';

InterstitialAd _interstitialAd;

// Se crea un intersticial
_interstitialAd = InterstitialAd('Ad Unit ID de Wortise', listener: (event, args) {
  // Este listener será invocado cuando se produzca algún evento
});

// Se solicita la carga de un anuncio
await _interstitialAd.loadAd();

/* ... */

// Se muestra el anuncio si está disponible
if (await _interstitialAd.isAvailable) {
  await _interstitialAd.showAd();
}
```

El constructor de la clase `InterstitialAd` admite un tercer parámetro, llamado `reloadOnDismissed`, que al establecerse a `true` (el valor por defecto es `false`) permite que el interstitial cargue automáticamente un nuevo anuncio cuando se finalice de mostrar el actual.

## **Eventos del listener**

El listener asignado a un `InterstitialAd` puede recibir los siguientes eventos:

```dart
// El anuncio ha sido clickeado
InterstitialAdEvent.CLICKED
// El anuncio ha sido cerrado
InterstitialAdEvent.DISMISSED
// El anuncio no se ha podido cargar
InterstitialAdEvent.FAILED_TO_LOAD
// El anuncio no se ha podido mostrar
InterstitialAdEvent.FAILED_TO_SHOW
// El anuncio ha generado una impresión
InterstitialAdEvent.IMPRESSION
// El anuncio ha sido cargado
InterstitialAdEvent.LOADED
// El anuncio ha generado un ingreso
InterstitialAdEvent.REVENUE_PAID
// El anuncio ha sido mostrado
InterstitialAdEvent.SHOWN
```


# Rewarded

## Integración

A continuación se muestra un sencillo ejemplo para entender el funcionamiento de los anuncios recompensados:

```dart
import 'package:wortise/rewarded_ad.dart';

RewardedAd _rewardedAd;

// Se crea un recompensado
_rewardedAd = RewardedAd('Ad Unit ID de Wortise', listener: (event, args) {
  // Este listener será invocado cuando se produzca algún evento
});

// Se solicita la carga de un anuncio
await _rewardedAd.loadAd();

/* ... */

// Se muestra el anuncio si está disponible
if (await _rewardedAd.isAvailable) {
  await _rewardedAd.showAd();
}
```

El constructor de la clase `RewardedAd` admite un tercer parámetro, llamado `reloadOnDismissed`, que al establecerse a `true` (el valor por defecto es `false`) permite que el recompensado cargue automáticamente un nuevo anuncio cuando se finalice de mostrar el actual.

## **Eventos del listener**

El listener asignado a un `RewardedAd` puede recibir los siguientes eventos:

```dart
// El anuncio ha sido clickeado
RewardedAdEvent.CLICKED
// El anuncio ha sido completado
// (los argumentos 'amount', 'label' y 'success' son especificados)
RewardedAdEvent.COMPLETED
// El anuncio ha sido cerrado
RewardedAdEvent.DISMISSED
// El anuncio no se ha podido cargar
RewardedAdEvent.FAILED_TO_LOAD
// El anuncio no se ha podido mostrar
RewardedAdEvent.FAILED_TO_SHOW
// El anuncio ha generado una impresión
RewardedAdEvent.IMPRESSION
// El anuncio ha sido cargado
RewardedAdEvent.LOADED
// El anuncio ha generado un ingreso
RewardedAdEvent.REVENUE_PAID
// El anuncio ha sido mostrado
RewardedAdEvent.SHOWN
```

A continuación,  se muestra un pequeño ejemplo para obtener la recompensa una vez el anuncio ha sido completado con éxito:

```dart
(event, args) {
  if (event == RewardedAdEvent.COMPLETED) {
    int    amount  = args['amount'];
    String label   = args['label'];
    bool   success = args['success'];
    
    ...
  }
});
```


# Native (Google)

Los anuncios nativos son un tipo de anuncio que puede ser mostrado con el mismo estilo visual del resto de la app, lo que permite una integración natural y no-intrusiva con la interfaz de usuario.

Actualmente, desde Wortise ofrecemos la posibilidad de utilizar los anuncios nativos de la plataforma de anuncios de Google, de una manera directa y sencilla.

## Integración

En primer lugar, es necesario crear una clase Java (o Kotlin) que implemente un objeto `GoogleNativeAdFactory.` Este objeto contendrá un método que recibirá un `NativeAd` de Google y devolverá un objeto `NativeAdView` con al anuncio nativo renderizado.

Este paso es muy similar al explicado por Google en su propia [documentación](https://developers.google.com/admob/flutter/native?hl=es#platform_setup), con la única diferencia de utilizar `GoogleNativeAdFactory` en lugar de `NativeAdFactory` .

A continuación, se muestra un ejemplo de implementación de esta clase:

```kotlin
import android.graphics.Color
import android.view.LayoutInflater
import android.widget.TextView
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView

class NativeAdFactoryExample(private val layoutInflater: LayoutInflater)
    : GoogleNativeAdFactory {

    override fun createNativeAd(nativeAd: NativeAd): NativeAdView {
        val adView = layoutInflater.inflate(R.layout.my_native_ad, null) as NativeAdView
        
        val headlineView = adView.findViewById<TextView>(R.id.ad_headline)
        val bodyView     = adView.findViewById<TextView>(R.id.ad_body)
    
        headlineView.setText(nativeAd.headline)

        bodyView.setText(nativeAd.body)
    
        adView.setBackgroundColor(Color.YELLOW)
        adView.setNativeAd(nativeAd)
        adView.setBodyView(bodyView)
        adView.setHeadlineView(headlineView)
        
        return adView
    }
}
```

Una vez implementada, hay que registrar esta clase dentro de `MainActivity` como en el siguiente ejemplo:

```kotlin
import com.wortise.ads.flutter.natives.GoogleNativeAdManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine

class MainActivity: FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        GoogleNativeAdManager.registerAdFactory(
            "test-factory", NativeAdFactoryExample(layoutInflater))
    }

    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine)

        GoogleNativeAdManager.unregisterAdFactory("test-factory")
    }
}
```

En este ejemplo, `test-factory` es el identificador que se le asigna al objeto `GoogleNativeAdFactory` y que debe ser utilizado más tarde al crear un anuncio nativo en Flutter.

A continuación, para solicitar un anuncio nativo, es necesario realizar una integración por código como la siguiente:

```dart
import 'package:wortise/google_native_ad.dart';

GoogleNativeAd _interstitialAd;

// Se crea un native

// Es necesario especificar el ID del objeto "GoogleNativeAdFactory" indicado
// anteriormente
_nativeAd = GoogleNativeAd('test-native', 'test-factory', (event, args) {
  // Este listener será invocado cuando se produzca algún evento
});

// Se solicita la carga de un anuncio
await _nativeAd.loadAd();
```

Una vez el anuncio nativo ha sido cargado con éxito, es necesario crear un widget de tipo `AdWidget` que debe ser añadido a la interfaz de la app.

Este paso se puede implementar como se muestra en el siguiente ejemplo:

```dart
import 'package:wortise/ad_widget.dart';
import 'package:wortise/google_native_ad.dart';

GoogleNativeAd? _nativeAd;

AdWidget? _nativeWidget;
  
// Se crea un native
_nativeAd = GoogleNativeAd('test-native', 'test-factory', (event, args) {
  // Se recibe un evento indicando una carga exitosa
  if (event == GoogleNativeAdEvent.LOADED) {
    // Se crea un widget "AdWidget" con el anuncio nativo
    // Este widget se debe añadir a la interfaz de la app para mostrar el anuncio
    setState(() => _nativeWidget = AdWidget(ad: _nativeAd!));
  }
});
```

## **Eventos del listener**

El listener asignado a un `GoogleNativeAd` puede recibir los siguientes eventos:

```dart
// El anuncio ha sido clickeado
GoogleNativeAdEvent.CLICKED
// El anuncio no se ha podido cargar
GoogleNativeAdEvent.FAILED_TO_LOAD
// El anuncio ha generado una impresión
GoogleNativeAdEvent.IMPRESSION
// El anuncio ha sido cargado
GoogleNativeAdEvent.LOADED
// El anuncio ha generado un ingreso
GoogleNativeAdEvent.REVENUE_PAID
```


# Targeting

## Solicitar permisos

{% hint style="info" %}
Este paso es **totalmente opcional** y solo se debe implementar si resulta conveniente para la finalidad de la aplicación.
{% endhint %}

La aplicación puede solicitar los permisos de ubicación para que nuestro SDK pueda obtener la localización actual del usuario y mostrar anuncios de mayor interés en base a dicho dato.

Para ello, es necesario añadir los siguientes permisos en el fichero `android/app/src/main/AndroidManifest.xml`:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

A continuación, se debe realizar la solicitud de los permisos para que los usuarios puedan otorgar su autorización. Para ello, por ejemplo, se puede hacer uso de la librería [permission\_handler](https://pub.dev/packages/permission_handler).


# Reporte de ingresos

## Implementación

Desde la versión **1.7.0**, las apps pueden recibir un reporte estimado del ingreso que previsiblemente ha sido generado por un anuncio.

Para ello, simplemente hay que implementar el listener correspondiente para cada formato de anuncio, como se muestra en el ejemplo a continuación:

```dart
BannerAd(
  ...
  listener: (event, args) {
    if (event == BannerAdEvent.REVENUE_PAID) {
      // El anuncio ha sido generado un ingreso
    }
  },
)
```

El listener recibe como argumento un objeto que contiene los siguientes campos:

<table><thead><tr><th width="139.62109375">Campo</th><th width="175.3203125">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>Map</code></td><td>El ingreso generado por el anuncio</td></tr><tr><td><code>source</code></td><td><code>String</code></td><td>La fuente del ingreso</td></tr></tbody></table>

Además, el objeto `revenue` contiene los siguientes campos que representan al ingreso:

<table><thead><tr><th width="140.49609375">Campo</th><th width="174.91796875">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>String</code></td><td>La divisa correspondiente al ingreso </td></tr><tr><td><code>precision</code></td><td><code>String</code></td><td>La precisión de la información. Puede ser <code>ESTIMATED</code>, <code>PRECISE</code> o <code>PUBLISHER_DEFINED</code></td></tr><tr><td><code>value</code></td><td><code>double</code></td><td>El valor del ingreso</td></tr></tbody></table>

## Integración con Firebase

A continuación, se muestra un ejemplo básico para reportar la información de los ingresos a Firebase:

```dart
final analytics = FirebaseAnalytics();

BannerAd(
  ...
  listener: (event, args) {
    if (event == BannerAdEvent.REVENUE_PAID) {
      analytics.logEvent(
        name: 'ad_revenue',
        parameters: {
          'currency':  args['revenue']['currency'],
          'precision': args['revenue']['precision'],
          'source':    args['source'],
          'value':     args['revenue']['value'],
        },
      );
    }
  },
)
```


# Consentimiento del usuario

El SDK de Wortise incluye soporte para el gestor de consentimiento (también llamado **Consent Manager** o **CMP**) de Google Ads para solicitar el consentimiento de cada usuario.

Obtener el consentimiento del usuario es importante para cumplir con las políticas de privacidad y optar a mayores CPM.

## Solicitar consentimiento

Para solicitar el consentimiento del usuario, es necesario llamar al método `ConsentManager.requestIfRequired` en un momento apropiado de la app. Esto mostrará un diálogo, solamente cuando sea totalmente necesario (normalmente en el primer arranque de la app), para que el usuario otorgue o deniegue su consentimiento.

También está disponible el método `ConsentManager.request` si se desea mostrar el diálogo siempre, y no exclusivamente cuando resulte necesario (por ejemplo, para ofrecer una opción en la pantalla de ajustes de la app que permita al usuario cambiar su consentimiento en cualquier momento).

### Ejemplo

```dart
import 'package:wortise/consent_manager.dart';

await ConsentManager.requestIfRequired();
```


# Privacidad

## Política de Familias (Families Policy)

Si tu aplicación está dirigida (exclusivamente o no) a usuarios menores de edad, es necesario cumplir con los requisitos establecidos por la [Política de Familias](https://support.google.com/googleplay/android-developer/answer/9900633) de Google Play.

Para facilitar el cumplimiento de estas políticas, el SDK permite especificar si las solicitudes de anuncios están dirigidas a menores de edad, además de poder establecer la clasificación de edad máxima permitida.

Es importante cumplir con estos requisitos, y revisar detenidamente las políticas asociadas, para evitar problemas con Google Play.

### Contenido dirigido a menores

Para indicar si un usuario es menor de edad o no, es necesario incluir el siguiente código **antes** de inicializar el SDK:

```dart
import 'package:wortise/ad_settings.dart';

// true  -> El usuario es menor de edad o la edad es desconocida
// false -> El usuario es mayor de edad
await AdSettings.setChildDirected(true);
```

Si se desconoce la edad del usuario, la app debe tratar a dicho usuario como si fuese menor de edad.

### Clasificación de edad

Para especificar la clasificación de edad máxima, se debe añadir el siguiente código antes de inicializar el SDK:

```dart
import 'package:wortise/ad_content_rating.dart';
import 'package:wortise/ad_settings.dart';

await AdSettings.setMaxAdContentRating(AdContentRating.G);
```

Los siguientes valores están disponibles a la hora de indicar la clasificación de edad:

| Valor                | Descripción                                                                   |
| -------------------- | ----------------------------------------------------------------------------- |
| `AdContentRating.G`  | Contenido adecuado para todas las audiencias                                  |
| `AdContentRating.PG` | Contenido adecuado para la mayoría de las audiencias con supervisión parental |
| `AdContentRating.T`  | Contenido adecuado para adolescentes                                          |
| `AdContentRating.MA` | Contenido adecuado únicamente para adultos                                    |

{% hint style="info" %}
Si la app está dirigida principalmente a niños, es completamente necesario especificar la clasificación `G`.

En cambio, si la audiencia de la app es mixta, se debe especificar una clasificación `G` o `PG`.
{% endhint %}

### Requisitos adicionales

Si tu aplicación está dirigida a niños, sea exclusivamente o no, es necesario eliminar el adaptador de Facebook que viene incluido en nuestro SDK debido a que todavía no se encuentra certificado por Google Play para su uso con niños.

Para ello, es necesario añadir las siguientes líneas dentro del fichero `android/app/build.gradle`:

```groovy
configurations {
    all*.exclude group: 'com.google.ads.mediation', module: 'facebook'
}
```


# Integración del SDK

## Instalar dependencia

Para integrar nuestro SDK para React Native, es necesario ejecutar el siguiente comando en la raíz del proyecto:

```bash
npm install @wortise/react-native-sdk --save
```

{% hint style="info" %}
La última versión del SDK para React Native es la **1.7.6**
{% endhint %}

## Configurar proyecto Expo

Si tu proyecto utiliza el framework **Expo**, el proceso de configuración se puede realizar de una manera sencilla.

Simplemente hay que agregar los siguientes detalles dentro del fichero `app.json` del proyecto:

```json
{
  "expo": {
    "plugins": [
      [
        "@wortise/react-native-sdk",
        {
          "androidGoogleAppId": "ca-app-pub-xxxxxxxxxxxxxx~yyyyyyyyyy",
          "iosGoogleAppId": "ca-app-pub-xxxxxxxxxxxxxx~yyyyyyyyyy"
        }
      ]
    ]
  }
}
```

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

Tras realizar esta configuración, nuestro plugin se encargará de insertar los "App ID" de Google para ambas plataformas, al igual que los repositorios y otros detalles que son necesarios para completar la integración del SDK.

## Configuración manual

Si tu proyecto no utiliza el framework Expo, o prefieres realizar una configuración manual, debes seguir los siguientes pasos que aparecen a continuación.

### Agregar repositorios (Android)

A continuación, hay que añadir los siguientes repositorios Maven en el bloque `allprojects > repositories` del fichero `android/build.gradle`:

```groovy
allprojects {
    repositories {
        ...
        maven { url 'https://maven.wortise.com/artifactory/public' }
        
        maven { url 'https://android-sdk.is.com/' }
        maven { url 'https://artifact.bytedance.com/repository/pangle' }
        maven { url 'https://cboost.jfrog.io/artifactory/chartboost-ads/' }
    }
}
```

### Configurar Manifest (Android)

Es necesario agregar el siguiente elemento `<meta-data>` en el fichero `android/app/src/main/AndroidManifest.xml`, dentro del bloque `<application>`, con el ID de aplicación de Google como valor:

```xml
<manifest>
    ...
    <application>
        ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>
```

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

### Configurar Info.plist (iOS)

Es necesario agregar el siguiente parámetro en el fichero `Info.plist`, con el ID de aplicación de Google como valor:

```xml
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxxxx</string>
```

{% hint style="info" %}
Este valor puede ser localizado en nuestro dashboard, dentro de los detalles de cada aplicación, bajo el nombre `Google App ID`.
{% endhint %}

A continuación, solo faltaría añadir el siguiente bloque, en el mismo fichero, para finalizar la correcta integración con Google:

<pre class="language-xml"><code class="lang-xml"><strong>&#x3C;key>SKAdNetworkItems&#x3C;/key>
</strong>&#x3C;array>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>cstr6suwn9.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4fzdc2evr5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4pfyvq9l8r.skadnetwork &#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>2fnua5tdw4.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ydx93a7ass.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>5a6flpkh64.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>p78axxw29g.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v72qych5uu.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ludvb6z3bs.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>cp8zw746q7.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>c6k4g5qg8m.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>s39g8k73mm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3qy4746246.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3sh42y64q3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>f38h382jlk.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>hs6bdukanm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>prcb7njmu6.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v4nxqhlyqp.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>wzmmz9fp6w.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>yclnxrl5pm.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>t38b2kh725.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>7ug5zh24hu.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>9rd848q2bz.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>y5ghdn5j9k.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>n6fk4nfna4.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>v9wttpbfk9.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>n38lu8286q.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>47vhws6wlr.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>kbd757ywx3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>9t245vhmpl.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>a2p9lx4jpn.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>22mmun2rn5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4468km3ulz.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>2u9pt9hc89.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>8s468mfl3y.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>av6w8kgt66.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>klf5c3l5u5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ppxm28t8ap.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>424m5254lk.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>ecpz2srf59.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>uw77j35x4d.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>mlmmfzh3r3.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>578prtvx9j.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>4dzt52r2t5.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>gta9lk7p23.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>e5fvkxwrpn.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>8c4e2ghe7u.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>zq492l623r.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3rd42ekr43.skadnetwork&#x3C;/string>
    &#x3C;/dict>
    &#x3C;dict>
    &#x3C;key>SKAdNetworkIdentifier&#x3C;/key>
    &#x3C;string>3qcr597p9d.skadnetwork&#x3C;/string>
    &#x3C;/dict>
&#x3C;/array>
</code></pre>

## Solicitar consentimiento

{% hint style="success" %}
Es **muy recomendable** solicitar consentimiento al usuario para poder mostrar anuncios personalizados. Esto permitirá mostrar contenido que resulte de mayor interés y generar ingresos superiores.
{% endhint %}

Puede consultar el siguiente apartado para implementar esta solicitud y obtener el consentimiento de los usuarios: [Consentimiento del usuario](/react-native/consentimiento-del-usuario)

## Inicializar SDK

Existen dos opciones para realizar la inicialización del SDK:

### Opción 1 (recomendado)

La opción más recomendada es realizar la inicialización desde la clase `Application` de la app. Para ello, hay que integrar el siguiente código en el método `onCreate()` del fichero `MainApplication.java`:

```java
WortiseSdk.initialize(this, "tu app key");
```

### Opción 2

En esta opción, la inicialización del SDK se realizaría directamente desde el código JavaScript del proyecto. Para ello, hay que añadir las siguientes líneas de código en un lugar apropiado:

```javascript
import { RNWortiseSdk } from '@wortise/react-native-sdk';

await RNWortiseSdk.initialize('tu app key');
```

## Modo de prueba

Para verificar la integración, el SDK ofrece un modo de prueba (*test mode*) que permite que la app siempre reciba anuncios.

Además de la opción que hay disponible en nuestro dashboard, es posible activar este modo de prueba programáticamente, desde el propio SDK, utilizando el siguiente código:

```javascript
import { RNWortiseAdSettings } from '@wortise/react-native-sdk';

RNWortiseAdSettings.setTestEnabled(true);
```


# App Open

## Integración

Para hacer uso de los anuncios App Open, es necesario solicitar su carga en algún momento de la app, siendo recomendable hacerlo lo más pronto posible.

A continuación, se muestra un ejemplo de como cargar y mostrar un anuncio:

```typescript
import { RNWortiseAppOpen } from '@wortise/react-native-sdk';

RNWortiseAppOpen.setAdUnitId('Ad Unit ID de Wortise');
RNWortiseAppOpen.loadAd();
```

A continuación, para mostrar el anuncio en el momento deseado, se pueden usar los métodos `showAd()` y `isAvailable` tal y como se muestra en el siguiente ejemplo:

```typescript
if (await RNWortiseAppOpen.isAvailable) {
    RNWortiseAppOpen.showAd();
}
```

Además, la clase `RNWortiseAppOpen` ofrece los siguientes métodos adicionales para configurar su comportamiento:

{% hint style="info" %}
Estos métodos deben ser invocados después de llamar al método `setAdUnitId()`
{% endhint %}

```typescript
// Establece si se debe cargar un nuevo anuncio tras cerrar el anterior
RNWortiseAppOpen.setAutoReload(true);

// Muestra un anuncio inmediatamente si está disponible. En caso contrario,
// solicita la carga de un nuevo anuncio
RNWortiseAppOpen.tryToShowAd();
```

## **Configuración de listeners**

Se pueden añadir listeners para recibir los diferentes eventos que sucedan durante el ciclo de vida del anuncio. Para ello, es necesario usar el método `addEventListener` y especificar el tipo de evento que se desea recibir, el cual debe ser alguno de los siguientes:

* `onAppOpenClicked`
* `onAppOpenDismissed`
* `onAppOpenFailedToLoad`
* `onAppOpenFailedToShow`
* `onAppOpenImpression`
* `onAppOpenLoaded`
* `onAppOpenRevenuePaid`
* `onAppOpenShown`

### Ejemplo

```typescript
RNWortiseAppOpen.addEventListener('onAppOpenLoaded', () => {
  // El callback será invocado cuando se haya cargado un anuncio
});
```


# Banner

Los anuncios de banner son anuncios de imagen o de texto rectangulares que ocupan un lugar dentro del diseño de una aplicación. Permanecen en la pantalla mientras los usuarios interactúan con la aplicación y pueden actualizarse automáticamente después de un cierto período de tiempo. Si eres nuevo en la publicidad móvil, son una excelente opción para comenzar.

## **Integración**

La integración de los banners se realiza añadiendo el widget `WortiseBanner` en el layout de la aplicación. A continuación, se muestra un sencillo ejemplo de integración:

```tsx
import { RNWortiseAdSize, WortiseBanner } from '@wortise/react-native-sdk';

/* ... */

const bannerRef = useRef(null);

return (
  <View style={styles.container}>
    <Button
      onPress={bannerRef.current?.loadAd()}
      title="Cargar Banner"
    />
    <WortiseBanner
      ref={bannerRef}
      adSize={RNWortiseAdSize.HEIGHT_50}
      adUnitId="Ad Unit ID de Wortise"
    />
  </View>
);
```

{% hint style="warning" %}
Desde la versión `1.6.1+patch.1`, es necesario llamar al método `loadAd()` para iniciar la carga del banner.&#x20;
{% endhint %}

El widget tiene soporte para los siguientes parámetros:

<table data-header-hidden><thead><tr><th width="170.15234375">Parámetro</th><th width="115.12890625">Tipo</th><th width="110.36328125">Requerido</th><th>Descripción</th></tr></thead><tbody><tr><td>Parámetro</td><td>Tipo</td><td>Requerido</td><td>Descripción</td></tr><tr><td><strong>adUnitId</strong></td><td>String</td><td><strong>Si</strong></td><td>El ID del ad unit a asignar al banner</td></tr><tr><td><strong>adSize</strong></td><td>String</td><td>No</td><td>Tamaño máximo (altura) para el banner. Los posibles valores para este parámetro se encuentran declarados en el objeto <code>RNWortiseAdSize</code></td></tr><tr><td><strong>autoRefreshTime</strong></td><td>Integer</td><td>No</td><td>Valor en segundos que representa el tiempo que deberá transcurrir para que se realice la carga de un nuevo anuncio banner</td></tr><tr><td><strong>onClicked</strong></td><td>Function</td><td>No</td><td>Función que es invocada cuando el banner ha sido clickeado</td></tr><tr><td><strong>onFailedToLoad</strong></td><td>Function</td><td>No</td><td>Función que es invocada cuando el banner no ha podido cargar un anuncio</td></tr><tr><td><strong>onImpression</strong></td><td>Function</td><td>No</td><td>Función que es invocada cuando el banner ha generado una impresión</td></tr><tr><td><strong>onLoaded</strong></td><td>Function</td><td>No</td><td>Función que es invocada cuando el banner ha cargado un anuncio</td></tr><tr><td><strong>onRevenuePaid</strong></td><td>Function</td><td>No</td><td>Función que es invocada cuando el banner ha generado un ingreso</td></tr><tr><td><strong>onSizeChange</strong></td><td>Function</td><td>No</td><td>Función que es invocada cuando el banner ha cambiado de tamaño</td></tr></tbody></table>

## **Banners adaptativos**

Los banners adaptativos son un nuevo formato de banner que se caracteriza por adaptar el tamaño de los anuncios según el dispositivo y la interfaz de la aplicación, para lograr maximizar el rendimiento.

Actualmente existe soporte para dos tipos de banners adaptativos:

### Anclados

Este tipo de banner está diseñado para reemplazar a los banners tradicionales de 320x50 y ser posicionado en la parte superior o inferior de la pantalla.

Para hacer uso de este formato, se debe pasar un `AdSize` al widget `BannerAd` generado de la siguiente manera:

```typescript
import { RNWortiseAdSize } from '@wortise/react-native-sdk';

// Es necesario especificar la anchura del banner
RNWortiseAdSize.getAnchoredAdaptiveBannerAdSize(width);
```

### Inline

Este otro tipo de banner, en comparación con los anclados, está diseñado para tener una altura variable y ser posicionado dentro de un contenido desplazable.

En este caso, se debe generar un `AdSize` como se muestra a continuación:

```typescript
import { RNWortiseAdSize } from '@wortise/react-native-sdk';

// Es necesario especificar la anchura del banner. La altura máxima es un
// parámetro opcional (pasando valor 0 o negativo)
RNWortiseAdSize.getInlineAdaptiveBannerAdSize(width, maxHeight);
```


# Interstitial

## Integración

Para hacer uso de los anuncios intersticiales, es necesario solicitar su carga en algún momento de la app, siendo recomendable hacerlo lo más pronto posible. Esto se puede realizar utilizando el siguiente código:

```typescript
import { RNWortiseInterstitial } from '@wortise/react-native-sdk';

RNWortiseInterstitial.setAdUnitId('Ad Unit ID de Wortise');
RNWortiseInterstitial.loadAd();
```

A continuación, para mostrar el anuncio en el momento deseado, se pueden usar los métodos `showAd()` y `isAvailable` tal y como se muestra en el siguiente ejemplo:

```typescript
if (await RNWortiseInterstitial.isAvailable) {
    RNWortiseInterstitial.showAd();
}
```

## **Configuración de listeners**

Se pueden añadir listeners para recibir los diferentes eventos que sucedan durante el ciclo de vida del anuncio. Para ello, es necesario usar el método `addEventListener` y especificar el tipo de evento que se desea recibir, el cual debe ser alguno de los siguientes:

* `onInterstitialClicked`
* `onInterstitialDismissed`
* `onInterstitialFailedToLoad`
* `onInterstitialFailedToShow`
* `onInterstitialImpression`
* `onInterstitialLoaded`
* `onInterstitialRevenuePaid`
* `onInterstitialShown`

### Ejemplo

```typescript
RNWortiseInterstitial.addEventListener('onInterstitialLoaded', () => {
  // El callback será invocado cuando se haya cargado un anuncio
});
```


# Rewarded

## Integración

Para hacer uso de los anuncios recompensados, es necesario solicitar su carga en algún momento de la app, siendo recomendable hacerlo lo más pronto posible. Esto se puede realizar utilizando el siguiente código:

```typescript
import { RNWortiseRewarded } from '@wortise/react-native-sdk';

RNWortiseRewarded.setAdUnitId('Ad Unit ID de Wortise');
RNWortiseRewarded.loadAd();
```

A continuación, para mostrar el anuncio en el momento deseado, se pueden usar los métodos `showAd()` y `isAvailable` tal y como se muestra en el siguiente ejemplo:

```typescript
if (await RNWortiseRewarded.isAvailable) {
    RNWortiseRewarded.showAd();
}
```

## **Configuración de listeners**

Se pueden añadir listeners para recibir los diferentes eventos que sucedan durante el ciclo de vida del anuncio. Para ello, es necesario usar el método `addEventListener` y especificar el tipo de evento que se desea recibir, el cual debe ser alguno de los siguientes:

* `onRewardedClicked`
* `onRewardedCompleted`
* `onRewardedDismissed`
* `onRewardedFailedToLoad`
* `onRewardedFailedToShow`
* `onRewardedImpression`
* `onRewardedLoaded`
* `onRewardedRevenuePaid`
* `onRewardedShown`

### Ejemplo

```typescript
RNWortiseRewarded.addEventListener('onRewardedCompleted', ({ amount, label, success }) => {
  // El callback será invocado cuando el anuncio haya sido completado
});

RNWortiseRewarded.addEventListener('onRewardedLoaded', () => {
  // El callback será invocado cuando se haya cargado un anuncio
});
```


# Targeting

## Solicitar permisos

{% hint style="info" %}
Este paso es **totalmente opcional** y solo se debe implementar si resulta conveniente para la finalidad de la aplicación.
{% endhint %}

La aplicación puede solicitar los permisos de ubicación para que nuestro SDK pueda obtener la localización actual del usuario y mostrar anuncios de mayor interés en base a dicho dato.

Para ello, es necesario añadir los siguientes permisos en el fichero  `android/app/src/main/AndroidManifest.xml`:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

A continuación, se debe realizar la solicitud de los permisos para que los usuarios puedan otorgar su autorización, tal y como se indica en la [documentación oficial](https://reactnative.dev/docs/permissionsandroid) de React Native.

### Ejemplo

```typescript
import { PermissionsAndroid } from 'react-native';

await PermissionsAndroid.requestMultiple([
  PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
  PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION
]);
```


# Reporte de ingresos

## Implementación

Desde la versión **1.7.0**, las apps pueden recibir un reporte estimado del ingreso que previsiblemente ha sido generado por un anuncio.

Para ello, simplemente hay que implementar el listener correspondiente para cada formato de anuncio, como se muestra en el ejemplo a continuación:

```tsx
function onRevenuePaid(data) {
  // El anuncio ha sido generado un ingreso
}

<WortiseBanner
  ...
  onRevenuePaid={onRevenuePaid}
/>
```

El listener recibe como argumento un objeto que contiene los siguientes campos:

<table><thead><tr><th width="139.62109375">Campo</th><th width="175.3203125">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>Object</code></td><td>El ingreso generado por el anuncio</td></tr><tr><td><code>source</code></td><td><code>String</code></td><td>La fuente del ingreso</td></tr></tbody></table>

Además, el objeto `revenue` contiene los siguientes campos que representan al ingreso:

<table><thead><tr><th width="140.49609375">Campo</th><th width="174.91796875">Tipo</th><th>Descripción</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>String</code></td><td>La divisa correspondiente al ingreso </td></tr><tr><td><code>precision</code></td><td><code>String</code></td><td>La precisión de la información. Puede ser <code>ESTIMATED</code>, <code>PRECISE</code> o <code>PUBLISHER_DEFINED</code></td></tr><tr><td><code>value</code></td><td><code>double</code></td><td>El valor del ingreso</td></tr></tbody></table>

## Integración con Firebase

A continuación, se muestra un ejemplo básico para reportar la información de los ingresos a Firebase:

```tsx
import analytics from '@react-native-firebase/analytics';

function onRevenuePaid({ revenue, source }) {
  const { currency, precision, value } = revenue;

  analytics().logEvent('ad_revenue', {
    currency,
    precision,
    source,
    value
   });
}

<WortiseBanner
  ...
  onRevenuePaid={onRevenuePaid}
/>
```


# Consentimiento del usuario

El SDK de Wortise incluye soporte para el gestor de consentimiento (también llamado **Consent Manager** o **CMP**) de Google Ads para solicitar el consentimiento de cada usuario.

Obtener el consentimiento del usuario es importante para cumplir con las políticas de privacidad y optar a mayores CPM.

## Solicitar consentimiento

Para solicitar el consentimiento del usuario, es necesario llamar al método `RNWortiseConsentManager.requestifRequired` en un momento apropiado de la app. Esto mostrará un diálogo, solamente cuando sea totalmente necesario (normalmente en el primer arranque de la app), para que el usuario otorgue o deniegue su consentimiento.

También está disponible el método `RNWortiseConsentManager.request` si se desea mostrar el diálogo siempre, y no exclusivamente cuando resulte necesario (por ejemplo, para ofrecer una opción en la pantalla de ajustes de la app que permita al usuario cambiar su consentimiento en cualquier momento).

### Ejemplo

```typescript
import {
  RNWortiseConsentManager,
  RNWortiseSdk
} from '@wortise/react-native-sdk';

RNWortiseSdk.wait().then(() => RNWortiseConsentManager.requestIfRequired());
```


# Privacidad

## Política de Familias (Families Policy)

Si tu aplicación está dirigida (exclusivamente o no) a usuarios menores de edad, es necesario cumplir con los requisitos establecidos por la [Política de Familias](https://support.google.com/googleplay/android-developer/answer/9900633) de Google Play.

Para facilitar el cumplimiento de estas políticas, el SDK permite especificar si las solicitudes de anuncios están dirigidas a menores de edad, además de poder establecer la clasificación de edad máxima permitida.

Es importante cumplir con estos requisitos, y revisar detenidamente las políticas asociadas, para evitar problemas con Google Play.

### Contenido dirigido a menores

Para indicar si un usuario es menor de edad o no, es necesario incluir el siguiente código **antes** de inicializar el SDK:

```typescript
import { RNWortiseAdSettings } from '@wortise/react-native-sdk';

// true  -> El usuario es menor de edad o la edad es desconocida
// false -> El usuario es mayor de edad
RNWortiseAdSettings.setChildDirected(true);
```

Si se desconoce la edad del usuario, la app debe tratar a dicho usuario como si fuese menor de edad.

### Clasificación de edad

Para especificar la clasificación de edad máxima, se debe añadir el siguiente código antes de inicializar el SDK:

```typescript
import {
  RNWortiseAdContentRating,
  RNWortiseAdSettings
} from '@wortise/react-native-sdk';

RNWortiseAdSettings.setMaxAdContentRating(RNWortiseAdContentRatingontentRating.G);
```

Los siguientes valores están disponibles a la hora de indicar la clasificación de edad:

<table><thead><tr><th width="387.3414252561863">Valor</th><th>Descripción</th></tr></thead><tbody><tr><td><code>RNWortiseAdContentRating.G</code></td><td>Contenido adecuado para todas las audiencias</td></tr><tr><td><code>RNWortiseAdContentRating.PG</code></td><td>Contenido adecuado para la mayoría de las audiencias con supervisión parental</td></tr><tr><td><code>RNWortiseAdContentRating.T</code></td><td>Contenido adecuado para adolescentes</td></tr><tr><td><code>RNWortiseAdContentRatingtRating.MA</code></td><td>Contenido adecuado únicamente para adultos</td></tr></tbody></table>

{% hint style="info" %}
Si la app está dirigida principalmente a niños, es completamente necesario especificar la clasificación `G`.

En cambio, si la audiencia de la app es mixta, se debe especificar una clasificación `G` o `PG`.
{% endhint %}

### Requisitos adicionales

Si tu aplicación está dirigida a niños, sea exclusivamente o no, es necesario eliminar el adaptador de Facebook que viene incluido en nuestro SDK debido a que todavía no se encuentra certificado por Google Play para su uso con niños.

Para ello, es necesario añadir las siguientes líneas dentro del fichero `android/build.gradle`:

```groovy
configurations {
    all*.exclude group: 'com.google.ads.mediation', module: 'facebook'
}
```


# Integración del SDK

## Configurar sitio web

Para realizar la integración de nuestro SDK web, es necesario agregar el siguiente tag JavaScript dentro del bloque `<head>` del sitio web, especificando el "**asset key**" proporcionado por nuestra plataforma:

```javascript
<script type="text/javascript" async src="https://cdn.resources.wortise.com/sdk/web/web-sdk.js">
    wortise.init('tu asset key')
</script>
```

## Formatos de anuncio

### Banner

Los anuncios de banner son anuncios de imagen o de texto rectangulares que ocupan un lugar dentro del diseño de un sitio web. Permanecen en la pantalla mientras los usuarios interactúan con el sitio web y pueden actualizarse automáticamente después de un cierto período de tiempo.

La integración de un banner se realiza con un proceso muy sencillo, insertando el siguiente elemento `<div>` en el lugar donde se quiera mostrar los anuncios:

```html
<div id='wortise:BANNER_ID' style='min-width: WIDTHpx; min-height: HEIGHTpx;'></div>
```

Es **totalmente necesario** especificar el ID del ad unit de banner que se vaya a utilizar, además de las dimensiones que deben ocupar los anuncios.


# Homepage

Welcome to Wortise official documentation.

Here you will find the instructions to integrate our SDK for all the current supported platforms:

| Platform         | Link                                      |
| ---------------- | ----------------------------------------- |
| **Android**      | [Guide](/en/android-sdk/sdk-integration)  |
| **Unity**        | [Guide](/en/unity-sdk/sdk-integration)    |
| **Flutter**      | [Guide](/en/flutter-sdk/sdk-integration)  |
| **React Native** | [Guide](/en/react-native/sdk-integration) |
| **Web**          | [Guide](/en/web-sdk/sdk-integration)      |


# Test Ad Units

To quickly and easily check if the SDK integration works correctly, we offer the following test ad units that always deliver an ad:

| Format           | Ad Unit ID          |
| ---------------- | ------------------- |
| **App Open**     | `test-app-open`     |
| **Banner**       | `test-banner`       |
| **Interstitial** | `test-interstitial` |
| **Rewarded**     | `test-rewarded`     |
| **Native**       | `test-native`       |

In case of not working, contact us so we can review the integration problems and/or check if there could be a problem with any of these ad units.


# Google Data Safety

If you have an app published on Google Play, you must be transparent with the users about how you handle data. This means disclosing your app's access, collection, and use of the data, and limiting that use to the purposes disclosed.

To comply with Google Play policies, it is needed to complete a form that can be found in the "[Data safety](https://play.google.com/console/app/app-content/summary)" section, inside the "[App content](https://play.google.com/console/app/app-content/summary)" page (Policies > App content).

The information disclosed in that form will be shown on the app store listing to help users to understand how their data is handled.

Below are the answers that must be provided regarding the Wortise SDK. Remember to include any additional information in relation to the use of the data by the app itself or other partners.

## Data Collection and security questions

| Question / Field                                                      | Response |
| --------------------------------------------------------------------- | -------- |
| Does your app collect or share any of the required user data types?   | ✅        |
| Is all of the user data collected by your app encrypted in transit?   | ✅        |
| Do you provide a way for users to request that their data is deleted? | ✅        |

## Data types

Select all of the user data types collected or shared by your app.

| Category                 | Data type                                       | Collected?    |
| ------------------------ | ----------------------------------------------- | ------------- |
| Location                 | <p>Approximate Location<br>Precise Location</p> | <p>✅<br>✅</p> |
| Personal info            | n/a                                             | No            |
| Financial info           | n/a                                             | No            |
| Health and fitness       | n/a                                             | No            |
| Messages                 | n/a                                             | No            |
| Photos                   | n/a                                             | No            |
| Audio files              | n/a                                             | No            |
| Files and docs           | n/a                                             | No            |
| Calendar                 | n/a                                             | No            |
| Contacts                 | n/a                                             | No            |
| App activity             | n/a                                             | No            |
| Web browsing             | n/a                                             | No            |
| App info and performance | n/a                                             | No            |
| Device or other IDs      | Device or other IDs                             | ✅             |

## Data usage and handling

With respect to Wortise, the response for all questions would be the following:

| Question / Field                                                                | Response                                        |
| ------------------------------------------------------------------------------- | ----------------------------------------------- |
| Collected                                                                       | ✅                                               |
| Shared                                                                          | ✅                                               |
| Is this data processed ephemerally?                                             | No                                              |
| Is this data required for your app, or can users choose whether it's collected? | Users can choose whether this data is collected |

| Purpose                                    | Response |
| ------------------------------------------ | -------- |
| App functionality                          | No       |
| Analytics                                  | ✅        |
| Developer communications                   | No       |
| Advertising or marketing                   | ✅        |
| Fraud prevention, security, and compliance | ✅        |
| Personalization                            | No       |
| Account management                         | No       |


# SDK integration

## Setup project

Depending of the language used by the project for the Gradle scripts, you must follow the steps from the corresponding tab:

{% tabs %}
{% tab title="Groovy" %}
In first place, it is needed to add the following Maven repositories inside the `repositories` block of the `settings.gradle` file:

{% hint style="info" %}
In the projects which still use an old structure, the `repositories` block can be found on the  `build.gradle` file located at the app-level.
{% endhint %}

```groovy
repositories {
    maven { url 'https://maven.wortise.com/artifactory/public' }
    
    maven { url 'https://android-sdk.is.com/' }
    maven { url 'https://artifact.bytedance.com/repository/pangle' }
    maven { url 'https://cboost.jfrog.io/artifactory/chartboost-ads/' }
}
```

Once added, you can proceed to integrate the SDK. To do so, you have to add the following line inside the `dependencies` block of the `build.gradle` file located at the app-level:

```groovy
implementation 'com.wortise:android-sdk:1.7.2'
```

In case of not already have it, it is needed to activate the Java 8 compatibility in the project. This can be achieved by adding these extra lines inside the `android` block, also in the same `build.gradle` file:

```groovy
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
```

{% endtab %}

{% tab title="Kotlin" %}
In first place, it is needed to add the following Maven repositories inside the `repositories` block of the `settings.gradle.kts` file:

```kotlin
dependencyResolutionManagement {
    repositories {
        maven { url = uri("https://maven.wortise.com/artifactory/public") }
    
        maven { url = uri("https://android-sdk.is.com/") }
        maven { url = uri("https://artifact.bytedance.com/repository/pangle") }
        maven { url = uri("https://cboost.jfrog.io/artifactory/chartboost-ads/") }
    }
}
```

Once added, you can proceed to integrate the SDK. To do so, you have to add the following line inside the `dependencies` block of the `build.gradle.kts` file located at the app-level:

```groovy
implementation("com.wortise:android-sdk:1.7.2")
```

In case of not already have it, it is needed to activate the Java 8 compatibility in the project. This can be achieved by adding these extra lines inside the `android` block, also in the same `build.gradle.kts` file:

```groovy
compileOptions {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}
```

{% endtab %}
{% endtabs %}

## Setup Manifest

It is needed to add the following `<meta-data>` element in the `AndroidManifest.xml` file, inside the `<application>` block, with Google's application ID as value:

```xml
<manifest>
    ...
    <application>
        ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>
```

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

## Request consent

{% hint style="success" %}
It is **very recommended** to request the user consent to be able to show personalised ads. This will allow to display content of more interest and generate higher revenues.
{% endhint %}

You can consult the following section to implement this request and obtain the user consent: [User consent](/en/android-sdk/user-consent)

## Initialize SDK

Our recommendation is to initialize the SDK in the `Application` class of the app, but it can also be done in any main `Activity`.

To do so, it is necessary to integrate the following code in the `onCreate` method:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
WortiseSdk.initialize(this, "your app key")
```

{% endtab %}

{% tab title="Java" %}

```java
WortiseSdk.initialize(this, "your app key");
```

{% endtab %}
{% endtabs %}

### Initialization listener

There are two possible ways to know when the SDK finishes its initialization:

#### Passing a listener as the last parameter of the method `WortiseSdk.initialize`

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
WortiseSdk.initialize(this, "your app key") {
    // This listener will be invoked when the initialization finishes
}
```

{% endtab %}

{% tab title="Java" %}

```java
WortiseSdk.initialize(this, "your app key", () -> {
    // This listener will be invoked when the initialization finishes
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}

#### Using the method `WortiseSdk.wait`

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
WortiseSdk.wait {
    // This listener will be invoked when the initialization finishes
}
```

{% endtab %}

{% tab title="Java" %}

```java
WortiseSdk.wait(() -> {
    // This listener will be invoked when the initialization finishes
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}

## Test mode

To verify the integration, the SDK provides a test mode that allows the app to always receive ads.

Beside the option that is available in our dashboard, you can programmatically enable this test mode, from the SDK itself, by using the following code:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
AdSettings.testEnabled = true
```

{% endtab %}

{% tab title="Java" %}

```java
AdSettings.setTestEnabled(true);
```

{% endtab %}
{% endtabs %}


# App Open

The app open ads are a special format which main purpose is to allow the monetization of the app load screens.

These ads can be closed anytime and are meant to be shown when the app moves to foreground.

## **Integration**

This ad format can be only integrated through code, by implementing any of the two possible ways of integration that are described below.

### **Manual**

In this kind of integration, it is needed to create an instance of the `AppOpenAd` class and use the `loadAd()` and `showAd()` methods to make the ad load and show on demand. The publisher is the responsible of deciding when the ad must be shown and implement the required logic.

Below you can find a simple integration example:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var appOpenAd: AppOpenAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        appOpenAd = AppOpenAd(this, "Wortise Ad Unit ID").also {
	    it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        appOpenAd?.destroy()
    }
    
    fun showAppOpen() {
        if (appOpenAd?.isAvailable == true) {
            appOpenAd?.showAd(this)
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private AppOpenAd mAppOpenAd;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mAppOpenAd = new AppOpenAd(this, "Wortise Ad Unit ID");
        mAppOpenAd.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mAppOpenAd.destroy();
    }
    
    public void showAppOpen() {
        if (mAppOpenAd.isAvailable()) {
            mAppOpenAd.showAd(this);
        }
    }
}
```

{% endtab %}
{% endtabs %}

Also, the `AppOpenAd` class offers the following additional methods to configure its behaviour:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// Sets if a new ad must be loaded after closing the previous one
appOpenAd.autoReload = true

// Shows an ad immediately if available. Otherwise, requests the load of a
// new ad
appOpenAd.tryToShowAd(activity)
```

{% endtab %}

{% tab title="Java" %}

```java
// Sets if a new ad must be loaded after closing the previous one
mAppOpenAd.setAutoReload(true);

// Shows an ad immediately if available. Otherwise, requests the load of a
// new ad
mAppOpenAd.tryToShowAd(activity);
```

{% endtab %}
{% endtabs %}

### **Via Manager**

The SDK provides a standard implementation of App Open to facilitate the integration of this ad format.

To perform this kind of integration, it is needed that the app extends the `Application` class and, inside it, creates an instance of `AppOpenManager`, just as shown in the example below:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MyApplication : Application() {

    private val appOpenManager by lazy {
        AppOpenManager(this, "Wortise Ad Unit ID")
    }

    override fun onCreate() {
        ...
        appOpenManager.loadAd()
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MyApplication extends Application {

    private AppOpenManager mAppOpenManager;

    @Override
    public void onCreate() {
        ...
        mAppOpenManager = new AppOpenManager(this, "Wortise Ad Unit ID");
        mAppOpenManager.loadAd();
    }
}
```

{% endtab %}
{% endtabs %}

With this simple integration, the app will show ads every time there is a transition from background to foreground.

Also, the `AppOpenManager` class offers the same methods as `AppOpenAd` to configure its behavior and show ads on demand.

## L**istener configuration**

Like occurs with other formats, a listener can be set to receive the events that happen during the ad lifecycle. For this, it is needed to implement the `AppOpenAd.Listener` interface just as shown in the example below:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
appOpenAd.listener = object : AppOpenAd.Listener() {

    override fun onAppOpenClicked(ad: AppOpenAd) {
        // Invoked when the ad has been clicked
    }
    
    override fun onAppOpenDismissed(ad: AppOpenAd) {
        // Invoked when the ad has been dismissed
    }
    
    override fun onAppOpenFailedToLoad(ad: AppOpenAd, error: AdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }
    
    override fun onAppOpenFailedToShow(ad: AppOpenAd, error: AdError) {
        // Invoked when the ad could not be shown
    }
    
    override fun onAppOpenImpression(ad: AppOpenAd) {
        // Invoked when the ad has generated an impression
    }
    
    override fun onAppOpenLoaded(ad: AppOpenAd) {
        // Invoked when the ad has been loaded
    }
    
    override fun onAppOpenRevenuePaid(ad: AppOpenAd,
                                      data: RevenueData) {
        // Invoked when the ad has generated revenue
    }
    
    override fun onAppOpenShown(ad: AppOpenAd) {
        // Invoked when the ad has been shown
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mAppOpenAd.setListener(new AppOpenAd.Listener() {
    @Override
    public void onAppOpenClicked(@NonNull AppOpenAd ad) {
        // Invoked when the ad has been clicked
    }
    
    @Override
    public void onAppOpenDismissed(@NonNull AppOpenAd ad) {
        // Invoked when the ad has been dismissed
    }
    
    @Override
    public void onAppOpenFailedToLoad(@NonNull AppOpenAd ad,
                                      @NonNull AdError error) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    @Override
    public void onAppOpenFailedToShow(@NonNull AppOpenAd ad,
                                      @NonNull AdError error) {
        // Invoked when the ad could not be shown
    }
    
    @Override
    public void onAppOpenImpression(@NonNull AppOpenAd ad) {
        // Invoked when the ad has generated an impression
    }

    @Override
    public void onAppOpenLoaded(@NonNull AppOpenAd ad) {
        // Invoked when the ad has been loaded
    }
    
    @Override
    public void onAppOpenRevenuePaid(@NonNull AppOpenAd ad,
                                     @NonNull RevenueData data) {
        // Invoked when the ad has generated revenue
    }
    
    @Override
    public void onAppOpenShown(@NonNull AppOpenAd ad) {
        // Invoked when the ad has been shown
    }
});
```

{% endtab %}
{% endtabs %}


# Banner

Banner ads are rectangular image or text ads that occupy a space inside the application layout. They stay on screen while the users interact with the app and can automatically refresh after a certain period of time. If you are new in mobile advertising, they are an excellent choice to start.

## **Integration**

There are two ways to integrate a banner: using code or adding the banner view inside a layout. Below we show some examples for both methods:

### Layout XML

```markup
<com.wortise.ads.banner.BannerAd
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:adSize="HEIGHT_50"
    app:adUnitId="Wortise Ad Unit ID" />
```

The widget has support for the following parameters:

| Parameter               | Type    | Required | Description                                                                                                     |
| ----------------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| **app:adUnitId**        | String  | **Yes**  | The ad unit ID to assign to the banner                                                                          |
| **app:adSize**          | AdSize  | No       | Maximum size (height) for the banner. The possible values for this parameter are declared in the `AdSize` class |
| **app:autoRefreshTime** | Integer | No       | Value in seconds that represents the time that must elapse to load a new banner ad                              |

### **Code**

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var bannerAd: BannerAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        bannerAd = BannerAd(this).also {
	        it.adSize = AdSize.HEIGHT_50
	        it.adUnitId = "<Ad Unit ID de Wortise>"
	        
	        // For example, we add the BannerAd into a FrameLayout
	        val frameLayout = findViewById<FrameLayout>(R.id.frame)
	        frameLayout.addView(it)
	        
	        it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        bannerAd?.destroy()
    }
    
    override fun onPause() {
        ...
        bannerAd?.pause()
    }
    
    override fun onResume() {
        ...
        bannerAd?.resume()
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private BannerAd mBannerAd;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mBannerAd = new BannerAd(this);
        mBannerAd.setAdSize(AdSize.HEIGHT_50);
        mBannerAd.setAdUnitId("Wortise Ad Unit ID");
        
        // For example, we add the BannerAd into a FrameLayout
        FrameLayout frameLayout = findViewById(R.id.frame);
        frameLayout.addView(mAdView);

        mBannerAd.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mBannerAd.destroy();
    }
    
    @Override
    public void onPause() {
        ...
        mBannerAd.pause();
    }
    
    @Override
    public void onResume() {
        ...
        mBannerAd.resume();
    }
}
```

{% endtab %}
{% endtabs %}

The `BannerAd` class providers the following methods to configure the instance:

| Method                               | Required | Descripción                                                                                                     |
| ------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------- |
| `setAdUnitId(String)`                | **Yes**  | Assigns an ad unit to the banner                                                                                |
| `setAdSize(AdSize)`                  | No       | Maximum size (height) for the banner. The possible values for this parameter are declared in the `AdSize` class |
| `setAutoRefreshTime(long)`           | No       | Value in milliseconds that represents the time that must elapse to load a new banner ad                         |
| `setAutoRefreshTime(long, TimeUnit)` | No       | Same as previous method, but allows to specify the time unit of the passed value                                |

## **Adaptive banners**

Adaptive banners are a new banner format where the size of the ads is adapted according to the device and the app user-interface, in order to maximize performance.

Currently there is support for two kind of adaptive banners:

### Anchored

This kind of banner is designed to replace the traditional 320x50 banners and be positioned at the top or bottom of the screen.

To make use of this format, the following code must be used to configure an adaptive size:&#x20;

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// It is needed to specify the banner width
val adSize = AdSize.getAnchoredAdaptiveBannerAdSize(context, width)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
// It is needed to specify the banner width
AdSize adSize = AdSize.getAnchoredAdaptiveBannerAdSize(context, width);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

Alternatively, this other option can be implemented to let the SDK calculate the banner width, where the `BannerAd` instance itself or the `View` that will contain it should be passed:

{% hint style="warning" %}
In this option, it is **highly recommended** that the `View` passed to the method is already added to the app’s layout, so that the SDK can correctly calculate all the dimensions.
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val adSize = AdSize.getAnchoredAdaptiveBannerAdSize(view)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
AdSize adSize = AdSize.getAnchoredAdaptiveBannerAdSize(view);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

### Inline

This other kind of banner, in comparison to the anchored, is designed to have a variable height and be positioned inside a scrolling content.

In this case, the following code must be used to configure a proper adaptive size:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val maxHeight = 200

// It is needed to specify the banner width. The maximum height is an
// optional parameter
val adSize = AdSize.getInlineAdaptiveBannerAdSize(context, width, maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
int maxHeight = 200;

// It is needed to specify the banner width. The maximum height is an
// optional parameter
AdSize adSize = AdSize.getInlineAdaptiveBannerAdSize(
    context, width, maxHeight
);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

Alternatively, this other option can be implemented to let the SDK calculate the banner width, where the `BannerAd` instance itself or the `View` that will contain it should be passed:

{% hint style="warning" %}
In this option, it is **highly recommended** that the `View` passed to the method is already added to the app’s layout, so that the SDK can correctly calculate all the dimensions.
{% endhint %}

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val maxHeight = 200

val adSize = AdSize.getInlineAdaptiveBannerAdSize(view, maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}

{% tab title="Java" %}

```java
int maxHeight = 200;

AdSize adSize = AdSize.getInlineAdaptiveBannerAdSize(view, maxHeight);
mBannerAd.setAdSize(adSize);
```

{% endtab %}
{% endtabs %}

## **Listener setup**

A listener can be set to any `BannerAd` instance to receive the events that happen during its lifecycle. For this, it is needed to implement the `BannerAd.Listener` interface as shown in the example below:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
bannerAd.listener = object : BannerAd.Listener() {

    override fun onBannerClicked(ad: BannerAd) {
        // Invoked when the ad has been clicked
    }

    override fun onBannerFailedToLoad(ad: BannerAd, error: AdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }
    
    override fun onBannerImpression(ad: BannerAd) {
        // Invoked when the ad has generated an impression
    }

    override fun onBannerLoaded(ad: BannerAd) {
        // Invoked when the ad has been loaded
    }
    
    override fun onBannerRevenuePaid(ad: BannerAd,
                                     data: RevenueData) {
        // Invoked when the ad has generated revenue
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mBannerAd.setListener(new BannerAd.Listener() {
    @Override
    public void onBannerClicked(@NonNull BannerAd ad) {
        // Invoked when the ad has been clicked
    }
    
    @Override
    public void onBannerFailedToLoad(@NonNull BannerAd ad,
                                     @NonNull AdError error) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }
    
    @Override
    public void onBannerImpression(@NonNull BannerAd ad) {
        // Invoked when the ad has generated an impression
    }

    @Override
    public void onBannerLoaded(@NonNull BannerAd ad) {
        // Invoked when the ad has been loaded
    }
    
    @Override
    public void onBannerRevenuePaid(@NonNull BannerAd ad,
                                     @NonNull RevenueData data) {
        // Invoked when the ad has generated revenue
    }
});
```

{% endtab %}
{% endtabs %}


# Interstitial

## Integration

Unlike banners, interstitials can only be integrated with code. Below we show a simple example to understand how it works:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var interstitialAd: InterstitialAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        interstitialAd = InterstitialAd(this, "<Wortise Ad Unit ID>").also {
	          it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        interstitialAd?.destroy()
    }
    
    fun showInterstitial() {
        if (interstitialAd?.isAvailable == true) {
            interstitialAd?.showAd(this)
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private InterstitialAd mInterstitial;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mInterstitial = new InterstitialAd(this, "Wortise Ad Unit ID");
        mInterstitial.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mInterstitial.destroy();
    }
    
    public void showInterstitial() {
        if (mInterstitial.isAvailable()) {
            mInterstitial.showAd(this);
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Listener configuration**

Like occurs with banners, a listener can be set to receive the events that happen during the interstitial lifecycle. For this, it is needed to implement the `InterstitialAd.Listener` interface just as shown in the example below:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
interstitialAd.listener = object : InterstitialAd.Listener() {

    override fun onInterstitialClicked(ad: InterstitialAd) {
        // Invoked when the ad has been clicked
    }
    
    override fun onInterstitialDismissed(ad: InterstitialAd) {
        // Invoked when the ad has been dismissed
    }
    
    override fun onInterstitialFailedToLoad(ad: InterstitialAd,
                                            error: AdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    override fun onInterstitialFailedToShow(ad: InterstitialAd,
                                            error: AdError) {
        // Invoked when the ad could not be shown
    }
    
    override fun onInterstitialImpression(ad: InterstitialAd) {
        // Invoked when the ad has generated an impression
    }
    
    override fun onInterstitialLoaded(ad: InterstitialAd) {
        // Invoked when the ad has been loaded
    }
    
    override fun onInterstitialRevenuePaid(ad: InterstitialAd,
                                           data: RevenueData) {
        // Invoked when the ad has generated revenue
    }
    
    override fun onInterstitialShown(ad: InterstitialAd) {
        // Invoked when the ad has been shown
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mInterstitial.setListener(new InterstitialAd.Listener() {
    @Override
    public void onInterstitialClicked(@NonNull InterstitialAd ad) {
        // Invoked when the ad has been clicked
    }
    
    @Override
    public void onInterstitialDismissed(@NonNull InterstitialAd ad) {
        // Invoked when the ad has been dismissed
    }
    
    @Override
    public void onInterstitialFailedToLoad(@NonNull InterstitialAd ad,
                                           @NonNull AdError error) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    @Override
    public void onInterstitialFailedToShow(@NonNull InterstitialAd ad,
                                           @NonNull AdError error) {
        // Invoked when the ad could not be shown
    }
    
    @Override
    public void onInterstitialImpression(@NonNull InterstitialAd ad) {
        // Invoked when the ad has generated an impression
    }
    
    @Override
    public void onInterstitialLoaded(@NonNull InterstitialAd ad) {
        // Invoked when the ad has been loaded
    }
    
    @Override
    public void onInterstitialRevenuePaid(@NonNull InterstitialAd ad,
                                          @NonNull RevenueData data) {
        // Invoked when the ad has generated revenue
    }
    
    @Override
    public void onInterstitialShown(@NonNull InterstitialAd ad) {
        // Invoked when the ad has been shown
    }
});
```

{% endtab %}
{% endtabs %}


# Rewarded

## Integration

Just as interstitials, rewarded ads can only be integrated with code. Below we show a simple example to understand how it works:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var interstitialAd: InterstitialAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        interstitialAd = InterstitialAd(this, "<Wortise Ad Unit ID>").also {
	        it.loadAd()
        }
    }
    
    override fun onDestroy() {
        ...
        interstitialAd?.destroy()
    }
    
    fun showInterstitial() {
        if (interstitialAd?.isAvailable == true) {
            interstitialAd?.showAd(this)
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private RewardedAd mRewarded;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mRewarded = new RewardedAd(this, "Wortise Ad Unit ID");
        mRewarded.loadAd();
    }
    
    @Override
    public void onDestroy() {
        ...
        mRewarded.destroy();
    }
    
    public void showInterstitial() {
        if (mRewarded.isAvailable()) {
            mRewarded.showAd(this);
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Listener configuration**

Like occurs with other formats, a listener can be set to receive the events that happen during the rewarded lifecycle. For this, it is needed to implement the `RewardedAd.Listener` interface just as shown in the example below:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
rewardedAd.listener = object : RewardedAd.Listener() {

    override fun onRewardedClicked(ad: RewardedAd) {
        // Invoked when the ad has been clicked
    }

    override fun onRewardedCompleted(ad: RewardedAd, reward: Reward) {
        // Invoked when the ad has been completed
    }
        
    override fun onRewardedDismissed(ad: RewardedAd) {
        // Invoked when the ad has been dismissed
    }
    
    override fun onRewardedFailedToLoad(ad: RewardedAd, error: AdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    override fun onRewardedFailedToShow(ad: RewardedAd, error: AdError) {
        // Invoked when the ad could not be shown
    }
    
    override fun onRewardedImpression(ad: RewardedAd) {
        // Invoked when the ad has generated an impression
    }    
    
    override fun onRewardedLoaded(ad: RewardedAd) {
        // Invoked when the ad has been loaded
    }
    
    override fun onRewardedRevenuePaid(ad: RewardedAd,
                                       data: RevenueData) {
        // Invoked when the ad has generated revenue
    }
    
    override fun onRewardedShown(ad: RewardedAd) {
        // Invoked when the ad has been shown
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
mRewarded.setListener(new RewardedAd.Listener() {
    @Override
    public void onRewardedClicked(@NonNull RewardedAd ad) {
        // Invoked when the ad has been clicked
    }
    
    @Override
    public void onRewardedCompleted(@NonNull RewardedAd ad,
                                    @NonNull Reward reward) {
        // Invoked when the ad has been completed
    }
    
    @Override
    public void onRewardedDismissed(@NonNull RewardedAd ad) {
        // Invoked when the ad has been dismissed
    }
    
    @Override
    public void onRewardedFailedToLoad(@NonNull RewardedAd ad,
                                       @NonNull AdError error) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    @Override
    public void onRewardedFailedToShow(@NonNull RewardedAd ad,
                                       @NonNull AdError error) {
        // Invoked when the ad could not be shown
    }
    
    @Override
    public void onRewardedImpression(@NonNull RewardedAd ad) {
        // Invoked when the ad has generated an impression
    }
    
    @Override
    public void onRewardedLoaded(@NonNull RewardedAd ad) {
        // Invoked when the ad has been loaded
    }
    
    @Override
    public void onRewardedRevenuePaid(@NonNull RewardedAd ad,
                                      @NonNull RevenueData data) {
        // Invoked when the ad has generated revenue
    }
    
    @Override
    public void onRewardedShown(@NonNull RewardedAd ad) {
        // Invoked when the ad has been shown
    }
});
```

{% endtab %}
{% endtabs %}


# Native (Google)

The native ads are a kind of ad that can be shown using the same visual style like the rest of the app, which allows a natural and non-intrusive integration with the user interface.

Currently, Wortise provides the possibility of use the native ads from Google's ad platform ("*Native Advanced*"), in a simple and direct way.

## Integration

To request a native ad, it is needed to make an integration by code just as shown in the example below:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
class MainActivity : Activity() {

    private var googleNativeAd: GoogleNativeAd? = null
    
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        googleNativeAd = GoogleNativeAd(
                         this, "Wortise Ad Unit ID", nativeListener).also {
            it.load()
        }
    }
    
    override fun onDestroy() {
        ...
        googleNativeAd?.destroy();
    }
    
    private val nativeListener = object : GoogleNativeAd.Listener() {
            
        override fun onNativeClicked(ad: GoogleNativeAd) {
            // Invoked when the ad has been clicked
        }
        
        override fun onNativeFailedToLoad(ad: GoogleNativeAd, error: AdError) {
            // Invoked when the ad could not be loaded
            // (because of an error or no fill)
        }
        
        override fun onNativeImpression(ad: GoogleNativeAd) {
            // Invoked when the ad has generated an impression
        }
        
        override fun onNativeLoaded(ad: GoogleNativeAd, nativeAd: NativeAd) {
            // Invoked when the ad has been loaded
        }
        
        override fun onNativeRevenuePaid(ad: GoogleNativeAd,
                                         data: RevenueData) {
            // Invoked when the ad has generated revenue
        }
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
public class MainActivity extends Activity {

    private GoogleNativeAd mGoogleNativeAd;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        mGoogleNativeAd = new GoogleNativeAd(
                this, "Wortise Ad Unit ID", mNativeListener);
        mGoogleNativeAd.load();
    }
    
    @Override
    public void onDestroy() {
        ...
        mGoogleNativeAd.destroy();
    }
    
    private GoogleNativeAd.Listener mNativeListener 
            = new GoogleNativeAd.Listener() {
            
        @Override
        public void onNativeClicked(@NonNull GoogleNativeAd ad) {
            // Invoked when ad has been clicked
        }
        
        @Override
        public void onNativeFailedToLoad(@NonNull GoogleNativeAd ad,
                                         @NonNull AdError error) {
            // Invoked when the ad could not be loaded
            // (because of an error or no fill)
        }
        
        @Override
        public void onNativeImpression(@NonNull GoogleNativeAd ad) {
            // Invoked when the ad has generated an impression
        }
        
        @Override
        public void onNativeLoaded(@NonNull GoogleNativeAd ad,
                                   @NonNull NativeAd nativeAd) {
            // Invoked when the ad has been loaded
        }
        
        @Override
        public void onNativeRevenuePaid(@NonNull GoogleNativeAd ad,
                                        @NonNull RevenueData data) {
            // Invoked when the ad has generated revenue
        }
    }
}
```

{% endtab %}
{% endtabs %}

Once the native ad has been successfully loaded, obtaining as result a `NativeAd` instance, it is needed to complete the integration by following Google's documentation on this matter: <https://developers.google.com/ad-manager/mobile-ads-sdk/android/native/advanced?hl=en#display_a_nativead>

### Specify options

The `GoogleNativeAd` class includes a method called `withNativeAdOptions` which allows to specify custom options by using the `NativeAdOptions` class from Google. This method must be called before loading the ad.

Below you can check a brief usage example:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
var adOptions = NativeAdOptions.Builder()
    // Options are set here
    .build();

googleNativeAd.withNativeAdOptions(adOptions)
```

{% endtab %}

{% tab title="Java" %}

```java
NativeAdOptions adOptions = new NativeAdOptions.Builder()
    // Options are set here
    .build();

mGoogleNativeAd.withNativeAdOptions(adOptions);
```

{% endtab %}
{% endtabs %}


# Targeting

## Request permissions

{% hint style="info" %}
This step is **completely optional** and should only be implemented if it is convenient for the application’s purpose.
{% endhint %}

The app may request the location permissions so that our SDK can obtain the user's current location and display more relevant ads based on that information.

For this, it is necessary to add the following permissions in the `AndroidManifest.xml` file:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

Following this, the app must request the permissions so that users can grant them.

### Example

{% tabs %}
{% tab title="Kotlin" %}

```java
private val PERMISSIONS = arrayOf(
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
)

ActivityCompat.requestPermissions(this, PERMISSIONS, 100)
```

{% endtab %}

{% tab title="Java" %}

```java
private static final String[] PERMISSIONS = {
    Manifest.permission.ACCESS_FINE_LOCATION,
    Manifest.permission.ACCESS_COARSE_LOCATION
};

ActivityCompat.requestPermissions(this, PERMISSIONS, 100);
```

{% endtab %}
{% endtabs %}


# Revenue reporting

## Implementation

Since version **1.7.0**, apps can receive an estimated revenue that has likely been generated by an ad.

To do this, it is just needed to implement the corresponding listener for each ad format, as shown in the example below:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
val bannerAd: BannerAd

bannerAd.listener = object : BannerAd.Listener() {
    override fun onBannerRevenuePaid(ad: BannerAd, data: Revenuedata) {
        // Invoked when the ad has generated revenue
    }
}
```

{% endtab %}

{% tab title="Java" %}

```java
BannerAd mBannerAd;

mBannerAd.setListener(new BannerAd.Listener() {
    @Override
    public void onBannerRevenuePaid(@NonNull BannerAd ad,
                                    @NonNull Revenuedata data) {
        // Invoked when the ad has generated revenue
    }
});
```

{% endtab %}
{% endtabs %}

The listener receives an object of type `RevenueData` that contains the following fields:

<table><thead><tr><th width="139.62109375">Field</th><th width="140.36328125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>AdValue</code></td><td>The revenue generated by the ad</td></tr><tr><td><code>source</code></td><td><code>String</code></td><td>The revenue source</td></tr></tbody></table>

In addition, the `AdValue` class contains the following fields that represent the revenue:

<table><thead><tr><th width="140.49609375">Field</th><th width="190.46484375">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>String</code></td><td>The currency corresponding to the revenue</td></tr><tr><td><code>precision</code></td><td><code>AdValue.Precision</code></td><td>The accuracy of the information. It can be <code>ESTIMATED</code>, <code>PRECISE</code> or <code>PUBLISHER_DEFINED</code></td></tr><tr><td><code>value</code></td><td><code>Double</code></td><td>The revenue value</td></tr></tbody></table>

## Integration with Firebase

Below, a basic example is shown of how to report the revenue information to Firebase:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
override func onBannerRevenuePaid(ad: BannerAd, data: RevenueData) {
    val bundle = Bundle().apply {
        putString("currency",   data.revenue.currency)
        putString("precision",  data.revenue.precision?.name)
        putString("source",     data.source)
        putDouble("value",      data.revenue.value)
    }

    Firebase.analytics.logEvent("ad_revenue", bundle)
}
```

{% endtab %}

{% tab title="Java" %}

```java
@Override
public void onBannerRevenuePaid(@NonNull BannerAd ad,
                                @NonNull RevenueData data) {
    Bundle bundle = new Bundle();

    bundle.putString("source", data.getSource());
    
    AdValue revenue = data.getRevenue();

    bundle.putString("currency",  revenue.getCurrency());
    bundle.putDouble("value",     revenue.getValue());
    
    AdValue.Precision precision = revenue.getPrecision();
    
    if (precision != null) {
        bundle.putString("precision", precision.name());
    }

    FirebaseAnalytics.getInstance(context).logEvent("ad_revenue", bundle);
}
```

{% endtab %}
{% endtabs %}


# User consent

The Wortise SDK includes support for Google Ads **Consent Manager** (**CMP**) to request the consent of every user.

Obtaining the user consent is important to comply with the privacy policies and qualify for higher CPMs.

## Request consent

To request the user consent, it is needed to invoke the method `ConsentManager.requestIfRequired` at an appropriate moment of the app. This will show a dialog, only when it is required (normally during the first app launch), so the user can grant or deny consent.

There is also the `ConsentManager.request` method to always show the dialog, and not only when required (for example, to provide an option in the app settings to allow the user change the consent at anytime).

### Example

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// Example with WortiseSdk.initialize
WortiseSdk.initialize(this, "your app key") {
    ConsentManager.requestIfRequired(this);
}

// Example with WortiseSdk.wait
WortiseSdk.wait {
    ConsentManager.requestIfRequired(this);
}
```

{% endtab %}

{% tab title="Java" %}

```java
// Example with WortiseSdk.initialize
WortiseSdk.initialize(this, "tu app key", () -> {
    ConsentManager.requestIfRequired(this);
    return Unit.INSTANCE;
});

// Example with WortiseSdk.wait
WortiseSdk.wait(() -> {
    ConsentManager.requestIfRequired(this);
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}

### Listener configuration

It is possible to pass a listener, to both `request` and `requestIfRequired`, to know when the consent requested has finished (and if it has been shown). To achieve this, just pass a listener as the last parameter of both methods.

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
ConsentManager.requestOnce(this, (shown) -> {
    // This listener will be invoked when the request finishes 
}
```

{% endtab %}

{% tab title="Java" %}

```java
ConsentManager.requestOnce(this, (shown) -> {
    // This listener will be invoked when the request finishes 
    return Unit.INSTANCE;
});
```

{% endtab %}
{% endtabs %}


# Privacy

## Families Policy

If you application is targeting minors (exclusively or not), it is needed to comply with the requirements established by Google Play's [Families Policy](https://support.google.com/googleplay/android-developer/answer/9900633).

To facilitate the compliance of these policies, the SDK allows to specify if the ad requests are targeted to minors, beside the ability to set the maximum content rating.

It is very important to comply with these requirements, and carefully review the related policies, to avoid any issues with Google Play.

### Child directed content

To specify if an user is a minor or not, it is needed to include the following code **before** initializing the SDK:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
// true  -> The user is a minor or the age is unknown
// false -> The user is an adult
AdSettings.setChildDirected(context, true)
```

{% endtab %}

{% tab title="Java" %}

```java
// true  -> The user is a minor or the age is unknown
// false -> The user is an adult
AdSettings.setChildDirected(context, true);
```

{% endtab %}
{% endtabs %}

If the user age is unknown, the app must treat that user as if they were a minor.

### Content rating

To specify the maximum content rating, the following code must be added before initializing the SDK:

{% tabs %}
{% tab title="Kotlin" %}

```kotlin
AdSettings.setMaxAdContentRating(context, AdContentRating.G)
```

{% endtab %}

{% tab title="Java" %}

```java
AdSettings.setMaxAdContentRating(context, AdContentRating.G);
```

{% endtab %}
{% endtabs %}

The following values are available when specifying the content rating:

| Value                | Description                                                |
| -------------------- | ---------------------------------------------------------- |
| `AdContentRating.G`  | Content suitable for minors                                |
| `AdContentRating.PG` | Content suitable for most audiences with parental guidance |
| `AdContentRating.T`  | Content suitable for teens                                 |
| `AdContentRating.MA` | Content suitable only for adults                           |

{% hint style="info" %}
If the app is directed primarily to children, it is completely needed to specify the `G` rating,

Otherwise, if the app audience is mixed, a `G` or `PG` rating must be set.
{% endhint %}

### Additional requirements

If you app is directed to children, exclusively or not, it is needed to remove the Facebook adapter that is included in our SDK due to not being certified by Google Play yet for its use with children.

To do this, it is needed to modify the SDK integration in the `build.gradle` file to specify the exclusion of the adapter, just as shown below:

```groovy
implementation('com.wortise:android-sdk:x.y.z') {
    exclude group: 'com.google.ads.mediation', module: 'facebook'
}
```


# ProGuard

No action is necessary for this as Wortise's SDK already includes the ProGuard rules needed for its correct functioning.


# SDK integration

## Requirements

* Xcode: **15.0** or higher
* Target deployment: **iOS 12.0** or higher

## Setup project

To start with the integration of our SDK, it is needed to add the following dependency into the `Podfile` file of the project, just as shown below:

```ruby
source 'https://cdn.cocoapods.org/'
platform :ios, '12.0'

...

target 'MyTarget' do
    use frameworks!
    ...
    pod 'WortiseSDK' '>= 1.7.3'
end
```

{% hint style="info" %}
Currently, the Wortise SDK is only distributed through Cocoapods. In the future, there will be support for its integration with Swift Package Manager (SPM).
{% endhint %}

## Setup Info.plist

It is needed to add the following parameter in the `Info.plist` file, with Google's application ID as value:

```xml
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxxxx</string>
```

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

Then, it would only be needed to add the following block, in the same file, to complete the correct integration with Google:

```xml
<key>SKAdNetworkItems</key>
<array>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cstr6suwn9.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4fzdc2evr5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4pfyvq9l8r.skadnetwork </string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2fnua5tdw4.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ydx93a7ass.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>5a6flpkh64.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>p78axxw29g.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v72qych5uu.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ludvb6z3bs.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cp8zw746q7.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>c6k4g5qg8m.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>s39g8k73mm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qy4746246.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3sh42y64q3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>f38h382jlk.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>hs6bdukanm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>prcb7njmu6.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v4nxqhlyqp.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>wzmmz9fp6w.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>yclnxrl5pm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>t38b2kh725.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>7ug5zh24hu.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>9rd848q2bz.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>y5ghdn5j9k.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n6fk4nfna4.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v9wttpbfk9.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n38lu8286q.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>47vhws6wlr.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>kbd757ywx3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>9t245vhmpl.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>a2p9lx4jpn.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>22mmun2rn5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4468km3ulz.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2u9pt9hc89.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8s468mfl3y.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>av6w8kgt66.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>klf5c3l5u5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ppxm28t8ap.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>424m5254lk.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ecpz2srf59.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>uw77j35x4d.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>mlmmfzh3r3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>578prtvx9j.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4dzt52r2t5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>gta9lk7p23.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>e5fvkxwrpn.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8c4e2ghe7u.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>zq492l623r.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3rd42ekr43.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qcr597p9d.skadnetwork</string>
    </dict>
</array>
```

## Request consent

{% hint style="success" %}
It is **very recommended** to request the user consent to be able to show personalised ads. This will allow to display content of more interest and generate higher revenues.
{% endhint %}

You can consult the following section to implement this request and obtain the user consent: [User consent](/en/ios-sdk/user-consent)

## Initialize SDK

Our recommendation is to initialize the SDK in the `AppDelegate` class of the app, but it can also be done in any main `ViewController`.

To do so, it is necessary to integrate the following code in the `application(didFinishLaunchingWithOptions:)` method:

{% tabs %}
{% tab title="Swift" %}

```swift
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    ...
    WortiseAds.shared.initialize(assetKey: "your app key")
}
```

{% endtab %}
{% endtabs %}

### Initialization delegate

There are two possible ways to know when the SDK finishes its initialization:

#### Passing a delegate as the last parameter of the method `WortiseAds.shared.initialize`

{% tabs %}
{% tab title="Swift" %}

```swift
WortiseAds.shared.initialize(assetKey: "your app key") {
    // This delegate will be invoked when the initialization finishes
}
```

{% endtab %}
{% endtabs %}

#### Using the method `WortiseAds.shared.wait`

{% tabs %}
{% tab title="Swift" %}

```swift
WortiseAds.shared.wait {
    // This delegate will be invoked when the initialization finishes
}
```

{% endtab %}
{% endtabs %}

## Test mode

To verify the integration, the SDK provides a test mode that allows the app to always receive ads.

Beside the option that is available in our dashboard, you can programmatically enable this test mode, from the SDK itself, by using the following code:

{% tabs %}
{% tab title="Swift" %}

```swift
WAAdSettings.testEnabled = true
```

{% endtab %}
{% endtabs %}


# App Open

The app open ads are a special format which main purpose is to allow the monetization of the app load screens.

These ads can be closed anytime and are meant to be shown when the app moves to foreground.

## **Integration**

This ad format can be only integrated through code, by implementing any of the two possible ways of integration that are described below.

### **Manual**

In this kind of integration, it is needed to create an instance of the `WAAppOpenAd` class and use the `loadAd()` and `showAd()` methods to make the ad load and show on demand. The publisher is the responsible of deciding when the ad must be shown and implement the required logic.

Below you can find a simple integration example:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {

    private var appOpenAd: WAAppOpenAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        appOpenAd = WAAppOpenAd(adUnitId: "test-app-open")
        appOpenAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        appOpenAd.destroy()
    }
    
    func showAppOpen() {
        if appOpenAd.isAvailable {
            appOpenAd.showAd(from: self)
        }
    }
}
```

{% endtab %}
{% endtabs %}

Also, the `WAAppOpenAd` class offers the following additional methods to configure its behaviour:

{% tabs %}
{% tab title="Swift" %}

```swift
// Sets if a new ad must be loaded after closing the previous one
appOpenAd.autoReload = true

// Shows an ad immediately if available. Otherwise, requests the load of a
// new ad
appOpenAd.tryToShowAd(from: self)
```

{% endtab %}
{% endtabs %}

### **Via Manager**

The SDK provides a standard implementation of App Open to facilitate the integration of this ad format.

To perform this kind of integration, it is needed to create an instance of `WAAppOpenManager` inside the `AppDelegate` class, just as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class AppDelegate: UIResponder, UIApplicationDelegate {

    private var appOpenManager: WAAppOpenManager!

    func application(_
        application: UIApplication, didFinishLaunchingWithOptions
        launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        ...
        appOpenManager = WAAppOpenManager(adUnitId: "test-app-open")
        appOpenManager.loadAd()
    }
}
```

{% endtab %}
{% endtabs %}

With this simple integration, the app will show ads every time there is a transition from background to foreground.

Also, the `WAAppOpenManager` class offers the same methods as `WAAppOpenAd` to configure its behavior and show ads on demand.

## Delegate **configuration**

Like occurs with other formats, a delegate can be set to receive the events that happen during the ad lifecycle. For this, it is needed to implement the `WAAppOpenDelegate` interface just as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
extension AppDelegate : WAAppOpenDelegate {
    
    func didClick(appOpenAd: WAAppOpenAd) {
        // Invoked when the ad has been clicked
    }

    func didDismiss(appOpenAd: WAAppOpenAd) {
        // Invoked when the ad has been dismissed
    }
    
    func didFailToLoad(appOpenAd: WAAppOpenAd, error: WAAdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    func didFailToShow(appOpenAd: WAAppOpenAd, error: WAAdError) {
        // Invoked when the ad could not be shown
    }

    func didImpress(appOpenAd: WAAppOpenAd) {
        // Invoked when the ad has generated an impression
    }

    func didLoad(appOpenAd: WAAppOpenAd) {
        // Invoked when the ad has been loaded
    }
    
    func didPayRevenue(appOpenAd: WAAppOpenAd, data: WARevenuedata) {
        // Invoked when the ad has generated revenue
    }
 
    func didShow(appOpenAd: WAAppOpenAd) {
        // Invoked when the ad has been shown
    }
}
```

Once the interface is implemented, the delegate is assigned to the ad instance:

```swift
appOpenAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Banner

Banner ads are rectangular image or text ads that occupy a space inside the application layout. They stay on screen while the users interact with the app and can automatically refresh after a certain period of time. If you are new in mobile advertising, they are an excellent choice to start.

## **Integration**

To integrate a banner, it is needed to add a `WABannerAd` class component to the app interface.

Then, an ad load should be requested just as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {
    @IBOutlet
    weak var bannerAd: WABannerAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        bannerAd.adUnitId = "Wortise Ad Unit ID"
        bannerAd.adSize = WAAdSize.height50
        bannerAd.rootViewController = self
        // Optional: value in seconds to auto-refresh the ad
        bannerAd.autoRefreshTime = 60.0
        bannerAd.loadAd()
    }
}
```

{% endtab %}
{% endtabs %}

## **Adaptive banners**

Adaptive banners are a new banner format where the size of the ads is adapted according to the device and the app user-interface, in order to maximize performance.

Currently there is support for two kind of adaptive banners:

### Anchored

This kind of banner is designed to replace the traditional 320x50 banners and be positioned at the top or bottom of the screen.

To make use of this format, the following code must be used to configure an adaptive size:&#x20;

{% tabs %}
{% tab title="Swift" %}

```swift
// It is needed to specify the banner width
let adSize = WAAdSize.getAnchoredAdaptiveBannerAdSize(width: width)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

Alternatively, this other option can be implemented to let the SDK calculate the banner width, where the `WABannerAd` instance itself or the `UIView` that will contain it should be passed:

{% hint style="warning" %}
In this option, it is **highly recommended** that the `UIView` passed to the method is already added to the app’s layout, so that the SDK can correctly calculate all the dimensions.
{% endhint %}

{% tabs %}
{% tab title="Swift" %}

```swift
let adSize = WAAdSize.getAnchoredAdaptiveBannerAdSize(container: view)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

### Inline

This other kind of banner, in comparison to the anchored, is designed to have a variable height and be positioned inside a scrolling content.

In this case, the following code must be used to configure a proper adaptive size:

{% tabs %}
{% tab title="Swift" %}

```swift
let maxHeight = 200

// It is needed to specify the banner width. The maximum height is an
// optional parameter
let adSize = WAAdSize.getInlineAdaptiveBannerAdSize(width: width,
                                                    maxHeight: maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

Alternatively, this other option can be implemented to let the SDK calculate the banner width, where the `WABannerAd` instance itself or the `UIView` that will contain it should be passed:

{% hint style="warning" %}
In this option, it is **highly recommended** that the `UIView` passed to the method is already added to the app’s layout, so that the SDK can correctly calculate all the dimensions.
{% endhint %}

{% tabs %}
{% tab title="Swift" %}

```swift
let maxHeight = 200

let adSize = AdSize.getInlineAdaptiveBannerAdSize(container: view,
                                                  maxHeight: maxHeight)
bannerAd.adSize = adSize
```

{% endtab %}
{% endtabs %}

## **Delegate setup**

A listener can be set to any `WABannerAd` instance to receive the events that happen during its lifecycle. For this, it is needed to implement the `WABannerDelegate` interface as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
extension ViewController : WABannerDelegate {
    
    func didClick(bannerAd: WABannerAd) {
        // Invoked when the ad has been clicked
    }
    
    func didFailToLoad(bannerAd: WABannerAd, error: WAAdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    func didImpress(bannerAd: WABannerAd) {
        // Invoked when the ad has generated an impression
    }

    func didLoad(bannerAd: WABannerAd) {
        // Invoked when the ad has been loaded
    }
    
    func didPayRevenue(bannerAd: WABannerAd, data: WARevenuedata) {
        // Invoked when the ad has generated revenue
    }
}
```

Once the interface is implemented, the delegate is assigned to the ad instance:

```swift
bannerAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Interstitial

## Integration

Unlike banners, interstitials can only be integrated with code. Below we show a simple example to understand how it works:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {

    private var interstitialAd: WAInterstitialAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        interstitialAd = WAInterstitialAd(adUnitId: "test-interstitial")
        interstitialAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        interstitialAd.destroy()
    }

    func showInterstitial() {
        if interstitialAd.isAvailable {
            interstitialAd.showAd(from: self)
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Delegate configuration**

Like occurs with banners, a listener can be set to receive the events that happen during the interstitial lifecycle. For this, it is needed to implement the `WAInterstitialDelegate` interface just as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
extension ViewController : WAInterstitialDelegate {
    
    func didClick(interstitialAd: WAInterstitialAd) {
        // Invoked when the ad has been clicked
    }

    func didDismiss(interstitialAd: WAInterstitialAd) {
        // Invoked when the ad has been dismissed
    }
    
    func didFailToLoad(interstitialAd: WAInterstitialAd, error: WAAdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    func didFailToShow(interstitialAdenAd: WAInterstitialAd, error: WAAdError) {
        // Invoked when the ad could not be shown
    }

    func didImpress(interstitialAd: WAInterstitialAd) {
        // Invoked when the ad has generated an impression
    }

    func didLoad(interstitialAd: WAInterstitialAd) {
        // Invoked when the ad has been loaded
    }
    
    func didPayRevenue(interstitialAd: WAInterstitialAd, data: WARevenuedata) {
        // Invoked when the ad has generated revenue
    }
 
    func didShow(interstitialAd: WAInterstitialAd) {
        // Invoked when the ad has been shown
    }
}
```

Once the interface is implemented, the delegate is assigned to the ad instance:

```swift
interstitialAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Rewarded

## Integration

Just as interstitials, rewarded ads can only be integrated with code. Below we show a simple example to understand how it works:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {

    private var rewardedAd: WARewardedAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        rewardedAd = WARewardedAd(adUnitId: "test-rewarded")
        rewardedAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        rewardedAd.destroy()
    }

    func showRewarded() {
        if rewardedAd.isAvailable {
            rewardedAd.showAd(from: self)
        }
    }
}
```

{% endtab %}
{% endtabs %}

## **Delegate configuration**

Like occurs with other formats, a listener can be set to receive the events that happen during the rewarded lifecycle. For this, it is needed to implement the `WARewardedDelegate` interface just as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
extension ViewController : WARewardedDelegate {
    
    func didClick(rewardedAd: WARewardedAd) {
        // Invoked when the ad has been clicked
    }

    func didComplete(rewardedAd: WARewardedAd, reward: WAReward) {
        // Invoked when the ad has been completed
    }

    func didDismiss(rewardedAd: WARewardedAd) {
        // Invoked when the ad has been dismissed
    }
    
    func didFailToLoad(rewardedAd: WARewardedAd, error: WAAdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    func didFailToShow(rewardedAd: WARewardedAd, error: WAAdError) {
        // Invoked when the ad could not be shown
    }

    func didImpress(rewardedAd: WARewardedAd) {
        // Invoked when the ad has generated an impression
    }

    func didLoad(rewardedAd: WARewardedAd) {
        // Invoked when the ad has been loaded
    }
    
    func didPayRevenue(rewardedAd: WARewardedAd, data: WARevenuedata) {
        // Invoked when the ad has generated revenue
    }
 
    func didShow(rewardedAd: WARewardedAd) {
        // Invoked when the ad has been shown
    }
}
```

Once the interface is implemented, the delegate is assigned to the ad instance:

```swift
rewardedAd.delegate = self
```

{% endtab %}
{% endtabs %}


# Native (Google)

The native ads are a kind of ad that can be shown using the same visual style like the rest of the app, which allows a natural and non-intrusive integration with the user interface.

Currently, Wortise provides the possibility of use the native ads from Google's ad platform ("*Native Advanced*"), in a simple and direct way.

## Integration

To request a native ad, it is needed to make an integration by code just as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
import UIKit
import WortiseSDK

class ViewController: UIViewController {
    private var nativeAd: WAGoogleNativeAd!

    override func viewDidLoad() {
        super.viewDidLoad()
        ...
        nativeAd = WAGoogleNativeAd(adUnitId: "test-native",
                                    rootViewController: self,
                                    delegate: self)
        nativeAd.loadAd()
    }

    override func willMove(toParent controller: UIViewController?) {
        super.willMove(toParent: controller)
        ...
        nativeAd.destroy()
    }
}

extension ViewController: WAGoogleNativeDelegate {

    func didClick(nativeAd: WAGoogleNativeAd) {
        // Invoked when the ad has been clicked
    }

    func didFailToLoad(nativeAd: WAGoogleNativeAd, error: WAAdError) {
        // Invoked when the ad could not be loaded
        // (because of an error or no fill)
    }

    func didLoad(nativeAd: WAGoogleNativeAd, googleNativeAd: GADNativeAd) {
        // Invoked when the ad has been loaded
    }
    
    func didPayRevenue(nativeAd: WAGoogleNativeAd, data: WARevenuedata) {
        // Invoked when the ad has generated revenue
    }

    func didRecord(impression: WAGoogleNativeAd) {
        // Invoked when the ad has generated an impression
    }
}
```

{% endtab %}
{% endtabs %}

Once the native ad has been successfully loaded, obtaining as result a `GADNativeAd` instance, it is needed to complete the integration by following Google's documentation on this matter: <https://developers.google.com/ad-manager/mobile-ads-sdk/ios/native/advanced?hl=en#display_a_nativead>

### Specify options

The `WAGoogleNativeAd` class includes an attribute called `options` which allows to specify custom options by using the `GADAdLoaderOptions` class from Google. This attribute must be set before loading the ad.

Below you can check a brief usage example:

{% tabs %}
{% tab title="Swift" %}

```swift
let adOptions = GADNativeAdViewAdOptions()

// Set the options through "adOptions"

googleNativeAd.options = adOptions
```

{% endtab %}
{% endtabs %}


# Revenue reporting

## Implementation

Since version **1.7.0**, apps can receive an estimated revenue that has likely been generated by an ad.

To do this, it is just needed to implement the corresponding delegate for each ad format, as shown in the example below:

{% tabs %}
{% tab title="Swift" %}

```swift
extension ViewController : WABannerDelegate {   
    func didPayRevenue(bannerAd: WABannerAd, data: WARevenueData) {
        // Invoked when the ad has generated revenue
    }
}
```

{% endtab %}
{% endtabs %}

The delegate receives an object of type `WARevenueData` that contains the following fields:

<table><thead><tr><th width="139.62109375">Field</th><th width="140.36328125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>WAAdValue</code></td><td>The revenue generated by the ad</td></tr><tr><td><code>source</code></td><td><code>String</code></td><td>The revenue source</td></tr></tbody></table>

In addition, the `WAAdValue` class contains the following fields that represent the revenue:

<table><thead><tr><th width="140.49609375">Field</th><th width="199.546875">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>String</code></td><td>The currency corresponding to the revenue</td></tr><tr><td><code>precision</code></td><td><code>WAAdValue.Precision</code></td><td>The accuracy of the information. It can be <code>estimated</code>, <code>precise</code> or <code>publisherDefined</code></td></tr><tr><td><code>value</code></td><td><code>Double</code></td><td>The revenue value</td></tr></tbody></table>

## Integration with Firebase

Below, a basic example is shown of how to report the revenue information to Firebase:

{% tabs %}
{% tab title="Swift" %}

```kotlin
import FirebaseAnalytics

func didPayRevenue(bannerAd: WABannerAd, data: WARevenueData) {
    let params = [
        "currency":  data.revenue.currency,
        "precision": data.precision?.name,
        "source":    data.source,
        "value":     data.revenue.value
    ]

    Analytics.logEvent("ad_revenue", parameters: params)
}
```

{% endtab %}
{% endtabs %}


# User consent

The Wortise SDK includes support for Google Ads **Consent Manager** (**CMP**) to request the consent of every user.

Obtaining the user consent is important to comply with the privacy policies and qualify for higher CPMs.

## Request consent

To request the user consent, it is needed to invoke the method `WAConsentManager.request(ifRequired:)` at an appropriate moment of the app. This will show a dialog, only when it is required (normally during the first app launch), so the user can grant or deny consent.

There is also the `WAConsentManager.request` method to always show the dialog, and not only when required (for example, to provide an option in the app settings to allow the user change the consent at anytime).

### Example

{% tabs %}
{% tab title="Swift" %}

```swift
// Example with WortiseAds.shared.initialize
WortiseAds.shared.initialize(assetKey: "your app key") {
    WAConsentManager.request(ifRequired: self)
}

// Example with WortiseAds.shared.wait
WortiseAds.shared.wait {
    WAConsentManager.request(ifRequired: self)
}
```

{% endtab %}
{% endtabs %}

### Delegate configuration

It is possible to pass a delegate, to both `request` and `request(ifRequired:)`, to know when the consent requested has finished (and if it has been shown). To achieve this, just pass a listener as the last parameter of both methods.

{% tabs %}
{% tab title="Swift" %}

```swift
WAConsentManager.request(ifRequired: self) {
    // This delegate will be invoked when the request finishes 
}
```

{% endtab %}
{% endtabs %}


# Privacy

## Privacy Policy

If you application is targeting minors (exclusively or not), it is needed to comply with the requirements established by Apple.

To facilitate the compliance of these policies, the SDK allows to specify if the ad requests are targeted to minors, beside the ability to set the maximum content rating.

It is very important to comply with these requirements, and carefully review the related policies, to avoid any issues with Apple.

### Child directed content

To specify if an user is a minor or not, it is needed to include the following code **before** initializing the SDK:

{% tabs %}
{% tab title="Swift" %}

```swift
// true  -> The user is a minor or the age is unknown
// false -> The user is an adult
WAAdSettings.childDirected = true
```

{% endtab %}
{% endtabs %}

If the user age is unknown, the app must treat that user as if they were a minor.

### Content rating

To specify the maximum content rating, the following code must be added before initializing the SDK:

{% tabs %}
{% tab title="Swift" %}

```swift
WAAdSettings.maxAdContentRating = WAAdContentRating.G
```

{% endtab %}
{% endtabs %}

The following values are available when specifying the content rating:

| Value                  | Description                                                |
| ---------------------- | ---------------------------------------------------------- |
| `WAAdContentRating.G`  | Content suitable for minors                                |
| `WAAdContentRating.PG` | Content suitable for most audiences with parental guidance |
| `WAAdContentRating.T`  | Content suitable for teens                                 |
| `WAAdContentRating.MA` | Content suitable only for adults                           |

{% hint style="info" %}
If the app is directed primarily to children, it is completely needed to specify the `G` rating,

Otherwise, if the app audience is mixed, a `G` or `PG` rating must be set.
{% endhint %}


# SDK integration

## Requisites

This documentation has been written for Unity **2022 or higher**. It is recommended to use these versions when integrating the SDK.

## Import Unity package

In first place, it is needed to download the Unity package from the following link:

<p align="center"><a href="https://cdn.resources.wortise.com/sdk/unity/Wortise-Unity-1.7.3.unitypackage" class="button primary" data-icon="arrow-down-to-line">Download Wortise Unity Package</a></p>

Once downloaded, double click on the file to import it into the project.

## Setup SDK

To setup the SDK, go to the **Wortise -> Settings** option in the Unity menu bar. After selecting the option, the settings window will open where you must specify the Google application IDs for each platform:

<figure><img src="/files/fGdv56q3jD3mD4NuDaIa" alt="" width="563"><figcaption><p>Window screenshot</p></figcaption></figure>

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

## Request consent

{% hint style="success" %}
It is **very recommended** to request the user consent to be able to show personalised ads. This will allow to display content of more interest and generate higher revenues.
{% endhint %}

You can consult the following section to implement this request and obtain the user consent: [User consent](/en/unity-sdk/user-consent)

## Initialize SDK

To initialize the SDK, it is needed to add the following lines in the `Start()` method of the first project `Scene`. Also, we recommend to implement the `OnInitialized` event to request the consent once the initialization has finished:

```csharp
void Start() {
    ...
    
    WortiseSdk.OnInitialized += () => {
        WortiseConsentManager.RequestIfRequired();
    };
    
    WortiseSdk.Initialize("your app key");
}
```

## Test mode

To verify the integration, the SDK provides a test mode that allows the app to always receive ads.

Beside the option that is available in our dashboard, you can programmatically enable this test mode, from the SDK itself, by using the following code:

```csharp
WortiseAdSettings.IsTestEnabled = true;
```


# App Open

## Integration

To make use of App Open ads, it is needed to request their load at some point inside the app, being recommended to do it as soon as possible.

Below you can find an example of how to load and show an ad:

```csharp
// Create an App Open
WortiseAppOpen appOpenAd = new WortiseAppOpen(
    "Wortise Ad Unit ID"
);

// Request an ad
appOpenAd.LoadAd();

// Show the ad if available
if (appOpenAd.IsAvailable) {
    appOpenAd.ShowAd();
}
```

Also, the `WortiseAppOpen` class offers the following additional methods to configure its behaviour:

```csharp
// Sets if a new ad must be loaded after closing the previous one
appOpenAd.AutoReload = true;

// Shows an ad immediately if available. Otherwise, requests the load of a
// new ad
appOpenAd.TryToShowAd();
```

## **Listener configuration**

Some listeners can be added to receive the different events that may occur during the ad lifecycle. For this, you can make use of the following attributes that are available at the `WortiseAppOpen` class:

* `OnClicked`
* `OnDismissed`
* `OnFailedToLoad`
* `OnFailedToShow`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`
* `OnShown`

### Example

```csharp
appOpenAd.OnClicked      += () => Debug.Log('App open clicked');
appOpenAd.OnDismissed    += () => Debug.Log('App open dismissed');
appOpenAd.OnFailedToLoad += () => Debug.Log('App open failed to load');
appOpenAd.OnFailedToShow += () => Debug.Log('App open failed to show');
appOpenAd.OnImpression   += () => Debug.Log('App open impression');
appOpenAd.OnLoaded       += () => Debug.Log('App open loaded');
appOpenAd.OnRevenuePaid  += (data) => Debug.Log('App open revenue paid');
appOpenAd.OnShown        += () => Debug.Log('App open shown');
```


# Banner

Banner ads are rectangular image or text ads that occupy a space inside the application layout. They stay on screen while the users interact with the app and can automatically refresh after a certain period of time. If you are new in mobile advertising, they are an excellent choice to start.

## **Integration**

Para realizar la integración de un banner, es necesario implementar un código similar al del ejemplo que se muestra a continuación:

```csharp
// Create a banner
WortiseBanner bannerAd = new WortiseBanner(
    "Wortise Ad Unit ID",
    WortiseAdSize.Height50,
    WortiseAdPosition.Top
);

// Optional: Set the auto-refresh time in milliseconds
bannerAd.AutoRefreshTime = 60000;

// Request an ad
banner.LoadAd();
```

## **Adaptive banners**

Adaptive banners are a new banner format where the size of the ads is adapted according to the device and the app user-interface, in order to maximize performance.

Currently there is support for two kind of adaptive banners:

### Anchored

This kind of banner is designed to replace the traditional 320x50 banners and be positioned at the top or bottom of the screen.

To make use of this format, an `WortiseAdSize` generated in the following way must be passed to the `WortiseBannerAd` instance:

```dart
// It is needed to specify the banner width
WortiseAdSize.GetAnchoredAdaptiveBannerAdSize(width);
```

### Inline

This other kind of banner, in comparison to the anchored, is designed to have a variable height and be positioned inside a scrolling content.

In this case, an `WortiseAdSize` must be generated this way:

```dart
// It is needed to specify the banner width. The maximum height is an
// optional parameter (by passing 0 or a negative value)
WortiseAdSize.GetInlineAdaptiveBannerAdSize(width, maxHeight);
```

## **Listener setup**

Some listeners can be added to receive the different events that may occur during the interstitial lifecycle. For this, you can make use of the following attributes that are available at the `WortiseBanner` class:

* `OnClicked`
* `OnFailedToLoad`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`

### Example

```csharp
bannerAd.OnClicked      += () => Debug.Log('Banner clicked');
bannerAd.OnFailedToLoad += () => Debug.Log('Banner failed to load');
bannerAd.OnImpression   += () => Debug.Log('Banner impression');
bannerAd.OnLoaded       += () => Debug.Log('Banner loaded');
bannerAd.OnRevenuePaid  += (data) => Debug.Log('Banner revenue paid');
```


# Interstitial

## Integration

To make use of interstitial ads, it is needed to request their load at some point inside the app, being recommended to do it as soon as possible.

Below you can find an example of how to load and show an interstitial ad:

```csharp
// Create an interstitial
WortiseInterstitial interstitialAd = new WortiseInterstitial(
    "Wortise Ad Unit ID"
);

// Request an ad
interstitialAd.LoadAd();

// Show an ad if available
if (interstitialAd.IsAvailable) {
    interstitialAd.ShowAd();
}
```

## **Listener configuration**

Some listeners can be added to receive the different events that may occur during the interstitial lifecycle. For this, you can make use of the following attributes that are available at the `WortiseInterstitial` class:

* `OnClicked`
* `OnDismissed`
* `OnFailedToLoad`
* `OnFailedToShow`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`
* `OnShown`

### Example

```csharp
interstitialAd.OnClicked      += () => Debug.Log('Interstitial clicked');
interstitialAd.OnDismissed    += () => Debug.Log('Interstitial dismissed');
interstitialAd.OnFailedToLoad += () => Debug.Log('Interstitial failed to load');
interstitialAd.OnFailedToShow += () => Debug.Log('Interstitial failed to show');
interstitialAd.OnImpression   += () => Debug.Log('Interstitial impression');
interstitialAd.OnLoaded       += () => Debug.Log('Interstitial loaded');
interstitialAd.OnRevenuePaid  += (data) => Debug.Log('Interstitial revenue paid');
interstitialAd.OnShown        += () => Debug.Log('Interstitial shown');
```


# Rewarded

## Integration

To make use of rewarded ads, it is needed to request their load at some point inside the app, being recommended to do it as soon as possible.

Below you can find an example of how to load and show an rewarded ad:

```csharp
// Create a rewarded
WortiseRewarded rewardedAd = new WortiseRewarded(
    "Wortise Ad Unit ID"
);

// Request an ad
rewardedAd.LoadAd();

// Show an ad if available
if (rewardedAd.IsAvailable) {
    rewardedAd.ShowAd();
}
```

## **Listener configuration**

Some listeners can be added to receive the different events that may occur during the rewarded lifecycle. For this, you can make use of the following attributes that are available at the `WortiseRewarded` class:

* `OnClicked`
* `OnCompleted`
* `OnDismissed`
* `OnFailedToLoad`
* `OnFailedToShow`
* `OnImpression`
* `OnLoaded`
* `OnRevenuePaid`
* `OnShown`

### Example

```csharp
rewardedAd.OnClicked      += () => Debug.Log('Rewarded clicked');
rewardedAd.OnCompleted    += (reward) => Debug.Log('Rewarded completed');
rewardedAd.OnDismissed    += () => Debug.Log('Rewarded dismissed');
rewardedAd.OnFailedToLoad += () => Debug.Log('Rewarded failed to load');
rewardedAd.OnFailedToShow += () => Debug.Log('Rewarded failed to show');
rewardedAd.OnImpression   += () => Debug.Log('Rewarded impression');
rewardedAd.OnLoaded       += () => Debug.Log('Rewarded loaded');
rewardedAd.OnRevenuePaid  += (data) => Debug.Log('Rewarded revenue paid');
rewardedAd.OnShown        += () => Debug.Log('Rewarded shown');
```


# Targeting

## Request permissions

{% hint style="info" %}
This step is **completely optional** and should only be implemented if it is convenient for the application’s purpose.
{% endhint %}

The app may request the location permissions so that our SDK can obtain the user's current location and display more relevant ads based on that information.

For this, it is necessary to add the following permissions in the `AndroidManifest.xml` file:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

Following this, the app must request the permissions so that users can grant them, just as specified in Unity's [official documentation](https://docs.unity3d.com/Manual/android-RequestingPermissions.html).


# Revenue reporting

## Implementation

Since version **1.7.0**, apps can receive an estimated revenue that has likely been generated by an ad.

To do this, it is just needed to implement the corresponding listener for each ad format, as shown in the example below:

```csharp
WortiseBannerAd bannerAd;

bannerAd.OnRevenuePaid += (data) => {
    Debug.Log('Banner revenue paid');
};
```

The listener receives an object of type `WortiseRevenueData` that contains the following fields:

<table><thead><tr><th width="139.62109375">Field</th><th width="175.20703125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>WortiseAdValue</code></td><td>The revenue generated by the ad</td></tr><tr><td><code>source</code></td><td><code>string</code></td><td>The revenue source</td></tr></tbody></table>

In addition, the `WortiseAdValue` class contains the following fields that represent the revenue:

<table><thead><tr><th width="140.49609375">Field</th><th width="175.171875">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>string</code></td><td>The currency corresponding to the revenue</td></tr><tr><td><code>precision</code></td><td><code>WortisePrecision</code></td><td>The accuracy of the information. It can be <code>Estimated</code>, <code>Precise</code> or <code>PublisherDefined</code></td></tr><tr><td><code>value</code></td><td><code>double</code></td><td>The revenue value</td></tr></tbody></table>

## Integration with Firebase

Below, a basic example is shown of how to report the revenue information to Firebase:

```csharp
using Firebase.Analytics;

bannerAd.OnRevenuePaid += (data) => {
    FirebaseAnalytics.LogEvent(
        "ad_revenue",
        new Parameter("currency",  data.revenue.currency),
        new Parameter("precision", data.revenue.precision?.ToString()),
        new Parameter("source",    data.source),
        new Parameter("value",     data.revenue.value)
    );
};
```


# User consent

The Wortise SDK includes support for Google Ads **Consent Manager** (**CMP**) to request the consent of every user.

Obtaining the user consent is important to comply with the privacy policies and qualify for higher CPMs.

## Request consent

To request the user consent, it is needed to invoke the method `WortiseConsentManager.RequestIfRequired` at an appropriate moment of the app. This will show a dialog, only when it is required (normally during the first app launch), so the user can grant or deny consent.

There is also the `WortiseConsentManager.Request` method to always show the dialog, and not only when required (for example, to provide an option in the app settings to allow the user change the consent at anytime).

### Example

```csharp
WortiseSdk.OnInitialized += () => {
    WortiseConsentManager.RequestIfRequired();
};
```


# Privacy

## Families Policy

If you application is targeting minors (exclusively or not), it is needed to comply with the requirements established by Google Play's [Families Policy](https://support.google.com/googleplay/android-developer/answer/9900633).

To facilitate the compliance of these policies, the SDK allows to specify if the ad requests are targeted to minors, beside the ability to set the maximum content rating.

It is very important to comply with these requirements, and carefully review the related policies, to avoid any issues with Google Play.

### Child directed content

To specify if an user is a minor or not, it is needed to include the following code **before** initializing the SDK:

```csharp
// true  -> The user is a minor or the age is unknown
// false -> The user is an adult
WortiseAdSettings.IsChildDirected = true;
```

If the user age is unknown, the app must treat that user as if they were a minor.

### Content rating

To specify the maximum content rating, the following code must be added before initializing the SDK:

```csharp
WortiseAdSettings.MaxAdContentRating = WortiseAdContentRating.G;
```

The following values are available when specifying the content rating:

| Value                       | Description                                                |
| --------------------------- | ---------------------------------------------------------- |
| `WortiseAdContentRating.G`  | Content suitable for minors                                |
| `WortiseAdContentRating.PG` | Content suitable for most audiences with parental guidance |
| `WortiseAdContentRating.T`  | Content suitable for teens                                 |
| `WortiseAdContentRating.MA` | Content suitable only for adults                           |

{% hint style="info" %}
If the app is directed primarily to children, it is completely needed to specify the `G` rating,

Otherwise, if the app audience is mixed, a `G` or `PG` rating must be set.
{% endhint %}

### Additional requirements

If you app is directed to children, exclusively or not, it is needed to remove the Facebook adapter that is included in our SDK due to not being certified by Google Play yet for its use with children.

To do this, it is needed to modify the SDK integration in the `mainTemplate.gradle` file to specify the exclusion of the adapter, just as shown below:

```groovy
implementation('com.wortise:android-sdk:x.y.z') {
    exclude group: 'com.google.ads.mediation', module: 'facebook'
}
```


# SDK integration

## Setup project

To integrate our SDK for Flutter, it is needed to add the following line inside the `dependencies` block of the `pubspec.yaml` file of your app:

```yaml
dependencies:
  wortise: ^1.7.5
```

Next, execute the following command to proceed with the SDK installation:

```bash
$ flutter pub get
```

Now, you will be able to use the following `import` statements to access the classes provided by the SDK:

```dart
import 'package:wortise/ad_content_rating.dart';
import 'package:wortise/ad_settings.dart';
import 'package:wortise/ad_size.dart';
import 'package:wortise/banner_ad.dart';
import 'package:wortise/consent_manager.dart';
import 'package:wortise/data_manager.dart';
import 'package:wortise/interstitial_ad.dart';
import 'package:wortise/rewarded_ad.dart';
import 'package:wortise/user_gender.dart';
import 'package:wortise/wortise_sdk.dart';
```

## Setup Manifest (Android)

It is needed to add the following `<meta-data>` element in the `android/app/src/main/AndroidManifest.xml` file, inside the `<application>` block, with Google's application ID as value:

```xml
<manifest>
    ...
    <application>
        ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>
```

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

## Setup Info.plist (iOS)

It is needed to add the following parameter in the `Info.plist` file, with Google's application ID as value:

```xml
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxxxx</string>
```

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

Then, it would only be needed to add the following block, in the same file, to complete the correct integration with Google:

```xml
<key>SKAdNetworkItems</key>
<array>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cstr6suwn9.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4fzdc2evr5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4pfyvq9l8r.skadnetwork </string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2fnua5tdw4.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ydx93a7ass.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>5a6flpkh64.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>p78axxw29g.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v72qych5uu.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ludvb6z3bs.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cp8zw746q7.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>c6k4g5qg8m.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>s39g8k73mm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qy4746246.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3sh42y64q3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>f38h382jlk.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>hs6bdukanm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>prcb7njmu6.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v4nxqhlyqp.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>wzmmz9fp6w.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>yclnxrl5pm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>t38b2kh725.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>7ug5zh24hu.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>9rd848q2bz.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>y5ghdn5j9k.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n6fk4nfna4.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v9wttpbfk9.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n38lu8286q.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>47vhws6wlr.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>kbd757ywx3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>9t245vhmpl.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>a2p9lx4jpn.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>22mmun2rn5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4468km3ulz.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2u9pt9hc89.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8s468mfl3y.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>av6w8kgt66.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>klf5c3l5u5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ppxm28t8ap.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>424m5254lk.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ecpz2srf59.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>uw77j35x4d.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>mlmmfzh3r3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>578prtvx9j.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4dzt52r2t5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>gta9lk7p23.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>e5fvkxwrpn.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8c4e2ghe7u.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>zq492l623r.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3rd42ekr43.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qcr597p9d.skadnetwork</string>
    </dict>
</array>
```

## Request consent

{% hint style="success" %}
It is **very recommended** to request the user consent to be able to show personalised ads. This will allow to display content of more interest and generate higher revenues.
{% endhint %}

You can consult the following section to implement this request and obtain the user consent: [User consent](/en/flutter-sdk/user-consent)

## Initialize SDK

To initialize the SDK, it is needed to add the following code inside the `initState()` method of your app:

```dart
import 'package:wortise/wortise_sdk.dart';

await WortiseSdk.initialize('your app key');
```

## Test mode

To verify the integration, the SDK provides a test mode that allows the app to always receive ads.

Beside the option that is available in our dashboard, you can programatically enable this test mode, from the SDK itself, by using the following code:

```dart
import 'package:wortise/ad_settings.dart';

await AdSettings.setTestEnabled(true);
```


# App Open

## Integration

Below we show a few simple examples to implement the App Open ads by following the two possible ways of integration:

### Manual

```dart
import 'package:wortise/app_open_ad.dart';

AppOpenAd _appOpenAd;

// Create an App Open
_appOpenAd = AppOpenAd('Wortise Ad Unit ID', listener: (event, args) {
  // This listener will be invoked when an event happens
});

// Request an ad
await _appOpenAd.loadAd();

/* ... */

// Show the ad if available
if (await _appOpenAd.isAvailable) {
  await _appOpenAd.showAd();
}
```

The AppOpenAd class constructor allows to specify the following optional parameters to configure its behaviour:

```dart
// Sets if a new ad must be loaded after closing the previous one
autoReload: true
```

Alternatively, the `tryToShowAd()` method can be used to show the ad with the difference that, if there is none available, the load of a new ad is automatically requested.

```dart
await _appOpenAd.tryToShowAd();
```

### Via Manager

```dart
import 'package:wortise/app_open_ad.dart';
import 'package:wortise/app_open_manager.dart';

// Create an App Open
AppOpenAd appOpenAd = AppOpenAd('Wortise Ad Unit ID')..loadAd();

// Register the ad in the manager
AppOpenManager.register(appOpenAd);
```

In this integration, the ads will be automatically shown when an app transitions from background to foreground. Also, the methods offered by `AppOpenAd` can still be used to show ads on demand.

## **Listener events**

The assigned listener to an `AppOpenAd` can receive the following events:

```dart
// The ad has been clicked
AppOpenAdEvent.CLICKED
// The ad has been dismissed
AppOpenAdEvent.DISMISSED
// The ad could not be loaded
AppOpenAdEvent.FAILED_TO_LOAD
// The ad could not be shown
AppOpenAdEvent.FAILED_TO_SHOW
// The ad has generated an impression
AppOpenAdEvent.IMPRESSION
// The ad has been loaded
AppOpenAdEvent.LOADED
// The ad has generated revenue
AppOpenAdEvent.REVENUE_PAID
// The ad has been shown
AppOpenAdEvent.SHOWN
```


# Banner

Banner ads are rectangular image or text ads that occupy a space inside the application layout. They stay on screen while the users interact with the app and can automatically refresh after a certain period of time. If you are new in mobile advertising, they are an excellent choice to start.

## **Integration**

Banners are integrated by adding the `BannerAd` widget to the app's layout. Below, you can find a simple integration example:

```dart
import 'package:wortise/ad_size.dart';
import 'package:wortise/banner_ad.dart';

/* ... */

@override
Widget build(BuildContext context) {
  return MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: const Text('Wortise Flutter Example'),
      ),
      body: ListView(
        padding: EdgeInsets.all(20),
        children: [
          /* Banner must be inside a container */
          Container(
            height: 50,
            child: BannerAd(
              adSize: AdSize.HEIGHT_50,
              adUnitId: 'Wortise Ad Unit ID',
            ),
          )
        ]
      ),
    ),
  );
}
```

The widget has support for the following parameters:

| Parameter           | Type     | Required | Description                                                                                                     |
| ------------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| **adUnitId**        | String   | **Yes**  | The ad unit ID to assign to the banner                                                                          |
| **adSize**          | AdSize   | No       | Maximum size (height) for the banner. The possible values for this parameter are declared in the `AdSize` class |
| **autoRefreshTime** | Integer  | No       | Value in seconds that represents the time that must elapse to load a new banner ad                              |
| **keepAlive**       | Boolean  | No       | Indicates if the banner instance should be keep "alive" at any moment                                           |
| **listener**        | Function | No       | Listener to receive the banner events (`BannerAdEvent`)                                                         |

## **Adaptive banners**

Adaptive banners are a new banner format where the size of the ads is adapted according to the device and the app user-interface, in order to maximize performance.

Currently there is support for two kind of adaptive banners:

### Anchored

This kind of banner is designed to replace the traditional 320x50 banners and be positioned at the top or bottom of the screen.

To make use of this format, an `AdSize` generated in the following way must be passed to the `BannerAd` widget:

```dart
// It is needed to specify the banner width
AdSize.getAnchoredAdaptiveBannerAdSize(width);
```

### Inline

This other kind of banner, in comparison to the anchored, is designed to have a variable height and be positioned inside a scrolling content.

In this case, an `AdSize` must be generated this way:

```dart
// It is needed to specify the banner width. The maximum height is an
// optional parameter (by passing 0 or a negative value)
AdSize.getInlineAdaptiveBannerAdSize(width, maxHeight);
```

## **Listener setup**

A listener can be set to any `BannerAd` instance to receive the events that happen during its lifecycle. For this, it is needed to assign a function to the `listener` parameter of the widget, just as shown below:

```dart
BannerAd(
  adSize: AdSize.HEIGHT_50,
  adUnitId: 'Wortise Ad Unit ID',
  listener: (event, args) {
    switch (event) {
      case BannerAdEvent.CLICKED: {
        // The ad has been clicked
      }
      break;
      
      case BannerAdEvent.FAILED_TO_LOAD: {
        // The ad could not be loaded
      }
      break;

      case BannerAdEvent.IMPRESSION: {
        // The ad has generated an impression
      }
      break;
      
      case BannerAdEvent.LOADED: {
        // The ad has been loaded
      }
      break;
      
      case BannerAdEvent.REVENUE_PAID: {
        // The ad has generated revenue
      }
      break;
    }
  },
)
```


# Interstitial

## Integration

&#x20;Below we show a simple example to understand how interstitial ads work:

```dart
import 'package:wortise/interstitial_ad.dart';

InterstitialAd _interstitialAd;

// Create an interstitial
_interstitialAd = InterstitialAd('Wortise Ad Unit ID', listener: (event, args) {
  // This listener will be invoked when an event happens
});

// Request an ad
await _interstitialAd.loadAd();

/* ... */

// Show the ad if available
if (await _interstitialAd.isAvailable) {
  await _interstitialAd.showAd();
}
```

The `InterstitialAd` class constructor admits a third parameter, called `reloadOnDismissed`, that when it is set to `true` (the default value is `false`) allows the interstitial to automatically load a new ad when the current one is dismissed.

## **Listener events**

The assigned listener to an `InterstitialAd` can receive the following events:

```dart
// The ad has been clicked
InterstitialAdEvent.CLICKED
// The ad has been dismissed
InterstitialAdEvent.DISMISSED
// The ad could not be loaded
InterstitialAdEvent.FAILED_TO_LOAD
// The ad could not be shown
InterstitialAdEvent.FAILED_TO_SHOW
// The ad has generated an impression
InterstitialAdEvent.IMPRESSION
// The ad has been loaded
InterstitialAdEvent.LOADED
// The ad has generated revenue
InterstitialAdEvent.REVENUE_PAID
// The ad has been shown
InterstitialAdEvent.SHOWN
```


# Rewarded

## Integration

&#x20;Below we show a simple example to understand how rewarded ads work:

```dart
import 'package:wortise/rewarded_ad.dart';

RewardedAd _rewardedAd;

// Create an interstitial
_rewardedAd = RewardedAd('Wortise Ad Unit ID', listener: (event, args) {
  // This listener will be invoked when an event happens
});

// Request an ad
await _rewardedAd.loadAd();

/* ... */

// Show the ad if available
if (await _rewardedAd.isAvailable) {
  await _rewardedAd.showAd();
}
```

The `RewardedAd` class constructor admits a third parameter, called `reloadOnDismissed`, that when it is set to `true` (the default value is `false`) allows the rewarded to automatically load a new ad when the current one is dismissed.

## **Listener events**

The assigned listener to an `RewardedAd` can receive the following events:

```dart
// The ad has been clicked
RewardedAdEvent.CLICKED
// The ad has been completed
// (the 'amount', 'label' y 'success' arguments are passed)
RewardedAdEvent.COMPLETED
// The ad has been dismissed
RewardedAdEvent.DISMISSED
// The ad could not be loaded
RewardedAdEvent.FAILED_TO_LOAD
// The ad could not be shown
RewardedAdEvent.FAILED_TO_SHOW
// The ad has generated an impression
RewardedAdEvent.IMPRESSION
// The ad has been loaded
RewardedAdEvent.LOADED
// The ad has generated revenue
RewardedAdEvent.REVENUE_PAID
// The ad has been shown
RewardedAdEvent.SHOWN
```

Below, we show a small example about how to obtain the reward once the ad has completed successfully:

```dart
(event, args) {
  if (event == RewardedAdEvent.COMPLETED) {
    int    amount  = args['amount'];
    String label   = args['label'];
    bool   success = args['success'];
    
    ...
  }
});
```


# Native (Google)

The native ads are a kind of ad that can be shown using the same visual style like the rest of the app, which allows a natural and non-intrusive integration with the user interface.

Currently, Wortise provides the possibility of use the native ads from Google's ad platform, in a simple and direct way.

## Integration

First of all, it is needed to create a Java (or Kotlin) class that implements a `GoogleNativeAdFactory` object. This object will contain a method that will receive a `NativeAd` from Google and will return a `NativeAdView` object with the rendered native ad.

This step is very similar to the one explained by Google in their own [documentation](https://developers.google.com/admob/flutter/native#platform_setup), with the only difference of using `GoogleNativeAdFactory` instead of `NativeAdFactory`.

Below we show an implementation example of this class:&#x20;

```kotlin
import android.graphics.Color
import android.view.LayoutInflater
import android.widget.TextView
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView

class NativeAdFactoryExample(private val layoutInflater: LayoutInflater)
    : GoogleNativeAdFactory {

    override fun createNativeAd(nativeAd: NativeAd): NativeAdView {
        val adView = layoutInflater.inflate(R.layout.my_native_ad, null) as NativeAdView
        
        val headlineView = adView.findViewById<TextView>(R.id.ad_headline)
        val bodyView     = adView.findViewById<TextView>(R.id.ad_body)
    
        headlineView.setText(nativeAd.headline)

        bodyView.setText(nativeAd.body)
    
        adView.setBackgroundColor(Color.YELLOW)
        adView.setNativeAd(nativeAd)
        adView.setBodyView(bodyView)
        adView.setHeadlineView(headlineView)
        
        return adView
    }
}
```

Once implemented, this class has to be registered inside the `MainActivity` as in the following example:

```kotlin
import com.wortise.ads.flutter.natives.GoogleNativeAdManager
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine

class MainActivity: FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        GoogleNativeAdManager.registerAdFactory(
            "test-factory", NativeAdFactoryExample(layoutInflater))
    }

    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine)

        GoogleNativeAdManager.unregisterAdFactory("test-factory")
    }
}
```

In this example, `test-factory` is the identifier that is assigned to the `GoogleNativeAdFactory` object, which should to be used later when creating a native ad in Flutter.

Next, to request a native ad, it is needed to make a code integration like the following:

```dart
import 'package:wortise/google_native_ad.dart';

GoogleNativeAd _interstitialAd;

// Create a native

// It is needed to specifiy the ID of the "GoogleNativeAdFactory" object that
// was set before
_nativeAd = GoogleNativeAd('test-native', 'test-factory', (event, args) {
  // This listener will be invoked when an event happens
});

// Request an ad
await _nativeAd.loadAd();
```

Once the native ad has been successfully loaded, it is needed to create an `AdWidget` widget that must be added to the app's interface.

This step can be implemented like in the following example:

```dart
import 'package:wortise/ad_widget.dart';
import 'package:wortise/google_native_ad.dart';

GoogleNativeAd? _nativeAd;

AdWidget? _nativeWidget;
  
// Create a native
_nativeAd = GoogleNativeAd('test-native', 'test-factory', (event, args) {
  // An event is recevied to notify a successful load
  if (event == GoogleNativeAdEvent.LOADED) {
    // Create an "AdWidget" widget with the native ad
    // This widget must be added to the app's interface to display the ad
    setState(() => _nativeWidget = AdWidget(ad: _nativeAd!));
  }
});
```

## **Listener events**

The assigned listener to an `GoogleNativeAd` can receive the following events:

```dart
// The ad has been clicked
GoogleNativeAdEvent.CLICKED
// The ad could not be loaded
GoogleNativeAdEvent.FAILED_TO_LOAD
// The ad has generated an impression
GoogleNativeAdEvent.IMPRESSION
// The ad has been loaded
GoogleNativeAdEvent.LOADED
// The ad has generated revenue
GoogleNativeAdEvent.REVENUE_PAID
```


# Targeting

## Request permissions

{% hint style="info" %}
This step is **completely optional** and should only be implemented if it is convenient for the application’s purpose.
{% endhint %}

The app may request the location permissions so that our SDK can obtain the user's current location and display more relevant ads based on that information.

For this, it is necessary to add the following permissions in the `android/app/src/main/AndroidManifest.xml` file:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

Following this, the app must request the permissions so that users can grant them. For this purpose, for example, the [permission\_handler](https://pub.dev/packages/permission_handler) library can be used.


# Revenue reporting

## Implementation

Since version **1.7.0**, apps can receive an estimated revenue that has likely been generated by an ad.

To do this, it is just needed to implement the corresponding listener for each ad format, as shown in the example below:

```dart
BannerAd(
  ...
  listener: (event, args) {
    if (event == BannerAdEvent.REVENUE_PAID) {
      // El anuncio ha sido generado un ingreso
    }
  },
)
```

The listener receives an object as argument that contains the following fields:

<table><thead><tr><th width="139.62109375">Field</th><th width="175.20703125">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>revenue</code></td><td><code>Map</code></td><td>The revenue generated by the ad</td></tr><tr><td><code>source</code></td><td><code>String</code></td><td>The revenue source</td></tr></tbody></table>

In addition, the `revenue` object contains the following fields that represent the revenue:

<table><thead><tr><th width="140.49609375">Field</th><th width="175.171875">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>currency</code></td><td><code>String</code></td><td>The currency corresponding to the revenue</td></tr><tr><td><code>precision</code></td><td><code>String</code></td><td>The accuracy of the information. It can be <code>ESTIMATED</code>, <code>PRECISE</code> or <code>PUBLISHER_DEFINED</code></td></tr><tr><td><code>value</code></td><td><code>double</code></td><td>The revenue value</td></tr></tbody></table>

## Integration with Firebase

Below, a basic example is shown of how to report the revenue information to Firebase:

```dart
final analytics = FirebaseAnalytics();

BannerAd(
  ...
  listener: (event, args) {
    if (event == BannerAdEvent.REVENUE_PAID) {
      analytics.logEvent(
        name: 'ad_revenue',
        parameters: {
          'currency':  args['revenue']['currency'],
          'precision': args['revenue']['precision'],
          'source':    args['source'],
          'value':     args['revenue']['value'],
        },
      );
    }
  },
)
```


# User consent

The Wortise SDK includes support for Google Ads **Consent Manager** (**CMP**) to request the consent of every user.

Obtaining the user consent is important to comply with the privacy policies and qualify for higher CPMs.

## Request consent

To request the user consent, it is needed to invoke the method `ConsentManager.requestIfRequired` at an appropriate moment of the app. This will show a dialog, only when it is required (normally during the first app launch), so the user can grant or deny consent.

There is also the `ConsentManager.request` method to always show the dialog, and not only when required (for example, to provide an option in the app settings to allow the user change the consent at anytime).

### Example

```dart
import 'package:wortise/consent_manager.dart';

await ConsentManager.requestIfRequired();
```


# Privacy

## Families Policy

If you application is targeting minors (exclusively or not), it is needed to comply with the requirements established by Google Play's [Families Policy](https://support.google.com/googleplay/android-developer/answer/9900633).

To facilitate the compliance of these policies, the SDK allows to specify if the ad requests are targeted to minors, beside the ability to set the maximum content rating.

It is very important to comply with these requirements, and carefully review the related policies, to avoid any issues with Google Play.

### Child directed content

To specify if an user is a minor or not, it is needed to include the following code **before** initializing the SDK:

```dart
import 'package:wortise/ad_settings.dart';

// true  -> The user is a minor or the age is unknown
// false -> The user is an adult
await AdSettings.setChildDirected(true);
```

If the user age is unknown, the app must treat that user as if they were a minor.

### Content rating

To specify the maximum content rating, the following code must be added before initializing the SDK:

```dart
import 'package:wortise/ad_content_rating.dart';
import 'package:wortise/ad_settings.dart';

await AdSettings.setMaxAdContentRating(AdContentRating.G);
```

The following values are available when specifying the content rating:

| Value                | Description                                                |
| -------------------- | ---------------------------------------------------------- |
| `AdContentRating.G`  | Content suitable for minors                                |
| `AdContentRating.PG` | Content suitable for most audiences with parental guidance |
| `AdContentRating.T`  | Content suitable for teens                                 |
| `AdContentRating.MA` | Content suitable only for adults                           |

{% hint style="info" %}
If the app is directed primarily to children, it is completely needed to specify the `G` rating,

Otherwise, if the app audience is mixed, a `G` or `PG` rating must be set.
{% endhint %}

### Additional requirements

If you app is directed to children, exclusively or not, it is needed to remove the Facebook adapter that is included in our SDK due to not being certified by Google Play yet for its use with children.

To do this, it is needed to add the following lines inside the `android/app/build.gradle` file:

```groovy
configurations {
    all*.exclude group: 'com.google.ads.mediation', module: 'facebook'
}
```


# SDK integration

## Install dependency

To integrate our SDK for React Native, it is needed to run the following command in the project's root:

```bash
npm install @wortise/react-native-sdk --save
```

{% hint style="info" %}
The latest version of the React Native SDK is **1.7.6**
{% endhint %}

## Setup Expo project

If your project uses the **Expo** framework, the setup process can be done in an easy way.

It is just needed to add the following details inside the project's `app.json` file:

```json
{
  "expo": {
    "plugins": [
      [
        "@wortise/react-native-sdk",
        {
          "androidGoogleAppId": "ca-app-pub-xxxxxxxxxxxxxx~yyyyyyyyyy",
          "iosGoogleAppId": "ca-app-pub-xxxxxxxxxxxxxx~yyyyyyyyyy"
        }
      ]
    ]
  }
}
```

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

After the setup has been done, our plugin will automatically insert the Google "App IDs" for both platforms, as well as the repositories and other details that are needed to complete the SDK integration.

## Setup project manually

If your project does not use the Expo framework, or you prefer to do a manual setup, you must follow the following steps:

### Add repositories (Android)

Next, the following Maven repositories need to be added inside the `allprojects > repositories` block of the `android/build.gradle` file:

```groovy
allprojects {
    repositories {
        ...
        maven { url 'https://maven.wortise.com/artifactory/public' }
        
        maven { url 'https://android-sdk.is.com/' }
        maven { url 'https://artifact.bytedance.com/repository/pangle' }
        maven { url 'https://cboost.jfrog.io/artifactory/chartboost-ads/' }
    }
}
```

### Setup Manifest (Android)

It is needed to add the following `<meta-data>` element in the `android/app/src/main/AndroidManifest.xml` file, inside the `<application>` block, with Google's application ID as value:

```xml
<manifest>
    ...
    <application>
        ...
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>
</manifest>
```

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

### Setup Info.plist (iOS)

It is needed to add the following parameter in the `Info.plist` file, with Google's application ID as value:

```xml
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-xxxxxxxxxxxxxxxxxx</string>
```

{% hint style="info" %}
This value can be found in our dashboard, inside the app details, under the name `Google App ID`.
{% endhint %}

Then, it would only be needed to add the following block, in the same file, to complete the correct integration with Google:

```xml
<key>SKAdNetworkItems</key>
<array>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cstr6suwn9.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4fzdc2evr5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4pfyvq9l8r.skadnetwork </string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2fnua5tdw4.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ydx93a7ass.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>5a6flpkh64.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>p78axxw29g.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v72qych5uu.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ludvb6z3bs.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>cp8zw746q7.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>c6k4g5qg8m.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>s39g8k73mm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qy4746246.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3sh42y64q3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>f38h382jlk.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>hs6bdukanm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>prcb7njmu6.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v4nxqhlyqp.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>wzmmz9fp6w.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>yclnxrl5pm.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>t38b2kh725.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>7ug5zh24hu.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>9rd848q2bz.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>y5ghdn5j9k.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n6fk4nfna4.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>v9wttpbfk9.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>n38lu8286q.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>47vhws6wlr.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>kbd757ywx3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>9t245vhmpl.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>a2p9lx4jpn.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>22mmun2rn5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4468km3ulz.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>2u9pt9hc89.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8s468mfl3y.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>av6w8kgt66.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>klf5c3l5u5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ppxm28t8ap.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>424m5254lk.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>ecpz2srf59.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>uw77j35x4d.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>mlmmfzh3r3.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>578prtvx9j.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>4dzt52r2t5.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>gta9lk7p23.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>e5fvkxwrpn.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>8c4e2ghe7u.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>zq492l623r.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3rd42ekr43.skadnetwork</string>
    </dict>
    <dict>
    <key>SKAdNetworkIdentifier</key>
    <string>3qcr597p9d.skadnetwork</string>
    </dict>
</array>
```

## Request consent

{% hint style="success" %}
It is **very recommended** to request the user consent to be able to show personalised ads. This will allow to display content of more interest and generate higher revenues.
{% endhint %}

You can consult the following section to implement this request and obtain the user consent: [User consent](/en/react-native/user-consent)

## Initialize SDK

There are two options to do the SDK initialization:

### Option 1 (recommended)

The most recommended option is to do the initialization in the `Application` class of the app. To do son, the following code has to be integrated in the `onCreate()` method of the `MainApplication.java` file:

```java
WortiseSdk.initialize(this, "your app key");
```

### Option 2

In this option, the SDK initialization would be directly done in the JavaScript code of the project. To do so, the following lines have to be added to the code in a proper place:

```javascript
import { RNWortiseSdk } from '@wortise/react-native-sdk';

await RNWortiseSdk.initialize('your app key');
```

## Test mode

To verify the integration, the SDK provides a test mode that allows the app to always receive ads.

Beside the option that is available in our dashboard, you can programatically enable this test mode, from the SDK itself, by using the following code:

```javascript
import { RNWortiseAdSettings } from '@wortise/react-native-sdk';

RNWortiseAdSettings.setTestEnabled(true);
```


# App Open

## Integration

To make use of App Open ads, it is needed to request their load at some point inside the app, being recommended to do it as soon as possible. This can be done by using the following code:

```typescript
import { RNWortiseAppOpen } from '@wortise/react-native-sdk';

RNWortiseAppOpen.setAdUnitId('Wortise Ad Unit ID');
RNWortiseAppOpen.loadAd();
```

Next, to show the ad in the desired moment, you can use the `showAd()` and `isAvailable` methods just as shown in the following example:

```typescript
if (await RNWortiseAppOpen.isAvailable) {
    RNWortiseAppOpen.showAd();
}
```

Also, the `RNWortiseAppOpen` class offers the following additional methods to configure its behaviour:

{% hint style="info" %}
These methods must be invoked after calling the `setAdUnitId()` method
{% endhint %}

```typescript
// Sets if a new ad must be loaded after closing the previous one
RNWortiseAppOpen.setAutoReload(true);

// Shows an ad immediately if available. Otherwise, requests the load of a
// new ad
RNWortiseAppOpen.tryToShowAd();
```

## **Listener setup**

Some listeners can be added to receive the different events that may occur during the ad lifecycle. For this, it is needed to use the `addEventListener` method and specify which event type to receive, which can be one of the following:

* `onAppOpenClicked`
* `onAppOpenDismissed`
* `onAppOpenFailedToLoad`
* `onAppOpenFailedToShow`
* `onAppOpenImpression`
* `onAppOpenLoaded`
* `onAppOpenRevenuePaid`
* `onAppOpenShown`

### Example

```typescript
RNWortiseAppOpen.addEventListener('onAppOpenLoaded', () => {
  // The callback will be invoked when an ad is loaded
});
```


# Banner

Banner ads are rectangular image or text ads that occupy a space inside the application layout. They stay on screen while the users interact with the app and can automatically refresh after a certain period of time. If you are new in mobile advertising, they are an excellent choice to start.

## **Integration**

Banners are integrated by adding the `WortiseBanner` widget to the app's layout. Below, you can find a simple integration example:

```tsx
import { RNWortiseAdSize, WortiseBanner } from '@wortise/react-native-sdk';

/* ... */

const bannerRef = useRef(null);

return (
  <View style={styles.container}>
    <Button
      onPress={bannerRef.current?.loadAd()}
      title="Load Banner"
    />
    <WortiseBanner
      adSize={RNWortiseAdSize.HEIGHT_50}
      adUnitId="Wortise Ad Unit ID"
    />
  </View>
);
```

{% hint style="warning" %}
Since version `1.6.1+patch.1`, it is necessary to call the `loadAd()` method to start loading the banner.
{% endhint %}

The widget has support for the following parameters:

<table data-header-hidden><thead><tr><th width="170.16015625">Parameter</th><th width="114.98046875">Type</th><th width="109.5703125">Required</th><th>Descripction</th></tr></thead><tbody><tr><td>Parameter</td><td>Type</td><td>Required</td><td>Descripction</td></tr><tr><td><strong>adUnitId</strong></td><td>String</td><td><strong>Yes</strong></td><td>The ad unit ID to assign to the banner</td></tr><tr><td><strong>adSize</strong></td><td>String</td><td>No</td><td>Maximum size (height) for the banner. The possible values for this parameter are declared in the <code>RNWortiseAdSize</code> object</td></tr><tr><td><strong>autoRefreshTime</strong></td><td>Integer</td><td>No</td><td>Value in seconds that represents the time that must elapse to load a new banner ad</td></tr><tr><td><strong>onClicked</strong></td><td>Function</td><td>No</td><td>Function that will be invoked when the banner has been clicked</td></tr><tr><td><strong>onFailedToLoad</strong></td><td>Function</td><td>No</td><td>Function that will be invoked when the banner could not load an ad</td></tr><tr><td><strong>onImpression</strong></td><td>Function</td><td>No</td><td>Function that will be invoked when the banner has generated an impression</td></tr><tr><td><strong>onLoaded</strong></td><td>Function</td><td>No</td><td>Function that will be invoked when the banner has loaded an ad</td></tr><tr><td><strong>onRevenuePaid</strong></td><td>Function</td><td>No</td><td>Function that will be invoked when the banner has generated revenue</td></tr><tr><td><strong>onSizeChange</strong></td><td>Function</td><td>No</td><td>Function that will be invoked when the banner size has changed</td></tr></tbody></table>

## **Adaptive banners**

Adaptive banners are a new banner format where the size of the ads is adapted according to the device and the app user-interface, in order to maximize performance.

Currently there is support for two kind of adaptive banners:

### Anchored

This kind of banner is designed to replace the traditional 320x50 banners and be positioned at the top or bottom of the screen.

To make use of this format, an `AdSize` generated in the following way must be passed to the `BannerAd` widget:

```typescript
import { RNWortiseAdSize } from '@wortise/react-native-sdk';

// It is needed to specify the banner width
RNWortiseAdSize.getAnchoredAdaptiveBannerAdSize(width);
```

### Inline

This other kind of banner, in comparison to the anchored, is designed to have a variable height and be positioned inside a scrolling content.

In this case, an `AdSize` must be generated this way:

```typescript
import { RNWortiseAdSize } from '@wortise/react-native-sdk';

// It is needed to specify the banner width. The maximum height is an
// optional parameter (by passing 0 or a negative value)
RNWortiseAdSize.getInlineAdaptiveBannerAdSize(width, maxHeight);
```


# Interstitial

## Integration

To make use of interstitial ads, it is needed to request their load at some point inside the app, being recommended to do it as soon as possible. This can be done by using the following code:

```typescript
import { RNWortiseInterstitial } from '@wortise/react-native-sdk';

RNWortiseInterstitial.setAdUnitId('Wortise Ad Unit ID');
RNWortiseInterstitial.loadAd();
```

Next, to show the ad in the desired moment, you can use the `showAd()` and `isAvailable` methods just as shown in the following example:

```typescript
if (await RNWortiseInterstitial.isAvailable) {
    RNWortiseInterstitial.showAd();
}
```

## **Listener setup**

Some listeners can be added to receive the different events that may occur during the ad lifecycle. For this, it is needed to use the `addEventListener` method and specify which event type to receive, which can be one of the following:

* `onInterstitialClicked`
* `onInterstitialDismissed`
* `onInterstitialFailedToLoad`
* `onInterstitialFailedToShow`
* `onInterstitialImpression`
* `onInterstitialLoaded`
* `onInterstitialRevenuePaid`
* `onInterstitialShown`

### Example

```typescript
RNWortiseInterstitial.addEventListener('onInterstitialLoaded', () => {
  // The callback will be invoked when an ad is loaded
});
```


# Rewarded

## Integration

To make use of rewarded ads, it is needed to request their load at some point inside the app, being recommended to do it as soon as possible. This can be done by using the following code:

```typescript
import { RNWortiseRewarded } from '@wortise/react-native-sdk';

RNWortiseRewarded.setAdUnitId('Wortise Ad Unit ID');
RNWortiseRewarded.loadAd();
```

Next, to show the ad in the desired moment, you can use the `showAd()` and `isAvailable` methods just as shown in the following example:

```typescript
if (await RNWortiseRewarded.isAvailable) {
    RNWortiseRewarded.showAd();
}
```

## **Listener setup**

Some listeners can be added to receive the different events that may occur during the ad lifecycle. For this, it is needed to use the `addEventListener` method and specify which event type to receive, which can be one of the following:

* `onRewardedClicked`
* `onRewardedCompleted`
* `onRewardedDismissed`
* `onRewardedFailedToLoad`
* `onRewardedFailedToShow`
* `onRewardedImpression`
* `onRewardedLoaded`
* `onRewardedRevenuePaid`
* `onRewardedShown`

### Ejemplo

```typescript
RNWortiseRewarded.addEventListener('onRewardedCompleted', ({ amount, label, success }) => {
  // The callback will be invoked when the ad is completed
});

RNWortiseRewarded.addEventListener('onRewardedLoaded', () => {
  // The callback will be invoked when an ad is loaded
});
```


# Targeting

## Request permissions

{% hint style="info" %}
This step is **completely optional** and should only be implemented if it is convenient for the application’s purpose.
{% endhint %}

The app may request the location permissions so that our SDK can obtain the user's current location and display more relevant ads based on that information.

For this, it is necessary to add the following permissions in the `android/app/src/main/AndroidManifest.xml` file:

```markup
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
```

Following this, the app must request the permissions so that users can grant them, just as specified in React Native's [official documentation](https://reactnative.dev/docs/permissionsandroid).

### Example

```typescript
import { PermissionsAndroid } from 'react-native';

await PermissionsAndroid.requestMultiple([
  PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
  PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION
]);
```

abc




---

[Next Page](/llms-full.txt/1)

