### Durante el login/registro \{#during-loginsignup\}
Si identificas a los usuarios después del arranque de la app (por ejemplo, tras iniciar sesión o registrarse), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario antes**, Adapty pasará a trabajar con el perfil asociado a ese customer user ID.
:::important
Los customer user IDs deben ser únicos para cada usuario. Si escribes el valor del parámetro directamente en el código, todos los usuarios se considerarán como uno solo.
:::
Espera a que se ejecute el callback de finalización de `identify` antes de llamar a otros métodos del SDK. Las llamadas concurrentes pueden acabar en el perfil anónimo en lugar del identificado. Consulta [Orden de llamadas en el SDK de Android](android-sdk-call-order).
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo irregular que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante limpieza manual.
El SDK de Adapty almacena paywalls localmente en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN sea inaccesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede exceder ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
Para Android: puedes crear `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` es de `import com.adapty.utils.seconds`), o `TimeInterval.seconds(5)`. Para no establecer ningún límite, usa `TimeInterval.INFINITE`.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Un objeto [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) con una lista de IDs de productos, el identificador del paywall, Remote Config y otras propiedades. | ## Obtener la configuración de vista del paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el toggle **Show on device** en el Paywall Builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperar. ::: Después de obtener el paywall, comprueba si incluye una `ViewConfiguration`, lo que indica que fue creado con Paywall Builder. Esto te indicará cómo mostrar el paywall. Si la `ViewConfiguration` está presente, trátalo como un paywall de Paywall Builder; si no, [manéjalo como un paywall de Remote Config](present-remote-config-paywalls).opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo irregular que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante limpieza manual.
| ## Personalizar assets \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los assets personalizados. Las imágenes y vídeos hero tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de assets personalizado, apuntas a estos elementos por sus IDs y personalizas su comportamiento. Para otras imágenes y vídeos, necesitas [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta funcionalidad, actualiza el SDK de Android de Adapty a la versión 3.7.0 o superior. ::: Aquí tienes un ejemplo de cómo puedes proporcionar assets personalizados mediante un diccionario simple: ```kotlin showLineNumbers val customAssets = AdaptyCustomAssets.of( "hero_image" to AdaptyCustomImageAsset.remote( url = "https://example.com/image.jpg", preview = AdaptyCustomImageAsset.file( FileLocation.fromAsset("images/hero_image_preview.png"), ) ), "hero_video" to AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), ), ) val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, customAssets, ) ``` :::note Si un asset no se encuentra, el paywall volverá a su apariencia predeterminada. ::: --- # File: android-present-paywalls --- --- title: "Android - Presentar paywalls con el nuevo Paywall Builder" description: "Aprende a presentar paywalls en Android para una monetización efectiva." --- Si has personalizado un paywall con el Paywall Builder, no necesitas preocuparte por renderizarlo en el código de tu app para mostrárselo al usuario. Ese paywall ya contiene tanto lo que se muestra como la forma en que se muestra. :::warning Esta guía es solo para **paywalls del nuevo Paywall Builder** que requieren SDK v3.0. El proceso para mostrar paywalls es diferente según si fueron diseñados con versiones anteriores del Paywall Builder, si son paywalls con Remote Config, o si usas el [modo Observer](observer-vs-full-mode). - Para presentar **paywalls con Remote Config**, consulta [Renderizar paywalls diseñados con Remote Config](present-remote-config-paywalls). - Para presentar **paywalls en modo Observer**, consulta [Android - Presentar paywalls de Paywall Builder en modo Observer](android-present-paywall-builder-paywalls-in-observer-mode) ::: Para obtener el objeto `viewConfiguration` utilizado a continuación, consulta [Obtener paywalls de Paywall Builder y su configuración](android-get-pb-paywalls).Los insets son los espacios alrededor del paywall que evitan que los elementos interactivos queden ocultos detrás de las barras del sistema.
Por defecto: `UNSPECIFIED`, lo que significa que Adapty ajustará automáticamente los insets. Esto funciona bien para paywalls de borde a borde.
Si tu paywall no es de borde a borde, puede que quieras definir insets personalizados. Consulta la sección [Change paywall insets](android-present-paywalls#change-paywall-insets) más abajo para saber cómo hacerlo.
| | **personalizedOfferResolver** | opcional | Para indicar precios personalizados ([más información](https://developer.android.com/google/play/billing/integrate#personalized-price)), implementa `AdaptyUiPersonalizedOfferResolver` y proporciona tu propia lógica que mapee `AdaptyPaywallProduct` a `true` si el precio del producto es personalizado, o a `false` en caso contrario. | | **tagResolver** | opcional | Usa `AdaptyUiTagResolver` para resolver etiquetas personalizadas dentro del texto del paywall. Este resolver recibe un parámetro de etiqueta y lo resuelve a la cadena correspondiente. Consulta el tema [Custom tags in Paywall Builder](custom-tags-in-paywall-builder) para más detalles. | | **timerResolver** | opcional | Pasa el resolver aquí si vas a usar funcionalidad de temporizador personalizado. | :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: ## Cambiar los márgenes del paywall \{#change-paywall-insets\} Los márgenes son los espacios alrededor del paywall que evitan que los elementos interactivos queden ocultos detrás de las barras del sistema. Por defecto, Adapty ajusta automáticamente estos márgenes, lo que funciona perfectamente para paywalls de borde a borde. Si tu paywall no es de borde a borde, puede que quieras definir márgenes personalizados: - Si ni la barra de estado ni la barra de navegación se superponen con `AdaptyPaywallView`, usa `AdaptyPaywallInsets.NONE`. - Para configuraciones más personalizadas, como cuando tu paywall se superpone con la barra de estado superior pero no con la inferior, puedes establecer solo el `bottomInset` a `0`, como se muestra en el ejemplo a continuación:
## El número de vistas del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El contador de vistas del paywall muestra el doble del número esperado.
**Causa**: Es posible que estés llamando a `logShowPaywall` en tu código, lo que duplica el contador de vistas si estás usando el Paywall Builder. Para los paywalls diseñados con el Paywall Builder, las analíticas se registran automáticamente, por lo que no necesitas usar este método.
**Solución**: Asegúrate de no llamar a `logShowPaywall` en tu código si estás usando el Paywall Builder.
## Otros problemas \{#other-issues\}
**Problema**: Estás experimentando otros problemas relacionados con el Paywall Builder que no se tratan más arriba.
**Solución**: Migra el SDK a la versión más reciente usando las [guías de migración](android-sdk-migration-guides) si es necesario. Muchos problemas se resuelven en versiones más recientes del SDK.
---
# File: android-quickstart-manual
---
---
title: "Habilitar compras en tu paywall personalizado en Android SDK"
description: "Integra el SDK de Adapty en tus paywalls personalizados de Android para habilitar las compras in-app."
---
Esta guía describe cómo integrar Adapty en tus paywalls personalizados. Mantén el control total sobre la implementación del paywall, mientras el SDK de Adapty obtiene los productos, gestiona las nuevas compras y restaura las anteriores.
:::important
**Esta guía es para desarrolladores que implementan paywalls personalizados.** Si quieres la forma más sencilla de habilitar compras, usa el [Adapty Paywall Builder](android-quickstart-paywalls). Con Paywall Builder, creas paywalls en un editor visual sin código, Adapty gestiona toda la lógica de compras automáticamente y puedes probar distintos diseños sin volver a publicar tu app.
:::
## Antes de empezar \{#before-you-start\}
### Configurar productos \{#set-up-products\}
Para habilitar las compras in-app, necesitas entender tres conceptos clave:
- [**Productos**](product) – todo lo que los usuarios pueden comprar (suscripciones, consumibles, acceso de por vida)
- [**Paywalls**](paywalls) – configuraciones que definen qué productos ofrecer. En Adapty, los paywalls son la única forma de obtener productos, pero este diseño te permite modificar productos, precios y ofertas sin tocar el código de tu app.
- [**Placements**](placements) – dónde y cuándo muestras los paywalls en tu app (como `main`, `onboarding`, `settings`). Configuras los paywalls para los placements en el dashboard y luego los solicitas por ID de placement en tu código. Esto facilita ejecutar pruebas A/B y mostrar diferentes paywalls a distintos usuarios.
Asegúrate de entender estos conceptos aunque trabajes con tu paywall personalizado. Básicamente, son tu forma de gestionar los productos que vendes en tu app.
Para implementar tu paywall personalizado, necesitarás crear un **paywall** y añadirlo a un **placement**. Esta configuración te permite obtener tus productos. Para entender qué debes hacer en el dashboard, sigue la guía de inicio rápido [aquí](quickstart).
### Gestionar usuarios \{#manage-users\}
Puedes trabajar con o sin autenticación de backend en tu lado.
Sin embargo, el SDK de Adapty gestiona de forma diferente a los usuarios anónimos e identificados. Lee la [guía de inicio rápido de identificación](android-quickstart-identify) para entender las particularidades y asegurarte de trabajar correctamente con los usuarios.
## Paso 1. Obtener productos \{#step-1-get-products\}
Para obtener los productos de tu paywall personalizado, necesitas:
1. Obtener el objeto `paywall` pasando el ID del [placement](placements) al método `getPaywall`.
2. Obtener el array de productos para este paywall usando el método `getPaywallProducts`.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto de una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](android-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos utilizarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá los datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios puede que no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](android-use-fallback-paywalls). También usamos CDN para obtener paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera de este método. Si se alcanza el tiempo de espera, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede agotar el tiempo de espera un poco más tarde de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
| ¡No escribas los IDs de producto en el código! Como los paywalls se configuran de forma remota, los productos disponibles, el número de productos y las ofertas especiales (como pruebas gratuitas) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, tu app debería mostrar esos 2 productos. Sin embargo, si más adelante obtienes 3 productos, tu app debería mostrar los 3 sin necesidad de cambios en el código. Lo único que debes escribir directamente en el código es el ID del placement. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------- | | Paywall | Un objeto [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) con: una lista de IDs de producto, el identificador del paywall, Remote Config y varias otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tienes el paywall, puedes consultar el array de productos que le corresponde:opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto de una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](android-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos utilizarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá los datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios puede que no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
| --- # File: present-remote-config-paywalls-android --- --- title: "Renderizar un paywall diseñado con Remote Config en Android SDK" description: "Descubre cómo presentar paywalls de Remote Config en el SDK de Android de Adapty para personalizar la experiencia del usuario." --- Si has personalizado un paywall usando Remote Config, tendrás que implementar el renderizado en el código de tu app móvil para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú controlas qué se incluye y cómo se ve tu paywall. Te proporcionamos un método para obtener la configuración remota, dándote autonomía para mostrar tu paywall personalizado configurado mediante Remote Config. ## Obtener el Remote Config del paywall y presentarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores necesarios.Si la solicitud se realizó correctamente, la respuesta contiene este objeto. Un objeto [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) proporciona información completa sobre los niveles de acceso, suscripciones y compras no recurrentes de un usuario dentro de la app.
Comprueba el estado del nivel de acceso para determinar si el usuario tiene el acceso requerido a la app.
| :::warning **Nota:** si aún usas una versión de StoreKit de Apple inferior a v2.0 y una versión del SDK de Adapty inferior a v.2.9.0, debes proporcionar el [secreto compartido de App Store de Apple](app-store-connection-configuration#step-5-enter-app-store-shared-secret). Apple ha deprecado este método. ::: ## Cambiar la suscripción al realizar una compra \{#change-subscription-when-making-a-purchase\} Cuando un usuario elige una nueva suscripción en lugar de renovar la actual, el funcionamiento depende del store. En Google Play, la suscripción no se actualiza automáticamente. Tendrás que gestionar el cambio en el código de tu app tal como se describe a continuación. Para reemplazar una suscripción por otra en Android, llama al método `.makePurchase()` con el parámetro adicional:Un objeto [`AdaptyProfile`](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/). Este modelo contiene información sobre los niveles de acceso, suscripciones y compras únicas.
Comprueba el **estado del nivel de acceso** para determinar si el usuario tiene acceso a la app.
| :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: --- # File: implement-observer-mode-android --- --- title: "Implementar el modo Observer en el SDK de Android" description: "Implementa el modo Observer en Adapty para rastrear eventos de suscripción de usuarios en el SDK de Android." --- Si ya tienes tu propia infraestructura de compras y no estás listo para migrar completamente a Adapty, puedes explorar el [modo Observer](observer-vs-full-mode). En su forma básica, el modo Observer ofrece analíticas avanzadas e integración fluida con sistemas de atribución y analíticas. Si esto cubre tus necesidades, solo tienes que: 1. Activarlo al configurar el SDK de Adapty estableciendo el parámetro `observerMode` en `true`. Sigue las instrucciones de configuración para [Android](sdk-installation-android#activate-adapty-module-of-adapty-sdk). 2. [Reportar transacciones](report-transactions-observer-mode-android) desde tu infraestructura de compras existente a Adapty. ## Configuración del modo Observer \{#observer-mode-setup\} Activa el modo Observer si gestionas las compras y el estado de la suscripción por tu cuenta y usas Adapty para enviar eventos de suscripción y analíticas. :::important Cuando se ejecuta en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlas tú mismo. :::1. Implementa el `AdaptyUiObserverModeHandler`. El evento `onPurchaseInitiated` te informará de que el usuario ha iniciado una compra. Puedes activar tu flujo de compra personalizado en respuesta a este callback:
Para iOS, StoreKit 1: un objeto [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction).
Para iOS, StoreKit 2: objeto [Transaction](https://developer.apple.com/documentation/storekit/transaction).
Para Android: identificador de cadena (`purchase.getOrderId()`) de la compra, donde la compra es una instancia de la clase [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) de la biblioteca de facturación.
|Para iOS, StoreKit 1: un objeto [`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction).
Para iOS, StoreKit 2: un objeto [Transaction](https://developer.apple.com/documentation/storekit/transaction).
Para Android: el identificador de cadena (`purchase.getOrderId()`) de la compra, donde la compra es una instancia de la clase [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) de la biblioteca de facturación.
| Para el modo de pantalla completa, donde las barras del sistema se superponen a parte de tu UI, obtén los insets de la siguiente manera:phoneNumber
firstName
lastName
| String | | gender | Enum, los valores permitidos son: `female`, `male`, `other` | | birthday | Date | ### Atributos personalizados de usuario \{#custom-user-attributes\} Puedes definir tus propios atributos personalizados, que normalmente están relacionados con el uso de tu app. Por ejemplo, en aplicaciones de fitness pueden ser el número de ejercicios por semana; en apps de aprendizaje de idiomas, el nivel de conocimiento del usuario, etc. Puedes usarlos en segmentos para crear paywalls y ofertas segmentadas, y también en analíticas para identificar qué métricas de producto influyen más en los ingresos.Un objeto [AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/). En general, solo necesitas comprobar el estado del nivel de acceso del perfil para determinar si el usuario tiene acceso premium a la app.
El método `.getProfile` devuelve el resultado más actualizado posible, ya que siempre intenta consultar la API. Si por algún motivo (p. ej., sin conexión a internet) el SDK de Adapty no puede obtener información del servidor, se devolverán los datos de la caché. También es importante tener en cuenta que el SDK de Adapty actualiza la caché de `AdaptyProfile` con regularidad para mantener esta información lo más actualizada posible.
| El método `.getProfile()` te proporciona el perfil del usuario, a partir del cual puedes obtener el estado del nivel de acceso. Puedes tener varios niveles de acceso por app. Por ejemplo, si tienes una app de periódico y vendes suscripciones a distintos temas de forma independiente, puedes crear los niveles de acceso "sports" y "science". Sin embargo, la mayoría de las veces solo necesitarás un nivel de acceso; en ese caso, puedes utilizar simplemente el nivel de acceso "premium" predeterminado. A continuación se muestra un ejemplo para comprobar el nivel de acceso "premium" predeterminado:opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés; `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios puede que no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra al desinstalarla o mediante limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no esté disponible. Este sistema está diseñado para asegurarse de que siempre obtengas la versión más reciente de tus onboardings garantizando la fiabilidad incluso cuando la conexión a internet es limitada.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera de este método. Si se alcanza el timeout, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede estar compuesta por diferentes solicitudes internamente.
Para Android: puedes crear `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` es de `import com.adapty.utils.seconds`), o `TimeInterval.seconds(5)`. Para no establecer ningún límite, usa `TimeInterval.INFINITE`.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Un objeto [`AdaptyOnboarding`](https://android.adapty.io/adapty/com.adapty.models/-adapty-onboarding/) con: el identificador y la configuración del onboarding, Remote Config y varias otras propiedades. | ## Acelerar la obtención del onboarding con el onboarding de la audiencia predeterminada \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Normalmente, los onboardings se obtienen casi al instante, por lo que no tienes que preocuparte por acelerar este proceso. Sin embargo, cuando tienes muchas audiencias y onboardings y tus usuarios tienen una conexión a internet débil, obtener un onboarding puede tardar más de lo deseable. En esas situaciones, puede que quieras mostrar un onboarding por defecto para garantizar una experiencia fluida en lugar de no mostrar ninguno. Para abordar esto, puedes usar el método `getOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, tal como se detalla en la sección [Obtener onboarding](#fetch-onboarding) anterior. :::warning Considera usar `getOnboarding` en lugar de `getOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: puede crear problemas al dar soporte a múltiples versiones de la app, lo que requiere diseños compatibles con versiones anteriores o asumir que las versiones más antiguas podrían mostrarse incorrectamente. - **Sin personalización**: solo muestra contenido para la audiencia "All Users", eliminando la segmentación por país, atribución o atributos personalizados. Si la mayor velocidad de obtención compensa estos inconvenientes para tu caso de uso, utiliza `getOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getOnboarding` como se describe [arriba](#fetch-onboarding). ::: ```kotlin Adapty.getOnboardingForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val onboarding = result.value // Handle successful onboarding retrieval } is AdaptyResult.Error -> { val error = result.error // Handle error case } } } ``` Parámetros: | Parámetro | Presencia | Descripción | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés; `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios puede que no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra al desinstalarla o mediante limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no esté disponible. Este sistema está diseñado para asegurarse de que siempre obtengas la versión más reciente de tus onboardings garantizando la fiabilidad incluso cuando la conexión a internet es limitada.
| --- # File: android-present-onboardings --- --- title: "Presentar onboardings en Android SDK" description: "Aprende cómo presentar onboardings en Android para una interacción efectiva con el usuario." --- Antes de comenzar, asegúrate de que: 1. Has instalado el [SDK de Adapty para Android](sdk-installation-android) 3.8.0 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). Si has personalizado un onboarding con el Onboarding Builder, no necesitas preocuparte por renderizarlo en el código de tu app móvil para mostrárselo al usuario. Ese onboarding ya contiene tanto qué mostrar como cómo mostrarlo. Para mostrar el onboarding visual en la pantalla del dispositivo, primero debes configurarlo. Para ello, llama al método `AdaptyUI.getOnboardingView()` o crea el `OnboardingView` directamente:
Por ejemplo, si un usuario toca un botón personalizado como **Login** o **Allow notifications**, se activará el método delegado `onCustomAction` con el ID de acción definido en el builder. Puedes crear tus propios IDs, como "allowNotifications".
```kotlin showLineNumbers
class YourActivity : AppCompatActivity() {
private val eventListener = object : AdaptyOnboardingEventListener {
override fun onCustomAction(action: AdaptyOnboardingCustomAction, context: Context) {
when (action.actionId) {
"allowNotifications" -> {
// Request notification permissions
}
}
}
override fun onError(error: AdaptyOnboardingError, context: Context) {
// Handle errors
}
// ... other required delegate methods
}
}
```
El JSON del paywall de respaldo local no es válido.
Corrige tu paywall en inglés predeterminado y luego reemplaza los paywalls locales no válidos. Consulta el tema [Personalizar el paywall con Remote Config](customize-paywall-with-remote-config) para saber cómo corregir un paywall, y [Definir paywalls de respaldo locales](fallback-paywalls) para saber cómo reemplazar los paywalls locales.
| |CURRENT_SUBSCRIPTION_TO_UPDATE
\_NOT_FOUND_IN_HISTORY
| La suscripción original que debe reemplazarse no se encontró en las suscripciones activas. | | [BILLING_SERVICE_TIMEOUT](https://developer.android.com/google/play/billing/errors#service_timeout_error_code_-3) | Este error indica que la solicitud alcanzó el tiempo de espera máximo antes de que Google Play pudiera responder. Puede deberse, por ejemplo, a un retraso en la ejecución de la acción solicitada por la llamada a la Play Billing Library. | | [FEATURE_NOT_SUPPORTED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#FEATURE_NOT_SUPPORTED()) | La función solicitada no es compatible con la Play Store en el dispositivo actual. | | [BILLING_SERVICE_DISCONNECTED](https://developer.android.com/google/play/billing/errors#service_disconnected_error_code_-1) | Este error indica que la conexión de la app cliente con el servicio de Google Play Store a través del `BillingClient` se ha interrumpido. | | [BILLING_SERVICE_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#service_unavailable_error_code_2) | Este error indica que el servicio de facturación de Google Play no está disponible en este momento. En la mayoría de los casos significa que hay un problema de conexión de red entre el dispositivo cliente y los servicios de Google Play Billing. | | [BILLING_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) |Este error indica que ocurrió un problema de facturación durante el proceso de compra. Las posibles causas son:
1. La app de Play Store en el dispositivo del usuario no está instalada o está desactualizada.
2. El usuario se encuentra en un país no compatible.
3. El usuario forma parte de una cuenta empresarial cuyo administrador ha desactivado las compras.
4. Google Play no pudo cargar el método de pago del usuario (por ejemplo, una tarjeta de crédito caducada).
5. El usuario no ha iniciado sesión en la app de Play Store.
| | [DEVELOPER_ERROR](https://developer.android.com/google/play/billing/errors#developer_error) | Este error indica que estás usando una API de forma incorrecta. | | [BILLING_ERROR](https://developer.android.com/google/play/billing/errors#error_error_code_6) | Este error indica un problema interno del propio Google Play. | | [ITEM_ALREADY_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_ALREADY_OWNED()) | El producto ya fue comprado anteriormente. | | [ITEM_NOT_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_NOT_OWNED()) | Este error indica que la acción solicitada sobre el ítem falló porque el usuario no es su propietario. | | [BILLING_NETWORK_ERROR](https://developer.android.com/google/play/billing/errors#network_error_error_code_12) | Este error indica que hubo un problema con la conexión de red entre el dispositivo y los sistemas de Play. | | NO_PRODUCT_IDS_FOUND |Este error indica que ninguno de los productos del paywall está disponible en el store.
Si encuentras este error, sigue los pasos a continuación para resolverlo:
Si el código expira antes de que autorices, o si haces clic en **Deny**, ejecuta el siguiente comando de nuevo para reiniciar el proceso:
```bash
adapty auth login
```
## Gestionar la autenticación \{#manage-authentication\}
### Comprobar el estado de autenticación \{#check-authentication-status\}
Para ver tu estado de autenticación actual, ejecuta:
```bash
adapty auth status
```
Cuando estás autenticado, la salida muestra tu correo electrónico, un prefijo de token enmascarado y la ruta al archivo de configuración local:
```
Email: you@example.com
Token: abcd1234****
Config: ~/.config/adapty/config.json
```
Cuando no estás autenticado:
```
Not authenticated. Run `adapty auth login`.
```
### Verificar tu token \{#verify-your-token\}
Para confirmar que tu token es válido y ver los detalles de tu cuenta, ejecuta:
```bash
adapty auth whoami
```
A diferencia de `adapty auth status`, este comando realiza una solicitud en tiempo real al servidor para verificar el token.
### Cerrar sesión \{#log-out\}
Para eliminar tus credenciales almacenadas localmente, ejecuta:
```bash
adapty auth logout
```
Esto borra `~/.config/adapty/config.json`. El token sigue siendo válido en el servidor hasta que expira; si necesitas invalidarlo de inmediato, usa `adapty auth revoke` en su lugar.
### Revocar tu token \{#revoke-your-token\}
Para invalidar el token en el servidor y eliminarlo localmente, ejecuta:
```bash
adapty auth revoke
```
Úsalo cuando quieras invalidar un token por completo, por ejemplo, si crees que tus credenciales pueden haberse visto comprometidas. Tras revocarlo, ejecuta `adapty auth login` para volver a autenticarte.
## Errores de token \{#token-errors\}
Si un token se revoca o deja de ser válido, los comandos del CLI devuelven un error 401. Para volver a autenticarte, ejecuta:
```bash
adapty auth login
```
---
# File: developer-cli-reference
---
---
title: "Referencia completa de la CLI para desarrolladores de Adapty"
description: "Referencia completa de todos los comandos de la CLI para desarrolladores de Adapty."
---
:::link
¿Usas un asistente de IA? Hay disponible una [skill de Adapty CLI](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) para ayudar a los LLMs a trabajar con la CLI.
:::
Este artículo lista todos los comandos de la CLI de Adapty con sus argumentos, flags y valores aceptados.
:::link
Para configurar la autenticación y gestionar tokens, consulta [Autenticación](developer-cli-authentication).
:::
## Flags globales \{#global-flags\}
Estos flags están disponibles en todos los comandos.
| Flag | Descripción |
|---|---|
| `--json` | Mostrar la salida en JSON en lugar de texto formateado |
| `--help` | Mostrar la ayuda del comando |
Todos los comandos `list` también aceptan flags de paginación:
| Flag | Por defecto | Descripción |
|---|---|---|
| `--page` | `1` | Número de página |
| `--page-size` | `20` | Elementos por página (máx.: 100) |
## Apps \{#apps\}
Gestiona las apps de tu cuenta de Adapty. Para la configuración desde el dashboard, consulta [App settings](general).
### adapty apps list \{#adapty-apps-list\}
Lista todas las apps de tu cuenta de Adapty.
```bash
adapty apps list
```
Acepta [flags de paginación](#global-flags).
### adapty apps get \{#adapty-apps-get\}
Obtén los detalles de una app específica.
```bash
adapty apps get
:::note Para hacer seguimiento de eventos de suscripción, usa la integración de [Webhook](webhook) en Adapty o intégralo directamente con tu servicio existente. ::: ## Caso 1: Sincronizar suscriptores entre web y móvil \{#case-1-sync-subscribers-between-web-and-mobile\} Si usas proveedores de pago web como Stripe, ChargeBee u otros, puedes sincronizar tus suscriptores fácilmente. Así es cómo: 1.
El ID de perfil de Adapty del usuario. Visible en el campo **Adapty ID** en [Adapty Dashboard -> **Profiles**](https://app.adapty.io/profiles/users) -> página del perfil específico.
Es intercambiable con **adapty-customer-user-id**; usa cualquiera de los dos.
| | **adapty-customer-user-id** |El ID del usuario en tu sistema. Visible en el campo **Customer user ID** en [Adapty Dashboard -> **Profiles**](https://app.adapty.io/profiles/users) -> página del perfil específico.
Es intercambiable con **adapty-profile-id**; usa cualquiera de los dos.
⚠️ Solo funciona si
### Durante el inicio/registro de sesión \{#during-loginsignup\}
Si identificas a los usuarios después de que la app se inicie (por ejemplo, tras iniciar sesión o registrarse), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario antes**, Adapty cambiará a trabajar con el perfil asociado a ese customer user ID.
:::tip
Al crear un customer user ID, guárdalo junto con los datos de tu usuario para poder enviar el mismo ID cuando inicie sesión desde nuevos dispositivos o reinstale tu app.
:::
Siempre usa `await` con `identify` antes de llamar a otros métodos del SDK. Las llamadas concurrentes producen `#3006 profileWasChanged` o recaen en el perfil anónimo. Consulta [Orden de llamadas en el SDK de Capacitor](capacitor-sdk-call-order).
```typescript showLineNumbers
try {
await adapty.identify({ customerUserId: "YOUR_USER_ID" });
// successfully identified
} catch (error) {
// handle the error
}
```
### Durante la activación del SDK \{#during-the-sdk-activation\}
Si ya conoces el customer user ID cuando activas el SDK, puedes enviarlo en el método `activate` en lugar de llamar a `identify` por separado.
Si conoces el customer user ID pero lo estableces solo después de la activación, eso significa que, al activarse, Adapty creará un nuevo perfil vacío y cambiará al existente únicamente cuando llames a `identify`.
Puedes pasar un customer user ID existente (uno que hayas usado antes) o uno nuevo. Si pasas uno nuevo, el nuevo perfil creado en la activación se vinculará automáticamente al customer user ID.
:::tip
Para excluir los perfiles vacíos creados de las [analíticas](analytics-charts) del dashboard, ve a **App settings** y configura [**Installs definition for analytics**](general#4-installs-definition-for-analytics).
:::
```typescript showLineNumbers
await adapty.activate({
apiKey: "YOUR_PUBLIC_SDK_KEY",
params: {
customerUserId: "YOUR_USER_ID"
}
});
```
### Cerrar sesión de usuarios \{#log-users-out\}
Si tienes un botón para cerrar la sesión de los usuarios, usa el método `logout`. Esto crea un nuevo ID de perfil anónimo para el usuario.
```typescript showLineNumbers
try {
await adapty.logout();
// successful logout
} catch (error) {
// handle the error
}
```
:::info
Para volver a iniciar sesión en la app, usa el método `identify`.
:::
### Permitir compras sin inicio de sesión \{#allow-purchases-without-login\}
Si tus usuarios pueden realizar compras tanto antes como después de iniciar sesión en tu app, no necesitas realizar ninguna configuración adicional:
Así es como funciona:
1. Cuando un usuario sin sesión iniciada realiza una compra, Adapty la asocia a su ID de perfil anónimo.
2. Cuando el usuario inicia sesión en su cuenta, Adapty cambia a trabajar con su perfil identificado.
- Si es un customer user ID existente (el customer user ID ya está vinculado a un perfil), Adapty sincroniza sus transacciones automáticamente.
- Si es un customer user ID nuevo (por ejemplo, la compra se realizó antes del registro), Adapty asigna el customer user ID al perfil actual, por lo que se mantiene todo el historial de compras.
---
# File: adapty-cursor-capacitor
---
---
title: "Integra Adapty en tu app de Capacitor con ayuda de IA"
description: "Una guía paso a paso para integrar Adapty en tu app de Capacitor usando Cursor, Context7, ChatGPT, Claude u otras herramientas de IA."
---
Esta página cubre dos formas de integrar Adapty en tu app de Capacitor. Usa la skill de integración del SDK para un flujo automatizado de principio a fin, o sigue el recorrido manual más abajo.
## Usa la skill de integración del SDK (beta) \{#use-the-sdk-integration-skill-beta\}
La [skill adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza toda la integración: configuración del dashboard, instalación del SDK, paywall y verificación en cada etapa. El recorrido manual más abajo es la alternativa si tu herramienta no admite el formato Claude Skills.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
### Instalar \{#install\}
Elige el formato para tu herramienta. La lista completa está en el [README de la skill](https://github.com/adaptyteam/adapty-sdk-integration-skill).
- **Claude Code**: Ejecuta `claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill` y luego `claude plugin install adapty-sdk-integration@adapty` desde tu terminal.
- **GitHub Copilot CLI**: Ejecuta `gh skill install adaptyteam/adapty-sdk-integration-skill`.
- **Gemini CLI**: Ejecuta `gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill`.
- **OpenAI Codex u otra herramienta**: Clona el repositorio y copia `plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` en el directorio de skills de tu herramienta.
### Ejecutar \{#run\}
En tu proyecto, ejecuta `/adapty-sdk-integration`. La skill detecta tu plataforma y hace algunas preguntas de configuración. Después recorre la configuración del dashboard, la instalación del SDK, el paywall y la verificación, obteniendo la documentación relevante de Adapty en cada etapa.
:::note
La skill está en beta. Si se detiene o se comporta de forma inesperada, el recorrido manual a continuación cubre cada etapa paso a paso.
:::
## Antes de empezar: configuración del dashboard \{#before-you-start-dashboard-setup\}
Adapty requiere cierta configuración en el dashboard antes de escribir cualquier código del SDK. Puedes hacerlo con una skill interactiva de LLM o manualmente desde el Dashboard.
### Enfoque con skill (recomendado) \{#skill-approach-recommended\}
La skill de Adapty CLI permite que tu LLM configure tu app, productos, niveles de acceso, paywalls y placements directamente, sin tener que abrir el Dashboard en cada paso. Solo necesitas [conectar tus stores](integrate-payments) en el Dashboard.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Una vez añadida la skill, ejecuta `/adapty-cli` en tu agente. Te guiará por cada paso, incluyendo cuándo abrir el Dashboard para conectar tus stores.
### Enfoque manual con el Dashboard \{#dashboard-approach\}
Si prefieres configurarlo todo manualmente, esto es lo que necesitas antes de escribir código. Tu LLM no puede buscar los valores del dashboard por ti — tendrás que proporcionárselos.
1. **Conecta tus stores**: En el Adapty Dashboard, ve a **App settings → General**. Conecta tanto App Store como Google Play si tu app de Capacitor apunta a ambas plataformas. Esto es obligatorio para que funcionen las compras.
[Conectar stores](integrate-payments)
2. **Copia tu Public SDK key**: En el Adapty Dashboard, ve a **App settings → General** y busca la sección **API keys**. En el código, es la cadena que pasas a `adapty.activate()`.
3. **Crea al menos un producto**: En el Adapty Dashboard, ve a la página **Products**. No referenciarás los productos directamente en el código — Adapty los entrega a través de paywalls.
[Añadir productos](quickstart-products)
4. **Crea un paywall y un placement**: En el Adapty Dashboard, crea un paywall en la página **Paywalls** y asígnalo a un placement en la página **Placements**. En el código, el ID del placement es la cadena que pasas a `adapty.getPaywall()`.
[Crear paywall](quickstart-paywalls)
5. **Configura los niveles de acceso**: En el Adapty Dashboard, configúralos por producto en la página **Products**. En el código, la cadena que se verifica es `profile.accessLevels['premium']?.isActive`. El nivel de acceso `premium` predeterminado funciona para la mayoría de las apps. Si los usuarios de pago acceden a funciones distintas según el producto (por ejemplo, un plan `basic` vs. un plan `pro`), [crea niveles de acceso adicionales](assigning-access-level-to-a-product) antes de empezar a programar.
:::tip
Una vez que tengas los cinco, estás listo para escribir código. Dile a tu LLM: "Mi Public SDK key es X, mi placement ID es Y" para que pueda generar el código correcto de inicialización y obtención de paywalls.
:::
### Configura cuando estés listo \{#set-up-when-ready\}
Estos pasos no son necesarios para empezar a programar, pero los necesitarás a medida que tu integración madure:
- **Pruebas A/B**: Configúralas en la página **Placements**. No se necesita ningún cambio en el código.
[Pruebas A/B](ab-tests)
- **Paywalls y placements adicionales**: Añade más llamadas a `getPaywall` con diferentes IDs de placement.
- **Integraciones de analíticas**: Configúralas en la página **Integrations**. La configuración varía según la integración. Consulta [integraciones de analíticas](analytics-integration) e [integraciones de atribución](attribution-integration).
## Proporciona la documentación de Adapty a tu LLM \{#feed-adapty-docs-to-your-llm\}
### Usa Context7 (recomendado) \{#use-context7-recommended\}
[Context7](https://context7.com) es un servidor MCP que da a tu LLM acceso directo a la documentación actualizada de Adapty. Tu LLM obtiene los documentos adecuados automáticamente según lo que le preguntes — sin necesidad de pegar URLs manualmente.
Context7 funciona con **Cursor**, **Claude Code**, **Windsurf** y otras herramientas compatibles con MCP. Para configurarlo, ejecuta:
```
npx ctx7 setup
```
Esto detecta tu editor y configura el servidor de Context7. Para la configuración manual, consulta el [repositorio de Context7 en GitHub](https://github.com/upstash/context7).
Una vez configurado, referencia la librería de Adapty en tus prompts:
```
Use the adaptyteam/adapty-docs library to look up how to install the Capacitor SDK
```
:::warning
Aunque Context7 elimina la necesidad de pegar links de documentación manualmente, el orden de implementación es importante. Sigue el [recorrido de implementación](#implementation-walkthrough) paso a paso para asegurarte de que todo funcione.
:::
### Usa documentación en texto plano \{#use-plain-text-docs\}
Puedes acceder a cualquier documento de Adapty como Markdown en texto plano. Añade `.md` al final de su URL, o haz clic en **Copy for LLM** bajo el título del artículo. Por ejemplo: [adapty-cursor-capacitor.md](https://adapty.io/docs/es/adapty-cursor-capacitor.md).
Cada etapa del [recorrido de implementación](#implementation-walkthrough) incluye un bloque "Envía esto a tu LLM" con links `.md` para pegar.
Para acceder a más documentación a la vez, consulta los [archivos de índice y subconjuntos por plataforma](#plain-text-doc-index-files) más abajo.
## Recorrido de implementación \{#implementation-walkthrough\}
El resto de esta guía recorre la integración de Adapty en orden de implementación. Cada etapa incluye los documentos que debes enviar a tu LLM, lo que deberías ver cuando esté listo y los problemas más comunes.
### Planifica tu integración \{#plan-your-integration\}
Antes de ponerte a escribir código, pide a tu LLM que analice tu proyecto y cree un plan de implementación. Si tu herramienta de IA admite un modo de planificación (como el de Cursor o el de Claude Code), úsalo para que el LLM pueda leer tanto la estructura de tu proyecto como la documentación de Adapty antes de escribir cualquier código.
Dile a tu LLM qué enfoque usas para las compras — esto afecta a las guías que debe seguir:
- [**Adapty Paywall Builder**](adapty-paywall-builder): Creas paywalls en el editor sin código de Adapty y el SDK los renderiza automáticamente.
- [**Paywalls creados manualmente**](capacitor-making-purchases): Construyes tu propia UI de paywall en código, pero sigues usando Adapty para obtener productos y gestionar compras.
- [**Modo Observer**](observer-vs-full-mode): Mantienes tu infraestructura de compras existente y usas Adapty solo para analíticas e integraciones.
¿No sabes cuál elegir? Lee la [tabla comparativa en el quickstart](capacitor-quickstart-paywalls).
### Instala y configura el SDK \{#install-and-configure-the-sdk\}
Añade la dependencia del SDK de Adapty usando npm y actívalo con tu Public SDK key. Esto es la base — sin ello nada más funciona.
**Guía:** [Instalar y configurar el SDK de Adapty](sdk-installation-capacitor)
Envía esto a tu LLM:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/es/sdk-installation-capacitor.md
```
:::tip[Punto de control]
- **Esperado:** La app se compila y ejecuta tanto en iOS como en Android. La consola muestra el log de activación de Adapty.
- **Truco:** "Public API key is missing" → comprueba que hayas reemplazado el placeholder con tu clave real de App settings.
:::
### Muestra paywalls y gestiona compras \{#show-paywalls-and-handle-purchases\}
Obtén un paywall por ID de placement, muéstralo y gestiona los eventos de compra. Las guías que necesitas dependen de cómo gestionas las compras.
Prueba cada compra en el sandbox mientras avanzas — no esperes al final. Consulta [Probar compras en sandbox](test-purchases-in-sandbox) para las instrucciones de configuración.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto de uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma, la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **params** | opcional | Parámetros adicionales para obtener el paywall. | **No escribas IDs de productos en el código.** El único ID que debes escribir directamente en el código es el ID del placement. Los paywalls se configuran de forma remota, por lo que el número de productos y las ofertas disponibles pueden cambiar en cualquier momento. Tu app debe gestionar estos cambios de forma dinámica: si hoy un paywall devuelve dos productos y mañana tres, muéstralos todos sin necesidad de modificar el código. Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Un objeto [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) con una lista de IDs de productos, el identificador del paywall, el Remote Config y otras propiedades. | ## Obtener la configuración de vista del paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el botón **Show on device** en el Paywall Builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperar. ::: Después de obtener el paywall, comprueba si incluye un `ViewConfiguration`, lo que indica que fue creado con Paywall Builder. Esto te orientará sobre cómo mostrar el paywall. Si el `ViewConfiguration` está presente, trátalo como un paywall de Paywall Builder; si no lo está, [trátalo como un paywall de Remote Config](present-remote-config-paywalls-capacitor). En el SDK de Capacitor, llama directamente al método `createPaywallView` sin necesidad de obtener primero la configuración de vista manualmente. :::warning El resultado del método `createPaywallView` solo puede usarse una vez. Si necesitas usarlo de nuevo, vuelve a llamar al método `createPaywallView`. ::: ```typescript showLineNumbers if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { // use your custom logic } ``` Parámetros: | Parámetro | Presencia | Descripción | | :------------------- | :------- | :----------------------------------------------------------- | | **paywall** | obligatorio | Un objeto `AdaptyPaywall` para obtener un controlador del paywall deseado. | | **customTags** | opcional | Define un diccionario de etiquetas personalizadas y sus valores resueltos. Las etiquetas personalizadas actúan como marcadores de posición en el contenido del paywall y se sustituyen dinámicamente por cadenas específicas para personalizar el contenido. Consulta el tema [Etiquetas personalizadas en el Paywall Builder](custom-tags-in-paywall-builder) para más detalles. | | **prefetchProducts** | opcional | Actívalo para optimizar el momento de visualización de los productos en pantalla. Cuando es `true`, AdaptyUI obtiene automáticamente los productos necesarios. Por defecto: `false`. | :::note Si usas varios idiomas, aprende a añadir una [localización en Paywall Builder](add-paywall-locale-in-adapty-paywall-builder) y cómo usar correctamente los códigos de idioma [aquí](capacitor-localizations-and-locale-codes). ::: Una vez que tengas la vista, [presenta el paywall](capacitor-present-paywalls). ## Obtener un paywall para la audiencia predeterminada y recuperarlo más rápido \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Por lo general, los paywalls se obtienen casi de forma instantánea, por lo que no necesitas preocuparte por agilizar este proceso. Sin embargo, si tienes muchas audiencias y paywalls, y tus usuarios tienen una conexión a internet débil, obtener un paywall puede tardar más de lo deseado. En esas situaciones, puede que quieras mostrar un paywall predeterminado para garantizar una experiencia fluida al usuario en lugar de no mostrar ningún paywall. Para resolver esto, puedes usar el método `getPaywallForDefaultAudience`, que obtiene el paywall del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el paywall con el método `getPaywall`, tal como se detalla en la sección [Obtener el paywall](#fetch-paywall-designed-with-paywall-builder) anterior. :::warning Por qué recomendamos usar `getPaywall` El método `getPaywallForDefaultAudience` tiene algunos inconvenientes importantes: - **Posibles problemas de compatibilidad con versiones anteriores**: Si necesitas mostrar paywalls diferentes para distintas versiones de la app (actual y futuras), tendrás que diseñar paywalls que sean compatibles con la versión actual (heredada) o asumir que los usuarios con esa versión podrían encontrarse con paywalls que no se renderizan correctamente. - **Pérdida de segmentación**: Todos los usuarios verán el mismo paywall diseñado para la audiencia **All Users**, lo que significa que pierdes la segmentación personalizada (incluida la basada en países, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a aceptar estos inconvenientes para beneficiarte de una obtención más rápida del paywall, usa el método `getPaywallForDefaultAudience` como se indica a continuación. De lo contrario, usa `getPaywall` como se describe [arriba](#fetch-paywall-designed-with-paywall-builder). ::: ```typescript showLineNumbers try { const paywall = await adapty.getPaywallForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', }); // the requested paywall } catch (error) { // handle the error } ``` :::note El método `getPaywallForDefaultAudience` está disponible a partir de la versión 2.11.2 del SDK de Capacitor. ::: | Parámetro | Presencia | Descripción | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements). Es el valor que especificaste al crear un placement en tu Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto de una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma, la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](capacitor-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **params** | opcional | Parámetros adicionales para obtener el paywall. | ## Personalizar recursos \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los recursos personalizados. Las imágenes y vídeos principales tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de recursos personalizados, seleccionas estos elementos por sus IDs y personalizas su comportamiento. Para otras imágenes y vídeos, debes [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta función, actualiza el SDK de Capacitor de Adapty a la versión 3.8.0 o superior. ::: Aquí tienes un ejemplo de cómo puedes proporcionar recursos personalizados mediante un diccionario sencillo: ```typescript showLineNumbers const customAssets: Recordopcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](capacitor-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **params.fetchPolicy** |opcional
por defecto: `'reload_revalidating_cache_data'`
|Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `'return_cache_data_else_load'` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante limpieza manual.
| | **params.loadTimeoutMs** |opcional
por defecto: 5000 ms
|Este valor limita el tiempo de espera (en milisegundos) para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeoutMs`, ya que la operación puede consistir en diferentes solicitudes internamente.
| **No escribas los IDs de productos directamente en el código.** El único ID que debes incluir en el código es el del placement. Los paywalls se configuran de forma remota, por lo que el número de productos y las ofertas disponibles pueden cambiar en cualquier momento. Tu app debe gestionar estos cambios de forma dinámica: si hoy un paywall devuelve dos productos y mañana tres, muéstralos todos sin modificar el código. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) con: una lista de IDs de productos, el identificador del paywall, Remote Config y otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tienes el paywall, puedes consultar el array de productos que le corresponde: ```typescript showLineNumbers try { const products = await adapty.getPaywallProducts({ paywall }); // the requested products list } catch (error) { console.error('Failed to fetch products:', error); } ``` Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Lista de objetos [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) con: identificador del producto, nombre, precio, moneda, duración de la suscripción y otras propiedades. | Al implementar tu propio diseño de paywall, probablemente necesitarás acceder a estas propiedades del objeto [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct). A continuación se muestran las propiedades más utilizadas, pero consulta el documento enlazado para ver todos los detalles disponibles. | Propiedad | Descripción | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Título** | Para mostrar el título del producto, usa `product.localizedTitle`. Ten en cuenta que la localización se basa en el país de la store seleccionado por el usuario, no en el idioma del dispositivo. | | **Precio** | Para mostrar el precio localizado, usa `product.price?.localizedString`. Esta localización se basa en la configuración regional del dispositivo. También puedes acceder al precio como número con `product.price?.amount`. El valor se proporcionará en la moneda local. Para obtener el símbolo de moneda correspondiente, usa `product.price?.currencySymbol`. | | **Período de suscripción** | Para mostrar el período (p. ej., semana, mes, año, etc.), usa `product.subscription?.localizedSubscriptionPeriod`. Esta localización se basa en el idioma del dispositivo. Para obtener el período de suscripción de forma programática, usa `product.subscription?.subscriptionPeriod`. Desde ahí puedes acceder a la propiedad `unit` para obtener la duración (es decir, `'day'`, `'week'`, `'month'`, `'year'` o `'unknown'`). El valor `numberOfUnits` te dará el número de unidades del período. Por ejemplo, para una suscripción trimestral verías `'month'` en la propiedad unit y `3` en numberOfUnits. | | **Oferta introductoria** | Para mostrar una insignia u otro indicador de que una suscripción incluye una oferta introductoria, revisa la propiedad `product.subscription?.offer?.phases`. Esta es una lista que puede contener hasta dos fases de descuento: la fase de prueba gratuita y la fase de precio introductorio. Dentro de cada objeto de fase están las siguientes propiedades útiles:opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](capacitor-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **params.fetchPolicy** |opcional
por defecto: `'reload_revalidating_cache_data'`
|Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `'return_cache_data_else_load'` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante limpieza manual.
| --- # File: present-remote-config-paywalls-capacitor --- --- title: "Renderizar un paywall diseñado con Remote Config en Capacitor SDK" description: "Descubre cómo presentar paywalls de Remote Config en el SDK de Adapty para Capacitor y personalizar la experiencia del usuario." --- Si has personalizado un paywall usando Remote Config, tendrás que implementar el renderizado en el código de tu app para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú decides qué se incluye y cómo se ve tu paywall. Proporcionamos un método para obtener la configuración remota y así puedas mostrar tu paywall personalizado configurado mediante Remote Config. ## Obtener el Remote Config del paywall y presentarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores que necesites. ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', params: { fetchPolicy: 'reload_revalidating_cache_data', // Load from server, fallback to cache loadTimeoutMs: 5000 // 5 second timeout } }); const headerText = paywall.remoteConfig?.data?.['header_text']; } catch (error) { console.error('Failed to fetch paywall:', error); } ``` En este punto, una vez que hayas recibido todos los valores necesarios, es momento de renderizarlos y componerlos en una página visualmente atractiva. Asegúrate de que el diseño se adapte a distintas pantallas y orientaciones de dispositivos móviles, ofreciendo una experiencia fluida y agradable en todos ellos. :::warning Asegúrate de [registrar el evento de visualización del paywall](present-remote-config-paywalls-capacitor#track-paywall-view-events) tal como se describe a continuación, para que los análisis de Adapty puedan capturar información para los embudos y las pruebas A/B. ::: Cuando termines de mostrar el paywall, continúa configurando el flujo de compra. Cuando el usuario realice una compra, simplemente llama a `.makePurchase()` con el producto de tu paywall. Para más detalles sobre el método `.makePurchase()`, consulta [Realizar compras](capacitor-making-purchases). Te recomendamos [crear un paywall de respaldo](capacitor-use-fallback-paywalls). Este paywall de respaldo se mostrará al usuario cuando no haya conexión a internet ni caché disponible, garantizando una experiencia fluida incluso en esas situaciones. ## Registrar eventos de visualización del paywall \{#track-paywall-view-events\} Adapty te ayuda a medir el rendimiento de tus paywalls. Aunque los datos de compras se recopilan automáticamente, registrar las visualizaciones del paywall requiere tu intervención, ya que solo tú sabes cuándo un usuario ve un paywall. Para registrar un evento de visualización del paywall, simplemente llama a `.logShowPaywall(paywall)` y esto quedará reflejado en las métricas de tu paywall en los embudos y las pruebas A/B. :::important No es necesario llamar a `.logShowPaywall(paywall)` si estás mostrando paywalls creados en el [Paywall Builder](adapty-paywall-builder). ::: ```typescript showLineNumbers try { await adapty.logShowPaywall({ paywall }); } catch (error) { console.error('Failed to log paywall view:', error); } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :-------- | :--------------------------------------------------------- | | **paywall** | requerido | Un objeto [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall). | --- # File: capacitor-making-purchases --- --- title: "Realizar compras en una app móvil con Capacitor SDK" description: "Guía para gestionar compras in-app y suscripciones con Adapty." --- Mostrar paywalls en tu app móvil es un paso fundamental para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, simplemente mostrarlos basta para gestionar compras solo si usas el [Paywall Builder](adapty-paywall-builder) para personalizar tus paywalls. Si no usas el Paywall Builder, debes utilizar un método separado llamado `.makePurchase()` para completar una compra y desbloquear el contenido deseado. Este método es la puerta de entrada para que los usuarios interactúen con los paywalls y procedan con sus transacciones. Si tu paywall tiene una oferta promocional activa para el producto que el usuario intenta comprar, Adapty la aplicará automáticamente en el momento de la compra. Asegúrate de haber completado la [configuración inicial](quickstart) sin saltarte ningún paso. Sin ella, no podemos validar las compras. ## Realizar una compra \{#make-purchase\} :::note **¿Usas el [Paywall Builder](adapty-paywall-builder)?** Las compras se procesan automáticamente; puedes saltarte este paso. **¿Buscas instrucciones paso a paso?** Consulta la [guía de inicio rápido](capacitor-implement-paywalls-manually) para obtener instrucciones de implementación completas con todo el contexto. ::: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product }); if (result.type === 'success') { const isSubscribed = result.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features console.log('User is now subscribed!'); } } else if (result.type === 'user_cancelled') { console.log('Purchase cancelled by user'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { console.error('Purchase failed:', error); } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :--------- |:--------------------------------------------------------------------------------------------------------------------------------------| | **product** | obligatorio | Un objeto [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) obtenido del paywall. | Parámetros de la respuesta: | Parámetro | Descripción | |------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **result** | Un objeto [`AdaptyPurchaseResult`](https://capacitor.adapty.io/types/adaptypurchaseresult) con un campo `type` que indica el resultado de la compra (`'success'`, `'user_cancelled'` o `'pending'`) y un campo `profile` que contiene el [`AdaptyProfile`](https://capacitor.adapty.io/interfaces/adaptyprofile) actualizado cuando la compra es exitosa. | ## Cambiar la suscripción al realizar una compra \{#change-subscription-when-making-a-purchase\} Cuando un usuario opta por una nueva suscripción en lugar de renovar la actual, el comportamiento depende del store: - En el App Store, la suscripción se actualiza automáticamente dentro del grupo de suscripciones. Si un usuario compra una suscripción de un grupo mientras ya tiene una activa de otro, ambas estarán activas al mismo tiempo. - En Google Play, la suscripción no se actualiza automáticamente. Deberás gestionar el cambio en el código de tu app tal como se describe a continuación. Para reemplazar una suscripción por otra en Android, llama al método `.makePurchase()` con el parámetro adicional: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product, params: { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } } }); if (result.type === 'success') { const isSubscribed = result.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features console.log('Subscription updated successfully!'); } } else if (result.type === 'user_cancelled') { console.log('Purchase cancelled by user'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { console.error('Purchase failed:', error); } ``` Parámetro de solicitud adicional: | Parámetro | Presencia | Descripción | | :--------- | :--------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **params** | opcional | Un objeto de tipo [`MakePurchaseParamsInput`](https://capacitor.adapty.io/types/makepurchaseparamsinput) que contiene parámetros de compra específicos de cada plataforma. | La estructura de `MakePurchaseParamsInput` es: ```typescript { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } } ``` Puedes obtener más información sobre suscripciones y modos de reemplazo en la documentación para desarrolladores de Google: - [Acerca de los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Recomendaciones de Google sobre modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Modo de reemplazo [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Nota: este método solo está disponible para actualizaciones de suscripción. No se admiten las degradaciones. - Modo de reemplazo [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Nota: el cambio real de suscripción solo ocurre cuando finaliza el período de facturación actual. ### Gestionar planes prepagos (Android) \{#manage-prepaid-plans-android\} Si los usuarios de tu app pueden adquirir [planes prepagos](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans) (por ejemplo, comprar una suscripción no renovable por varios meses), puedes habilitar las [transacciones pendientes](https://developer.android.com/google/play/billing/subscriptions#pending) para dichos planes. ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { enablePendingPrepaidPlans: true, }, } }); ``` ## Canjear códigos de oferta en iOS \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';opcional
predeterminado: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto de uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de configuración regional](localizations-and-locale-codes) para más información sobre los códigos de configuración regional y cómo recomendamos usarlos.
| | **params.fetchPolicy** |opcional
predeterminado: `'reload_revalidating_cache_data'`
|Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `'return_cache_data_else_load'` para devolver los datos en caché si existen. En este caso, es posible que los usuarios no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché se conserva al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
| | **params.loadTimeoutMs** |opcional
predeterminado: 5000 ms
|Este valor limita el tiempo de espera (en milisegundos) para este método. Si se alcanza el tiempo de espera, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeoutMs`, ya que la operación puede estar compuesta de diferentes solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onboarding** | Un objeto [`AdaptyOnboarding`](https://capacitor.adapty.io/interfaces/adaptyonboarding) con: el identificador y la configuración del onboarding, Remote Config y varias otras propiedades. | ## Acelera la obtención del onboarding con el onboarding de audiencia predeterminada \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Por lo general, los onboardings se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, en casos en los que tengas numerosas audiencias y onboardings, y tus usuarios tengan una conexión a internet lenta, obtener un onboarding puede tardar más de lo deseado. En estas situaciones, puede que quieras mostrar un onboarding predeterminado para garantizar una experiencia de usuario fluida en lugar de no mostrar ningún onboarding. Para ello, puedes usar el método `getOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es importante entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, tal como se detalla en la sección [Obtener el onboarding](#fetch-onboarding) anterior. :::warning Considera usar `getOnboarding` en lugar de `getOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: Puede generar problemas al dar soporte a varias versiones de la app, lo que requiere diseños compatibles con versiones anteriores o aceptar que las versiones más antiguas puedan mostrarse incorrectamente. - **Sin personalización**: Solo muestra contenido para la audiencia "All Users", eliminando la segmentación por país, atribución o atributos personalizados. Si para tu caso de uso la mayor velocidad de obtención compensa estos inconvenientes, usa `getOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getOnboarding` como se describe [arriba](#fetch-onboarding). ::: ```typescript showLineNumbers try { const onboarding = await adapty.getOnboardingForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data' // Load from server, fallback to cache } }); console.log('Default audience onboarding fetched successfully'); } catch (error) { console.error('Failed to fetch default audience onboarding:', error); } ``` Parámetros: | Parámetro | Presencia | Descripción | |---------|--------|-----------| | **placementId** | obligatorio | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
predeterminado: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto de uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de configuración regional](localizations-and-locale-codes) para más información sobre los códigos de configuración regional y cómo recomendamos usarlos.
| | **params.fetchPolicy** |opcional
predeterminado: `'reload_revalidating_cache_data'`
|Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `'return_cache_data_else_load'` para devolver los datos en caché si existen. En este caso, es posible que los usuarios no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché se conserva al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
| --- # File: capacitor-present-onboardings --- --- title: "Mostrar onboardings en el SDK de Capacitor" description: "Descubre cómo mostrar onboardings en Capacitor para mejorar las conversiones y los ingresos." --- Si has personalizado un onboarding con el builder, no necesitas preocuparte por renderizarlo en el código de tu app móvil para mostrárselo al usuario. Ese onboarding ya incluye tanto el contenido que debe mostrarse como la forma en que debe hacerlo. Antes de empezar, asegúrate de que: 1. Has [creado un onboarding](create-onboarding). 2. Has añadido el onboarding a un [placement](placements). ## Mostrar el onboarding \{#present-onboarding\} Para mostrar un onboarding, usa el método `view.present()` sobre el `view` creado por el método `createOnboardingView`. Cada `view` solo puede usarse una vez. Si necesitas mostrar el onboarding de nuevo, llama a `createOnboardingView` otra vez para crear una nueva instancia de `view`. :::warning Reutilizar el mismo `view` sin recrearlo puede provocar un error. ::: ```typescript showLineNumbers try { const view = await createOnboardingView(onboarding); view.setEventHandlers({ onClose: (actionId, meta) => { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, onCustom: (actionId, meta) => { console.log('Custom action:', actionId); return false; // Don't close the onboarding } }); await view.present(); console.log('Onboarding presented successfully'); } catch (error) { console.error('Failed to present onboarding:', error); } ``` ## Configurar el estilo de presentación en iOS \{#configure-ios-presentation-style\} Configura cómo se presenta el onboarding en iOS pasando el parámetro `iosPresentationStyle` al método `present()`. El parámetro acepta los valores `'full_screen'` (predeterminado) o `'page_sheet'`. ```typescript showLineNumbers await view.present({ iosPresentationStyle: 'page_sheet' }); ``` ## Personalizar cómo se abren los enlaces en los onboardings \{#customize-how-links-open-in-onboardings\} :::important La personalización de cómo se abren los enlaces en los onboardings está disponible a partir del SDK de Adapty v.3.15. ::: Por defecto, los enlaces en los onboardings se abren en un navegador integrado en la app. Esto ofrece una experiencia fluida al mostrar las páginas web dentro de tu aplicación, sin que el usuario tenga que cambiar de app. Si prefieres abrir los enlaces en un navegador externo, puedes personalizar este comportamiento estableciendo el parámetro `openIn` en `browser_out_app`: ```typescript showLineNumbers await view.present({ openIn: 'browser_out_app' }); // default — browser_in_app ``` ## Próximos pasos \{#next-steps\} Una vez que hayas mostrado tu onboarding, querrás [gestionar las interacciones y eventos del usuario](capacitor-handling-onboarding-events). Aprende a manejar los eventos del onboarding para responder a las acciones del usuario y hacer seguimiento de los datos analíticos. --- # File: capacitor-handling-onboarding-events --- --- title: "Gestionar eventos de onboarding en el SDK de Capacitor" description: "Gestiona eventos relacionados con el onboarding en Capacitor usando Adapty." --- Los onboardings configurados con el builder generan eventos a los que tu app puede responder. Usa el método `setEventHandlers` para gestionar estos eventos en la presentación de pantallas independientes. Antes de empezar, asegúrate de que: 1. Has [creado un onboarding](create-onboarding). 2. Has añadido el onboarding a un [placement](placements). ## Configurar los manejadores de eventos \{#set-up-event-handlers\} Para gestionar eventos de onboardings, usa el método `view.setEventHandlers`: ```typescript showLineNumbers try { const view = await createOnboardingView(onboarding); view.setEventHandlers({ onAnalytics(event, meta) { console.log('Analytics event:', event); }, onClose(actionId, meta) { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, onCustom(actionId, meta) { console.log('Custom action:', actionId); return false; // Don't close the onboarding }, onPaywall(actionId, meta) { console.log('Paywall action:', actionId); view.dismiss().then(() => { openPaywall(actionId); }); }, onStateUpdated(action, meta) { console.log('State updated:', action); }, onFinishedLoading(meta) { console.log('Onboarding finished loading'); }, onError(error) { console.error('Onboarding error:', error); }, }); await view.present(); } catch (error) { console.error('Failed to present onboarding:', error); } ``` ## Tipos de eventos \{#event-types\} Las siguientes secciones describen los distintos tipos de eventos que puedes gestionar. ### Gestionar acciones personalizadas \{#handle-custom-actions\} En el builder, puedes añadir una acción **custom** a un botón y asignarle un ID.
Luego puedes usar ese ID en tu código y gestionarlo como una acción personalizada. Por ejemplo, si el usuario pulsa un botón personalizado como **Login** o **Allow notifications**, el manejador de eventos se activará con el parámetro `actionId` que coincide con el **Action ID** del builder. Puedes crear tus propios IDs, como "allowNotifications".
```typescript showLineNumbers
view.setEventHandlers({
onCustom(actionId, meta) {
switch (actionId) {
case 'login':
console.log('Login action triggered');
break;
case 'allow_notifications':
console.log('Allow notifications action triggered');
break;
}
return false; // Don't close the onboarding
},
});
```
:::important
Ten en cuenta que debes gestionar qué ocurre cuando el usuario cierra el onboarding. Por ejemplo, necesitas dejar de mostrar el propio onboarding.
:::
```typescript showLineNumbers
view.setEventHandlers({
onClose(actionId, meta) {
console.log('Onboarding closed:', actionId);
return true; // Allow the onboarding to close
},
});
```
Este código de error indica que el usuario canceló una solicitud de pago.
No se requiere ninguna acción, pero en términos de lógica de negocio, puedes ofrecer un descuento al usuario o recordárselo más adelante.
| | paymentInvalid | 3 | Este error indica que uno de los parámetros de pago no fue reconocido por la store. | | paymentNotAllowed | 4 |Este código de error indica que el usuario no tiene permiso para autorizar pagos. Posibles razones:
- Los pagos no están disponibles en el país del usuario.
- El usuario es menor de edad.
| | storeProductNotAvailable | 5 | Este código de error indica que el producto solicitado no está disponible en la App Store. Asegúrate de que el producto esté disponible en el país correspondiente. | | cloudServicePermissionDenied | 6 | Este código de error indica que el usuario no ha permitido el acceso a la información del servicio en la nube. | | cloudServiceNetworkConnectionFailed | 7 | Este código de error indica que el dispositivo no pudo conectarse a la red. | | cloudServiceRevoked | 8 | Este código de error indica que el usuario ha revocado el permiso para usar este servicio en la nube. | | privacyAcknowledgementRequired | 9 | Este código de error indica que el usuario aún no ha aceptado la política de privacidad de la store. | | unauthorizedRequestData | 10 | Este código de error indica que la solicitud está construida de forma incorrecta. | | invalidOfferIdentifier | 11 |El identificador de oferta no es válido. Posibles razones:
- No has configurado una oferta con ese identificador en la App Store.
- Has revocado la oferta.
- Hay un error tipográfico en el ID de la oferta.
| | invalidSignature | 12 | Este código de error indica que la firma en un descuento de pago no es válida. Asegúrate de haber rellenado el campo **In-app purchase Key ID** y de haber subido el archivo **In-App Purchase Private Key**. Consulta el tema [Configure App Store integration](app-store-connection-configuration) para más detalles. | | missingOfferParams | 13 |Este error indica problemas con la integración de Adapty o con las ofertas.
Consulta [Configure App Store integration](app-store-connection-configuration) y [Offers](offers) para más detalles sobre cómo configurarlas.
| | invalidOfferPrice | 14 | Este código de error indica que el precio que especificaste en la store ya no es válido. Las ofertas siempre deben representar un precio con descuento. | ## Códigos personalizados de Android \{#custom-android-codes\} | Error | Código | Descripción | |-----|----|-----------| | adaptyNotInitialized | 20 | Necesitas configurar correctamente el SDK de Adapty mediante el método `Adapty.activate`. Aprende cómo hacerlo [para React Native](sdk-installation-reactnative). | | productNotFound | 22 | Este error indica que el producto solicitado para la compra no está disponible en la store. | | invalidJson | 23 | El JSON del paywall no es válido. Corrígelo en el Adapty Dashboard. Consulta el tema [Customize paywall with remote config](customize-paywall-with-remote-config) para más detalles sobre cómo corregirlo. | | currentSubscriptionToUpdateNotFoundInHistory | 24 | No se encontró la suscripción original que debe renovarse. | | pendingPurchase | 25 | Este error indica que el estado de la compra está pendiente en lugar de completado. Consulta la página [Handling pending transactions](https://developer.android.com/google/play/billing/integrate#pending) en la documentación para desarrolladores de Android para más detalles. | | billingServiceTimeout | 97 | Este error indica que la solicitud alcanzó el tiempo de espera máximo antes de que Google Play pudiera responder. Esto puede deberse, por ejemplo, a un retraso en la ejecución de la acción solicitada por la llamada a la Play Billing Library. | | featureNotSupported | 98 | La función solicitada no es compatible con la Play Store en el dispositivo actual. | | billingServiceDisconnected | 99 | Este error fatal indica que la conexión de la app cliente al servicio de Google Play Store a través del `BillingClient` se ha interrumpido. | | billingServiceUnavailable | 102 | Este error transitorio indica que el servicio de facturación de Google Play no está disponible en este momento. En la mayoría de los casos, significa que hay un problema de conexión de red entre el dispositivo cliente y los servicios de facturación de Google Play. | | billingUnavailable | 103 |Este error indica que ocurrió un error de facturación del usuario durante el proceso de compra. Algunos ejemplos de cuándo puede ocurrir:
1\. La app de Play Store en el dispositivo del usuario está desactualizada.
2. El usuario está en un país no compatible.
3. El usuario es un empleado de empresa y su administrador ha deshabilitado las compras.
4. Google Play no puede cargar el método de pago del usuario. Por ejemplo, la tarjeta de crédito del usuario puede haber caducado.
5. El usuario no ha iniciado sesión en la app de Play Store.
| | developerError | 105 | Este es un error fatal que indica que estás usando una API de forma incorrecta. | | billingError | 106 | Este es un error fatal que indica un problema interno en Google Play. | | itemAlreadyOwned | 107 | El producto consumible ya ha sido comprado. | | itemNotOwned | 108 | Este error indica que la acción solicitada sobre el artículo falló. | ## Códigos personalizados de StoreKit \{#custom-storekit-codes\} | Error | Código | Descripción | |-----|----|-----------| | noProductIDsFound | 1000 |Este error indica que ninguno de los productos del paywall está disponible en la store.
Si encuentras este error, sigue los pasos a continuación para resolverlo:
1. Comprueba que todos los productos se han añadido al Adapty Dashboard.
2. Asegúrate de que el Bundle ID de tu app coincide con el de Apple Connect.
3. Verifica que los identificadores de producto de las app stores coincidan con los que has añadido al Dashboard. Ten en cuenta que los identificadores no deben contener el Bundle ID, a menos que ya esté incluido en la store.
4. Confirma que el estado de pago de la app está activo en tu configuración fiscal de Apple. Asegúrate de que tu información fiscal está actualizada y que tus certificados son válidos.
5. Comprueba que hay una cuenta bancaria vinculada a la app para que pueda ser elegible para la monetización.
6. Verifica que los productos estén disponibles en todas las regiones. Además, asegúrate de que tus productos estén en estado **"Ready to Submit"**.
| | productRequestFailed | 1002 |No se pueden obtener los productos disponibles en este momento. Posible razón:
- Aún no se ha creado ninguna caché y no hay conexión a internet al mismo tiempo.
| | cantMakePayments | 1003 | Las compras in-app no están permitidas en este dispositivo. | | noPurchasesToRestore | 1004 | Este error indica que Google Play no encontró ninguna compra que restaurar. | | cantReadReceipt | 1005 |No hay ningún recibo válido disponible en el dispositivo. Esto puede ser un problema durante las pruebas en sandbox.
No se requiere ninguna acción, pero en términos de lógica de negocio, puedes ofrecer un descuento al usuario o recordárselo más adelante.
| | productPurchaseFailed | 1006 | La compra del producto falló. Esto envuelve un error subyacente de StoreKit: lee el error interno (o activa los registros detallados para verlo en la consola) para conocer la razón exacta. El error interno suele ser uno de los códigos de StoreKit 0–14 de la tabla anterior, siendo los más comunes `paymentCancelled`, `paymentInvalid`, `paymentNotAllowed` o `invalidOfferPrice`. Si no puedes identificar una razón concreta, prueba con un nuevo [perfil de sandbox](test-purchases-in-sandbox); si sigue fallando, contacta con el soporte de Apple. | | refreshReceiptFailed | 1010 | Este error indica que no se recibió el recibo. Solo aplica a StoreKit 1. | | receiveRestoredTransactionsFailed | 1011 | La restauración de la compra falló. | ## Códigos de red personalizados \{#custom-network-codes\} | Error | Código | Descripción | | :------------------- | :----- | :----------------------------------------------------------- | | notActivated | 2002 | Necesitas configurar correctamente el SDK de Adapty mediante el método `Adapty.activate`. Aprende cómo hacerlo [para React Native](sdk-installation-reactnative). | | badRequest | 2003 | Solicitud incorrecta. | | serverError | 2004 | Error del servidor. | | networkFailed | 2005 | La solicitud de red falló. | | decodingFailed | 2006 | Este error indica que falló la decodificación de la respuesta. | | encodingFailed | 2009 | Este error indica que falló la codificación de la solicitud. | | analyticsDisabled | 3000 | No podemos gestionar eventos de análisis porque los has desactivado. Consulta el tema [Analytics integration](analytics-integration) para más detalles. | | wrongParam | 3001 | Este error indica que alguno de tus parámetros no es correcto: está en blanco cuando no puede estarlo, tiene un tipo incorrecto, etc. | | activateOnceError | 3005 | No es posible llamar al método `.activate` más de una vez. | | profileWasChanged | 3006 | El perfil de usuario cambió durante la operación. | | fetchTimeoutError | 3101 | Este error significa que el paywall no se pudo obtener dentro del límite establecido. Para evitar esta situación, [configura los fallbacks locales](fetch-paywalls-and-products). | | operationInterrupted | 9000 | Esta operación fue interrumpida por el sistema. | --- # File: capacitor-sdk-migration-guides --- --- title: "Capacitor SDK Migration Guides" description: "Migration guides for Adapty Capacitor SDK versions." --- This page contains all migration guides for Adapty Capacitor SDK. Choose the version you want to migrate to for detailed instructions: - [**Migrate to v. 3.16**](migration-to-capacitor-316) --- # File: migration-to-capacitor-316 --- --- title: "Migrar el SDK de Adapty Capacitor a la versión 3.16" description: "Migra al SDK de Adapty Capacitor v3.16 para mejorar el rendimiento y acceder a nuevas funciones de monetización." --- A partir de la versión 3.16.0 del SDK de Adapty, se requiere Capacitor 8. Si necesitas Capacitor 7, usa la versión 3.15 del SDK de Adapty. Para actualizar al SDK de Capacitor v.3.16, asegúrate de que tu proyecto use Capacitor 8. Si todavía usas Capacitor 7, tienes dos opciones: 1. **Actualizar a Capacitor 8**: Sigue la [guía oficial de migración de Capacitor](https://capacitorjs.com/docs/updating/8-0) para actualizar tu proyecto y luego instala el SDK de Adapty v.3.16. 2. **Quedarte en el SDK de Adapty v.3.15**: Si actualizar a Capacitor 8 no es viable, sigue usando el SDK de Adapty v.3.15, que es compatible con Capacitor 7. --- # End of Documentation _Generated on: 2026-05-15T20:13:57.503Z_ _Successfully processed: 40/40 files_ # FLUTTER - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: es Generated on: 2026-05-15T20:13:57.504Z Total files: 39 --- # File: sdk-installation-flutter --- --- title: "Instalar y configurar el SDK de Flutter" description: "Guía paso a paso para instalar el SDK de Adapty en Flutter en apps con suscripciones." --- El SDK de Adapty incluye dos módulos clave para una integración fluida en tu app de Flutter: - **Core Adapty**: el SDK esencial, necesario para que Adapty funcione correctamente en tu app. - **AdaptyUI**: necesario si usas el [Adapty Paywall Builder](adapty-paywall-builder), una herramienta visual sin código para crear paywalls multiplataforma fácilmente. :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Consulta nuestra [app de ejemplo](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example), que muestra la configuración completa: visualización de paywalls, compras y otras funciones básicas. ::: ## Requisitos \{#requirements\} El SDK de Adapty es compatible con iOS 13.0+, pero requiere iOS 15.0+ para funcionar correctamente con paywalls creados en el Paywall Builder. :::info Adapty es compatible con Google Play Billing Library hasta la versión 8.x. Por defecto, Adapty trabaja con Google Play Billing Library v.7.0.0, pero si quieres forzar una versión posterior, puedes [añadir la dependencia](https://developer.android.com/google/play/billing/integrate#dependency) manualmente. ::: --- no_index: true --- import Callout from '../../../components/Callout.astro';
### Durante el login/registro \{#during-loginsignup\}
Si identificas a los usuarios después del lanzamiento de la app (por ejemplo, después de que inicien sesión o se registren), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario**, Adapty cambiará al perfil asociado a ese customer user ID.
:::important
Los customer user IDs deben ser únicos para cada usuario. Si defines el valor del parámetro de forma fija en el código, todos los usuarios se considerarán como uno solo.
:::
Siempre usa `await` con `identify` antes de llamar a otros métodos del SDK. Las llamadas concurrentes generan `#3006 profileWasChanged` o se aplican al perfil anónimo. Consulta [Orden de llamadas en el SDK de Flutter](flutter-sdk-call-order).
```dart showLineNumbers
try {
await Adapty().identify(customerUserId); // Unique for each user
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
}
```
### Durante la activación del SDK \{#during-the-sdk-activation\}
Si ya conoces el customer user ID cuando activas el SDK, puedes enviarlo en el método `activate` en lugar de llamar a `identify` por separado.
Si conoces el customer user ID pero lo defines solo después de la activación, Adapty creará un nuevo perfil anónimo al activarse y cambiará al existente solo después de que llames a `identify`.
Puedes pasar un customer user ID existente (uno que hayas usado antes) o uno nuevo. Si pasas uno nuevo, el perfil creado al activarse se vinculará automáticamente al customer user ID.
:::note
De forma predeterminada, la creación de perfiles anónimos no afecta a los dashboards de análisis, porque las instalaciones se cuentan según los IDs de dispositivo.
Un ID de dispositivo representa una única instalación de la app desde el store en un dispositivo y solo se regenera después de reinstalar la app.
No depende de si es una primera o posterior instalación, ni de si se usa un customer user ID existente.
Crear un perfil (al activar el SDK o al cerrar sesión), iniciar sesión o actualizar la app sin reinstalarla no genera eventos de instalación adicionales.
Si quieres contar las instalaciones por usuarios únicos en lugar de por dispositivos, ve a **App settings** y configura [**Installs definition for analytics**](general#4-installs-definition-for-analytics).
:::
```dart showLineNumbers"
try {
await Adapty().activate(
configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY')
..withCustomerUserId(YOUR_CUSTOMER_USER_ID) // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one.
);
} catch (e) {
// handle the error
}
```
### Cerrar sesión de usuarios \{#log-users-out\}
Si tienes un botón para cerrar sesión de los usuarios, usa el método `logout`.
:::important
Cerrar la sesión de un usuario crea un nuevo perfil anónimo para ese usuario.
:::
```dart showLineNumbers
try {
await Adapty().logout();
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
// handle unknown error
}
```
:::info
Para volver a iniciar sesión en la app, usa el método `identify`.
:::
### Permitir compras sin inicio de sesión \{#allow-purchases-without-login\}
Si tus usuarios pueden realizar compras tanto antes como después de iniciar sesión en tu app, debes asegurarte de que conserven el acceso después de iniciar sesión:
1. Cuando un usuario sin sesión iniciada realiza una compra, Adapty la vincula a su ID de perfil anónimo.
2. Cuando el usuario inicia sesión en su cuenta, Adapty cambia a trabajar con su perfil identificado.
- Si es un nuevo customer user ID (por ejemplo, la compra se realizó antes del registro), Adapty asigna el customer user ID al perfil actual, por lo que se mantiene todo el historial de compras.
- Si es un customer user ID existente (el customer user ID ya está vinculado a un perfil), debes obtener el nivel de acceso actual después del cambio de perfil. Puedes llamar a [`getProfile`](flutter-check-subscription-status) justo después de la identificación, o [escuchar las actualizaciones del perfil](flutter-check-subscription-status) para que los datos se sincronicen automáticamente.
## Siguientes pasos \{#next-steps\}
¡Enhorabuena! Has implementado la lógica de pagos in-app en tu app. ¡Te deseamos mucho éxito con la monetización de tu app!
Para sacar aún más partido a Adapty, puedes explorar estos temas:
- [**Pruebas**](troubleshooting-test-purchases): Verifica que todo funciona como se espera
- [**Onboardings**](flutter-onboardings): Engancha a los usuarios con onboardings y mejora la retención
- [**Integraciones**](configuration): Integra con servicios de atribución de marketing y análisis con una sola línea de código
- [**Establecer atributos de perfil personalizados**](flutter-setting-user-attributes): Añade atributos personalizados a los perfiles de usuario y crea segmentos para lanzar pruebas A/B o mostrar diferentes paywalls a distintos usuarios
---
# File: adapty-cursor-flutter
---
---
title: "Integra Adapty en tu app de Flutter con asistencia de IA"
description: "Una guía paso a paso para integrar Adapty en tu app de Flutter usando Cursor, Context7, ChatGPT, Claude u otras herramientas de IA."
---
Esta página explica dos formas de integrar Adapty en tu app de Flutter. Usa la habilidad de integración del SDK que se describe a continuación para un flujo automatizado de extremo a extremo, o sigue el recorrido manual más adelante.
## Usa la habilidad de integración del SDK (beta) \{#use-the-sdk-integration-skill-beta\}
La [habilidad adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza la integración de principio a fin: configuración del dashboard, instalación del SDK, paywall y verificación por etapas. El recorrido manual que aparece más abajo es la alternativa si tu herramienta no admite el formato Claude Skills.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
### Instalación \{#install\}
Elige el formato para tu herramienta. La lista completa está en el [README de la habilidad](https://github.com/adaptyteam/adapty-sdk-integration-skill).
- **Claude Code**: Ejecuta `claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill` y después `claude plugin install adapty-sdk-integration@adapty` desde tu shell.
- **GitHub Copilot CLI**: Ejecuta `gh skill install adaptyteam/adapty-sdk-integration-skill`.
- **Gemini CLI**: Ejecuta `gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill`.
- **OpenAI Codex u otra herramienta**: Clona el repositorio y copia `plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` en el directorio de habilidades de tu herramienta.
### Ejecución \{#run\}
Desde tu proyecto, ejecuta `/adapty-sdk-integration`. La habilidad detecta tu plataforma y hace algunas preguntas de configuración. Luego recorre la configuración del dashboard, la instalación del SDK, el paywall y la verificación, consultando la documentación de Adapty en cada etapa.
:::note
La habilidad está en beta. Si se detiene o se comporta de forma inesperada, el recorrido manual que aparece a continuación cubre cada etapa paso a paso.
:::
## Antes de empezar: configuración del dashboard \{#before-you-start-dashboard-setup\}
Adapty requiere cierta configuración en el dashboard antes de escribir código del SDK. Puedes hacerlo con una habilidad de LLM interactiva o manualmente desde el Dashboard.
### Enfoque con habilidad (recomendado) \{#skill-approach-recommended\}
La habilidad CLI de Adapty permite que tu LLM configure tu app, productos, niveles de acceso, paywalls y placements directamente, sin necesidad de abrir el Dashboard en cada paso. Solo necesitas [conectar tus stores](integrate-payments) desde el Dashboard.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Una vez añadida la habilidad, ejecuta `/adapty-cli` en tu agente. Te guiará por cada paso, incluido cuándo abrir el Dashboard para conectar tus stores.
### Enfoque manual desde el dashboard \{#dashboard-approach\}
Si prefieres configurarlo todo manualmente, esto es lo que necesitas antes de escribir código. Tu LLM no puede buscar los valores del dashboard por ti, así que tendrás que proporcionarlos.
1. **Conecta tus stores**: En el Adapty Dashboard, ve a **App settings → General**. Conecta App Store y Google Play si tu app de Flutter se dirige a ambas plataformas. Esto es obligatorio para que las compras funcionen.
[Conectar stores](integrate-payments)
2. **Copia tu clave SDK pública**: En el Adapty Dashboard, ve a **App settings → General** y localiza la sección **API keys**. En el código, esta es la cadena que pasas a la configuración de Adapty.
3. **Crea al menos un producto**: En el Adapty Dashboard, ve a la página **Products**. No referenciarás los productos directamente en el código: Adapty los entrega a través de los paywalls.
[Añadir productos](quickstart-products)
4. **Crea un paywall y un placement**: En el Adapty Dashboard, crea un paywall en la página **Paywalls** y asígnalo a un placement en la página **Placements**. En el código, el ID del placement es la cadena que pasas a `Adapty().getPaywall()`.
[Crear paywall](quickstart-paywalls)
5. **Configura los niveles de acceso**: En el Adapty Dashboard, configúralos por producto en la página **Products**. En el código, la cadena que se comprueba es `profile.accessLevels['premium']?.isActive`. El nivel de acceso `premium` predeterminado funciona para la mayoría de las apps. Si los usuarios de pago acceden a distintas funciones según el producto (por ejemplo, un plan `basic` frente a uno `pro`), [crea niveles de acceso adicionales](assigning-access-level-to-a-product) antes de empezar a programar.
:::tip
Una vez que tengas los cinco, estás listo para escribir código. Dile a tu LLM: "Mi clave SDK pública es X, mi ID de placement es Y" para que pueda generar el código correcto de inicialización y obtención del paywall.
:::
### Configura cuando estés listo \{#set-up-when-ready\}
Estos pasos no son necesarios para empezar a programar, pero los querrás a medida que tu integración madure:
- **Pruebas A/B**: Configúralas en la página **Placements**. No requieren cambios en el código.
[Pruebas A/B](ab-tests)
- **Paywalls y placements adicionales**: Añade más llamadas a `getPaywall` con distintos IDs de placement.
- **Integraciones de analíticas**: Configúralas en la página **Integrations**. La configuración varía según la integración. Consulta [integraciones de analíticas](analytics-integration) e [integraciones de atribución](attribution-integration).
## Proporciona documentación de Adapty a tu LLM \{#feed-adapty-docs-to-your-llm\}
### Usa Context7 (recomendado) \{#use-context7-recommended\}
[Context7](https://context7.com) es un servidor MCP que da a tu LLM acceso directo a la documentación actualizada de Adapty. El LLM obtiene automáticamente la documentación adecuada según lo que preguntes, sin necesidad de pegar URLs manualmente.
Context7 funciona con **Cursor**, **Claude Code**, **Windsurf** y otras herramientas compatibles con MCP. Para configurarlo, ejecuta:
```
npx ctx7 setup
```
Esto detecta tu editor y configura el servidor Context7. Para la configuración manual, consulta el [repositorio GitHub de Context7](https://github.com/upstash/context7).
Una vez configurado, referencia la biblioteca de Adapty en tus prompts:
```
Use the adaptyteam/adapty-docs library to look up how to install the Flutter SDK
```
:::warning
Aunque Context7 elimina la necesidad de pegar enlaces de documentación manualmente, el orden de implementación importa. Sigue el [recorrido de implementación](#implementation-walkthrough) paso a paso para asegurarte de que todo funciona correctamente.
:::
### Usa documentación en texto plano \{#use-plain-text-docs\}
Puedes acceder a cualquier documento de Adapty como Markdown en texto plano. Añade `.md` al final de su URL o haz clic en **Copy for LLM** debajo del título del artículo. Por ejemplo: [adapty-cursor-flutter.md](https://adapty.io/docs/es/adapty-cursor-flutter.md).
Cada etapa del [recorrido de implementación](#implementation-walkthrough) que aparece a continuación incluye un bloque "Envía esto a tu LLM" con enlaces `.md` listos para pegar.
Para obtener más documentación a la vez, consulta los [archivos de índice y subconjuntos por plataforma](#plain-text-doc-index-files) que aparecen más abajo.
## Recorrido de implementación \{#implementation-walkthrough\}
El resto de esta guía recorre la integración de Adapty en el orden de implementación recomendado. Cada etapa incluye la documentación que debes enviar a tu LLM, qué deberías ver al terminar y los problemas más comunes.
### Planifica tu integración \{#plan-your-integration\}
Antes de escribir código, pide a tu LLM que analice tu proyecto y cree un plan de implementación. Si tu herramienta de IA admite un modo de planificación (como el modo plan de Cursor o Claude Code), úsalo para que el LLM pueda leer tanto la estructura de tu proyecto como la documentación de Adapty antes de escribir código.
Dile a tu LLM qué enfoque usas para las compras, ya que esto afecta a las guías que debe seguir:
- [**Adapty Paywall Builder**](adapty-paywall-builder): Creas los paywalls en el editor no-code de Adapty y el SDK los renderiza automáticamente.
- [**Paywalls creados manualmente**](flutter-making-purchases): Construyes tu propia interfaz de paywall en código, pero sigues usando Adapty para obtener productos y gestionar compras.
- [**Modo Observer**](observer-vs-full-mode): Mantienes tu infraestructura de compras existente y usas Adapty solo para analíticas e integraciones.
¿No sabes cuál elegir? Lee la [tabla comparativa en la guía de inicio rápido](flutter-quickstart-paywalls).
### Instala y configura el SDK \{#install-and-configure-the-sdk\}
Añade la dependencia del SDK de Adapty usando `flutter pub add` y actívalo con tu clave SDK pública. Esta es la base: nada más funciona sin ella.
**Guía:** [Instalar y configurar el SDK de Adapty](sdk-installation-flutter)
Envía esto a tu LLM:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/es/sdk-installation-flutter.md
```
:::tip[Punto de control]
- **Esperado:** La app se compila y ejecuta en iOS y Android. La consola de depuración muestra el log de activación de Adapty.
- **Problema frecuente:** "Public API key is missing" → comprueba que reemplazaste el marcador de posición con tu clave real desde App settings.
:::
### Muestra paywalls y gestiona compras \{#show-paywalls-and-handle-purchases\}
Obtén un paywall por ID de placement, muéstralo y gestiona los eventos de compra. Las guías que necesitas dependen de cómo gestionas las compras.
Prueba cada compra en el sandbox a medida que avanzas; no esperes hasta el final. Consulta [Probar compras en sandbox](test-purchases-in-sandbox) para las instrucciones de configuración.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](flutter-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que la CDN no esté disponible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede exceder ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede estar compuesta por distintas peticiones internamente.
Para Android: puedes crear `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` es de `import com.adapty.utils.seconds`), o `TimeInterval.seconds(5)`. Para no establecer límite, usa `TimeInterval.INFINITE`.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) con una lista de IDs de productos, el identificador del paywall, el Remote Config y varias otras propiedades. | ## Obtener la configuración de vista del paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el toggle **Show on device** en el Paywall Builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperar. ::: Después de obtener el paywall, comprueba si incluye una `ViewConfiguration`, lo que indica que fue creado con el Paywall Builder. Esto te indicará cómo mostrar el paywall. Si la `ViewConfiguration` está presente, trátalo como un paywall de Paywall Builder; si no, [manéjalo como un paywall de Remote Config](present-remote-config-paywalls-flutter). ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` Una vez que tengas la vista, [presenta el paywall](flutter-present-paywalls). ## Obtener un paywall para la audiencia por defecto y cargarlo más rápido \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Normalmente, los paywalls se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, si tienes muchas audiencias y paywalls, y tus usuarios tienen una conexión a internet débil, obtener un paywall puede tardar más de lo deseado. En esos casos, puede que quieras mostrar un paywall por defecto para garantizar una experiencia de usuario fluida en lugar de no mostrar ninguno. Para resolver esto, puedes usar el método `getPaywallForDefaultAudience`, que obtiene el paywall del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el paywall con el método `getPaywall`, como se detalla en la sección [Obtener el paywall diseñado con Paywall Builder](flutter-get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) anterior. :::warning Por qué recomendamos usar `getPaywall` El método `getPaywallForDefaultAudience` tiene algunos inconvenientes importantes: - **Posibles problemas de compatibilidad con versiones anteriores**: Si necesitas mostrar paywalls distintos para diferentes versiones de la app (actual y futuras), puedes encontrar dificultades. Tendrás que diseñar paywalls que soporten la versión actual (legacy) o asumir que los usuarios con esa versión podrían encontrar problemas con paywalls que no se renderizan. - **Pérdida de targeting**: Todos los usuarios verán el mismo paywall diseñado para la audiencia **All Users**, lo que significa que pierdes el targeting personalizado (incluido el basado en países, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a asumir estos inconvenientes para beneficiarte de una carga más rápida del paywall, usa el método `getPaywallForDefaultAudience` como se indica a continuación. De lo contrario, usa `getPaywall` descrito [arriba](#fetch-paywall-designed-with-paywall-builder). ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note El método `getPaywallForDefaultAudience` está disponible a partir de la versión 3.2.0 del Flutter SDK. ::: | Parámetro | Presencia | Descripción | |---------|--------|-----------| | **placementId** | requerido | El identificador del [Placement](placements). Es el valor que especificaste al crear un placement en tu Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
| ## Personalizar recursos \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los recursos personalizados. Las imágenes y vídeos principales tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de recursos personalizados, apuntas a estos elementos por sus IDs y personalizas su comportamiento. Para otras imágenes y vídeos, necesitas [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta funcionalidad, actualiza el Flutter SDK de Adapty a la versión 3.8.0 o superior. ::: Aquí tienes un ejemplo de cómo proporcionar recursos personalizados mediante un diccionario simple: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customAssets:
## El número de vistas del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El recuento de vistas del paywall muestra el doble del número esperado.
**Causa**: Es posible que estés llamando a `logShowPaywall` en tu código, lo que duplica el recuento de vistas si usas el Paywall Builder. En los paywalls diseñados con el Paywall Builder, el seguimiento de analytics es automático, por lo que no es necesario usar este método.
**Solución**: Asegúrate de no llamar a `logShowPaywall` en tu código si estás usando el Paywall Builder.
## Otros problemas \{#other-issues\}
**Problema**: Experimentas otros problemas relacionados con el Paywall Builder que no se han tratado anteriormente.
**Solución**: Si es necesario, migra el SDK a la versión más reciente siguiendo las [guías de migración](flutter-sdk-migration-guides). Muchos problemas se resuelven en versiones más nuevas del SDK.
---
# File: flutter-quickstart-manual
---
---
title: "Habilitar compras en tu paywall personalizado en Flutter SDK"
description: "Integra el SDK de Adapty en tus paywalls personalizados de Flutter para habilitar compras in-app."
---
Esta guía describe cómo integrar Adapty en tus paywalls personalizados. Mantén el control total sobre la implementación del paywall, mientras el SDK de Adapty obtiene los productos, gestiona las nuevas compras y restaura las anteriores.
:::important
**Esta guía es para desarrolladores que implementan paywalls personalizados.** Si quieres la forma más sencilla de habilitar compras, usa el [Paywall Builder de Adapty](flutter-quickstart-paywalls). Con Paywall Builder, creas paywalls en un editor visual sin código, Adapty gestiona toda la lógica de compras automáticamente y puedes probar distintos diseños sin volver a publicar tu app.
:::
## Antes de empezar \{#before-you-start\}
### Configura los productos \{#set-up-products\}
Para habilitar las compras in-app, necesitas entender tres conceptos clave:
- [**Productos**](product) – todo lo que los usuarios pueden comprar (suscripciones, consumibles, acceso de por vida)
- [**Paywalls**](paywalls) – configuraciones que definen qué productos ofrecer. En Adapty, los paywalls son la única forma de recuperar productos, pero este diseño te permite modificar productos, precios y ofertas sin tocar el código de tu app.
- [**Placements**](placements) – dónde y cuándo muestras los paywalls en tu app (como `main`, `onboarding`, `settings`). Configuras los paywalls para los placements en el dashboard y luego los solicitas por ID de placement en tu código. Esto facilita ejecutar pruebas A/B y mostrar paywalls distintos a diferentes usuarios.
Asegúrate de entender estos conceptos aunque trabajes con tu paywall personalizado. Básicamente, son tu forma de gestionar los productos que vendes en tu app.
Para implementar tu paywall personalizado, necesitarás crear un **paywall** y añadirlo a un **placement**. Esta configuración te permite recuperar tus productos. Para entender qué debes hacer en el dashboard, sigue la guía de inicio rápido [aquí](quickstart).
### Gestiona usuarios \{#manage-users\}
Puedes trabajar con o sin autenticación de backend en tu lado.
Sin embargo, el SDK de Adapty gestiona de forma diferente a los usuarios anónimos e identificados. Lee la [guía de inicio rápido de identificación](flutter-quickstart-identify) para entender las particularidades y asegurarte de que trabajas con los usuarios correctamente.
## Paso 1. Obtén los productos \{#step-1-get-products\}
Para recuperar los productos de tu paywall personalizado, necesitas:
1. Obtener el objeto `paywall` pasando el ID del [placement](placements) al método `getPaywall`.
2. Obtener el array de productos para ese paywall usando el método `getPaywallProducts`.
```dart showLineNumbers
Futureopcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de configuración regional](flutter-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, puede que los usuarios no reciban los datos más recientes, pero experimentarán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché actualizada regularmente descrita arriba y los [paywalls de respaldo](flutter-use-fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo de espera, se devolverán datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo de espera especificado en `loadTimeout`, ya que la operación puede incluir diferentes solicitudes internamente.
| ¡No escribas los IDs de producto en el código! Dado que los paywalls se configuran de forma remota, los productos disponibles, el número de productos y las ofertas especiales (como períodos de prueba gratuitos) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, tu app debería mostrar esos 2 productos. Sin embargo, si luego obtienes 3 productos, tu app debería mostrar los 3 sin necesidad de cambios en el código. Lo único que debes escribir en el código es el ID del placement. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) con: una lista de IDs de productos, el identificador del paywall, el Remote Config y varias otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tengas el paywall, puedes consultar el array de productos que le corresponde: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(paywall: paywall); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Lista de objetos [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) con: identificador del producto, nombre del producto, precio, moneda, duración de la suscripción y varias otras propiedades. | Cuando implementes tu propio diseño de paywall, probablemente necesitarás acceder a estas propiedades del objeto [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html). A continuación se muestran las propiedades más utilizadas, pero consulta el documento enlazado para ver todos los detalles de las propiedades disponibles. | Propiedad | Descripción | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Para mostrar el título del producto, usa `product.localizedTitle`. Ten en cuenta que la localización se basa en el país del store seleccionado por el usuario, no en la configuración regional del dispositivo. | | **Price** | Para mostrar una versión localizada del precio, usa `product.price.localizedString`. Esta localización se basa en la información de configuración regional del dispositivo. También puedes acceder al precio como número con `product.price.amount`. El valor se proporcionará en la moneda local. Para obtener el símbolo de moneda asociado, usa `product.price.currencySymbol`. | | **Subscription Period** | Para mostrar el período (por ejemplo, semana, mes, año, etc.), usa `product.subscription?.localizedPeriod`. Esta localización se basa en la configuración regional del dispositivo. Para obtener el período de suscripción de forma programática, usa `product.subscription?.period`. Desde ahí puedes acceder al enum `unit` para obtener la duración (es decir, día, semana, mes, año o desconocido). El valor `numberOfUnits` te dará el número de unidades del período. Por ejemplo, para una suscripción trimestral, verías `AdaptyPeriodUnit.month` en la propiedad unit y `3` en la propiedad numberOfUnits. | | **Introductory Offer** | Para mostrar un distintivo u otro indicador de que una suscripción contiene una oferta introductoria, consulta la propiedad `product.subscription?.offer?.phases`. Es una lista que puede contener hasta dos fases de descuento: la fase de prueba gratuita y la fase de precio introductorio. Dentro de cada objeto de fase se encuentran las siguientes propiedades útiles:opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de configuración regional](flutter-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, puede que los usuarios no reciban los datos más recientes, pero experimentarán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
| --- # File: present-remote-config-paywalls-flutter --- --- title: "Renderizar un paywall diseñado con Remote Config en el SDK de Flutter" description: "Descubre cómo presentar paywalls de Remote Config en el SDK de Flutter de Adapty para personalizar la experiencia del usuario." --- Si has personalizado un paywall usando Remote Config, necesitarás implementar el renderizado en el código de tu app para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú decides qué incluir y cómo se muestra la vista de tu paywall. Proporcionamos un método para obtener la configuración remota, dándote autonomía para mostrar tu paywall personalizado configurado a través de Remote Config. ## Obtener el Remote Config del paywall y presentarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores necesarios. ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID"); final String? headerText = paywall.remoteConfig?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` En este punto, una vez que hayas recibido todos los valores necesarios, es momento de renderizarlos y ensamblarlos en una página visualmente atractiva. Asegúrate de que el diseño se adapte a las distintas pantallas y orientaciones de los móviles, ofreciendo una experiencia fluida y amigable en todos los dispositivos. :::warning Asegúrate de [registrar el evento de visualización del paywall](present-remote-config-paywalls-flutter#track-paywall-view-events) tal como se describe a continuación, para que Adapty Analytics pueda capturar información para los embudos y las pruebas A/B. ::: Una vez que hayas terminado de mostrar el paywall, continúa configurando el flujo de compra. Cuando el usuario realice una compra, simplemente llama a `.makePurchase()` con el producto de tu paywall. Para más detalles sobre el método `.makePurchase()`, consulta [Realizar compras](flutter-making-purchases). Te recomendamos [crear un paywall de respaldo llamado fallback paywall](flutter-use-fallback-paywalls). Este respaldo se mostrará al usuario cuando no haya conexión a internet ni caché disponible, garantizando una experiencia fluida incluso en esas situaciones. ## Registrar eventos de visualización del paywall \{#track-paywall-view-events\} Adapty te ayuda a medir el rendimiento de tus paywalls. Aunque los datos de compras se recopilan automáticamente, el registro de las visualizaciones del paywall requiere tu intervención, ya que solo tú sabes cuándo un usuario ve un paywall. Para registrar un evento de visualización del paywall, simplemente llama a `.logShowPaywall(paywall)`, y se reflejará en las métricas de tu paywall en los embudos y las pruebas A/B. :::important No es necesario llamar a `.logShowPaywall(paywall)` si estás mostrando paywalls creados en el [Paywall Builder](adapty-paywall-builder). ::: ```dart showLineNumbers try { final result = await Adapty().logShowPaywall(paywall: paywall); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :------- |:----------------------------------------------------------------------| | **paywall** | obligatorio | Un objeto [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html). | --- # File: flutter-making-purchases --- --- title: "Realizar compras en una aplicación móvil con Flutter SDK" description: "Guía sobre cómo gestionar compras in-app y suscripciones con Adapty." --- Mostrar paywalls en tu aplicación móvil es un paso esencial para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, simplemente mostrar esos paywalls es suficiente para gestionar las compras solo si usas el [Paywall Builder](adapty-paywall-builder) para personalizarlos. Si no usas el Paywall Builder, debes utilizar un método específico llamado `.makePurchase()` para completar una compra y desbloquear el contenido deseado. Este método es la puerta de entrada para que los usuarios interactúen con los paywalls y realicen sus transacciones. Si tu paywall tiene una oferta promocional activa para el producto que el usuario intenta comprar, Adapty la aplicará automáticamente en el momento de la compra. :::warning Ten en cuenta que la oferta introductoria solo se aplicará automáticamente si usas paywalls configurados con el Paywall Builder. En otros casos, tendrás que [verificar la elegibilidad del usuario para una oferta introductoria en iOS](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios). Omitir este paso puede provocar que tu app sea rechazada durante la revisión. Además, podría resultar en que se cobre el precio completo a usuarios que son elegibles para una oferta introductoria. ::: Asegúrate de haber completado la [configuración inicial](quickstart) sin saltarte ningún paso. Sin ella, no podemos validar las compras. ## Realizar una compra \{#make-purchase\} :::note **¿Usas el [Paywall Builder](adapty-paywall-builder)?** Las compras se procesan automáticamente; puedes omitir este paso. **¿Buscas instrucciones paso a paso?** Consulta la [guía de inicio rápido](flutter-implement-paywalls-manually) para obtener instrucciones de implementación completas con todo el contexto. ::: ```dart showLineNumbers try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): if (profile.accessLevels['premium']?.isActive ?? false) { // Grant access to the paid features } break; case AdaptyPurchaseResultPending(): break; case AdaptyPurchaseResultUserCancelled(): break; default: break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :-------- | :-------------------------------------------------------------------------------------------------- | | **Product** | obligatorio | Un objeto [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) obtenido del paywall. | Parámetros de la respuesta: | Parámetro | Descripción | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |Si la solicitud se ha realizado correctamente, la respuesta contiene este objeto. Un objeto [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas de un usuario dentro de la app.
Comprueba el estado del nivel de acceso para determinar si el usuario tiene el acceso requerido en la app.
| :::warning **Nota:** si aún utilizas una versión de StoreKit de Apple inferior a v2.0 y una versión del SDK de Adapty inferior a v.2.9.0, debes proporcionar el [secreto compartido de la App Store de Apple](app-store-connection-configuration#step-5-enter-app-store-shared-secret). Este método está actualmente deprecado por Apple. ::: ## Cambiar la suscripción al realizar una compra \{#change-subscription-when-making-a-purchase\} Cuando un usuario opta por una nueva suscripción en lugar de renovar la actual, el comportamiento depende del store: - En la App Store, la suscripción se actualiza automáticamente dentro del grupo de suscripciones. Si un usuario compra una suscripción de un grupo mientras ya tiene activa una de otro grupo, ambas suscripciones estarán activas al mismo tiempo. - En Google Play, la suscripción no se actualiza automáticamente. Tendrás que gestionar el cambio en el código de tu aplicación móvil tal como se describe a continuación. Para reemplazar la suscripción por otra en Android, llama al método `.makePurchase()` con el parámetro adicional: ```dart showLineNumbers try { final result = await adapty.makePurchase( product: product, subscriptionUpdateParams: subscriptionUpdateParams, ); // successful cross-grade } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` Parámetro adicional de la solicitud: | Parámetro | Presencia | Descripción | | :--------------------------- | :-------- |:--------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | obligatorio | Un objeto [`AdaptyAndroidSubscriptionUpdateParameters`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyAndroidSubscriptionUpdateParameters-class.html). | Puedes obtener más información sobre las suscripciones y los modos de reemplazo en la documentación para desarrolladores de Google: - [Acerca de los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Recomendaciones de Google para los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Modo de reemplazo [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Nota: este método solo está disponible para actualizaciones de suscripción. Las degradaciones no son compatibles. - Modo de reemplazo [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Nota: el cambio de suscripción real solo ocurrirá cuando finalice el período de facturación de la suscripción actual. ## Canjear códigos de oferta en iOS \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';Un objeto [`AdaptyProfile`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html). Este modelo contiene información sobre niveles de acceso, suscripciones y compras únicas.
Comprueba el **estado del nivel de acceso** para determinar si el usuario tiene acceso a la app.
| :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: --- # File: implement-observer-mode-flutter --- --- title: "Implementar el modo Observer en Flutter SDK" description: "Implementa el modo observer en Adapty para rastrear eventos de suscripción de usuarios en Flutter SDK." --- Si ya tienes tu propia infraestructura de compras y no estás listo para migrar completamente a Adapty, puedes explorar el [modo Observer](observer-vs-full-mode). En su forma básica, el modo Observer ofrece analíticas avanzadas e integración fluida con sistemas de atribución y analítica. Si esto cubre tus necesidades, solo tienes que: 1. Activarlo al configurar el SDK de Adapty estableciendo el parámetro `observerMode` en `true`. Sigue las instrucciones de configuración para [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk). 2. [Reportar transacciones](report-transactions-observer-mode-flutter) desde tu infraestructura de compras existente a Adapty. ## Configuración del modo Observer \{#observer-mode-setup\} Activa el modo Observer si gestionas las compras y el estado de la suscripción tú mismo y usas Adapty para enviar eventos de suscripción y analíticas. :::important Cuando se ejecuta en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlo tú mismo. ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withObserverMode(true) // Enable observer mode ..withLogLevel(AdaptyLogLevel.verbose), ); ``` Parámetros: | Parámetro | Descripción | | --------------------------- | ------------------------------------------------------------ | | observerMode | Un valor booleano que controla el [modo Observer](observer-vs-full-mode). El valor predeterminado es `false`. | ## Usar paywalls de Adapty en el modo Observer \{#using-adapty-paywalls-in-observer-mode\} Si también quieres usar los paywalls y las funciones de pruebas A/B de Adapty, puedes hacerlo, pero requiere algo de configuración adicional en el modo Observer. Esto es lo que necesitas hacer además de los pasos anteriores: 1. Muestra los paywalls como de costumbre para [paywalls con Remote Config](present-remote-config-paywalls-flutter). 3. [Asocia los paywalls](report-transactions-observer-mode-flutter) con las transacciones de compra. --- # File: report-transactions-observer-mode-flutter --- --- title: "Reportar transacciones en Observer Mode en Flutter SDK" description: "Reporta transacciones de compra en el Observer Mode de Adapty para obtener información sobre usuarios y seguimiento de ingresos en Flutter SDK." ---phoneNumber
firstName
lastName
| String | | gender | Enum, los valores permitidos son: `female`, `male`, `other` | | birthday | Date | ### Atributos de usuario personalizados \{#custom-user-attributes\} Puedes definir tus propios atributos personalizados, que habitualmente están relacionados con el uso de tu app. Por ejemplo, en aplicaciones de fitness podrían ser el número de ejercicios por semana; en apps de aprendizaje de idiomas, el nivel de conocimiento del usuario, etc. Puedes usarlos en segmentos para crear paywalls y ofertas dirigidas, y también en analítica para descubrir qué métricas de producto tienen más impacto en los ingresos. ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..setCustomStringAttribute('value1', 'key1') ..setCustomDoubleAttribute(1.0, 'key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` Para eliminar una clave existente, usa el método `.withRemoved(customAttributeForKey:)`: ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..removeCustomAttribute('key1') ..removeCustomAttribute('key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` A veces necesitas saber qué atributos personalizados se han establecido previamente. Para ello, utiliza el campo `customAttributes` del objeto `AdaptyProfile`. :::warning Ten en cuenta que el valor de `customAttributes` puede estar desactualizado, ya que los atributos de usuario pueden enviarse desde distintos dispositivos en cualquier momento, por lo que los atributos en el servidor podrían haber cambiado tras la última sincronización. ::: ### Límites \{#limits\} - Hasta 30 atributos personalizados por usuario - Los nombres de clave pueden tener hasta 30 caracteres. El nombre de la clave puede incluir caracteres alfanuméricos y cualquiera de los siguientes: `_` `-` `.` - El valor puede ser una cadena de texto o un número decimal con un máximo de 50 caracteres. --- # File: flutter-listen-subscription-changes --- --- title: "Comprobar el estado de suscripción en el SDK de Flutter" description: "Rastrea y gestiona el estado de suscripción de los usuarios en Adapty para mejorar la retención en tu app de Flutter." --- Con Adapty, llevar el control del estado de suscripción es muy sencillo. No tienes que insertar manualmente los IDs de producto en tu código. En su lugar, puedes confirmar fácilmente el estado de suscripción de un usuario comprobando si tiene un [nivel de acceso](access-level) activo.Un objeto [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html). En general, solo tienes que comprobar el estado del nivel de acceso del perfil para determinar si el usuario tiene acceso premium a la app.
El método `.getProfile` devuelve el resultado más actualizado posible, ya que siempre intenta consultar la API. Si por algún motivo (por ejemplo, sin conexión a internet) el SDK de Adapty no puede obtener la información del servidor, se devolverán los datos de la caché. También es importante destacar que el SDK de Adapty actualiza la caché de `AdaptyProfile` periódicamente para mantener esta información lo más actualizada posible.
| El método `.getProfile()` te proporciona el perfil del usuario desde el que puedes obtener el estado del nivel de acceso. Puedes tener múltiples niveles de acceso por app. Por ejemplo, si tienes una app de noticias y vendes suscripciones a diferentes temáticas de forma independiente, puedes crear niveles de acceso "sports" y "science". Pero la mayoría de las veces solo necesitarás un nivel de acceso; en ese caso, puedes usar simplemente el nivel de acceso "premium" por defecto. Aquí tienes un ejemplo para comprobar el nivel de acceso "premium" por defecto: ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); if (profile?.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### Escuchar actualizaciones del estado de suscripción \{#listening-for-subscription-status-updates\} Cada vez que cambia la suscripción del usuario, Adapty lanza un evento. Para recibir mensajes de Adapty, necesitas realizar una configuración adicional: ```javascript showLineNumbers Adapty().didUpdateProfileStream.listen((profile) { // handle any changes to subscription state }); ``` Adapty también lanza un evento al iniciar la aplicación. En ese caso, se pasará el estado de suscripción almacenado en caché. ### Caché del estado de suscripción \{#subscription-status-cache\} La caché implementada en el SDK de Adapty almacena el estado de suscripción del perfil. Esto significa que, aunque el servidor no esté disponible, se puede acceder a los datos en caché para obtener información sobre el estado de suscripción del perfil. No obstante, hay que tener en cuenta que no es posible solicitar datos directamente desde la caché. El SDK consulta periódicamente el servidor cada minuto para comprobar si hay actualizaciones o cambios relacionados con el perfil. Si hay alguna modificación, como nuevas transacciones u otras actualizaciones, se enviarán a los datos en caché para mantenerlos sincronizados con el servidor. --- # File: flutter-deal-with-att --- --- title: "Gestionar ATT en Flutter SDK" description: "Empieza con Adapty en Flutter para simplificar la configuración y gestión de suscripciones." --- Si tu aplicación utiliza el framework AppTrackingTransparency y muestra al usuario una solicitud de autorización de seguimiento, debes enviar el [estado de autorización](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) a Adapty. ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setAppTrackingTransparencyStatus(AdaptyIOSAppTrackingTransparencyStatus.authorized); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::warning Recomendamos encarecidamente que envíes este valor lo antes posible cuando cambie; solo así los datos se transmitirán a tiempo a las integraciones que hayas configurado. ::: --- # File: kids-mode-flutter --- --- title: "Modo Kids en Flutter SDK" description: "Activa fácilmente el Modo Kids para cumplir con las políticas de Apple y Google. Sin recopilación de IDFA, GAID ni datos de publicidad en Flutter SDK." --- Si tu aplicación Flutter está destinada a niños, debes seguir las políticas de [Apple](https://developer.apple.com/kids/) y [Google](https://support.google.com/googleplay/android-developer/answer/9893335). Si usas el SDK de Adapty, unos pocos pasos sencillos te ayudarán a configurarlo para cumplir con estas políticas y superar las revisiones de las tiendas. ## ¿Qué se requiere? \{#whats-required\} Debes configurar el SDK de Adapty para deshabilitar la recopilación de: - [IDFA (Identificador para Anunciantes)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [Dirección IP](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Además, te recomendamos usar el ID de usuario con precaución. Un ID de usuario con formato `opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexiones inestables a internet, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no reciban los últimos datos, pero experimentarán tiempos de carga más rápidos independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la última versión de tus onboardings y asegurar la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera de este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede agotar el tiempo de espera ligeramente después de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Un objeto [`AdaptyOnboarding`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyOnboarding-class.html) con: el identificador y la configuración del onboarding, el Remote Config y otras propiedades. | ## Acelerar la obtención del onboarding con el onboarding de audiencia predeterminada \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Por lo general, los onboardings se obtienen casi de forma instantánea, por lo que no es necesario preocuparse por acelerar este proceso. Sin embargo, en casos donde tienes muchas audiencias y onboardings, y tus usuarios tienen una conexión a internet débil, obtener un onboarding puede tardar más de lo deseable. En esas situaciones, puede que quieras mostrar un onboarding predeterminado para garantizar una experiencia fluida en lugar de no mostrar ninguno. Para esto, puedes usar el método `getOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, como se detalla en la sección [Obtener el onboarding](#fetch-onboarding) anterior. :::warning Considera usar `getOnboarding` en lugar de `getOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: Puede crear problemas al admitir varias versiones de la app, lo que requiere diseños compatibles hacia atrás o aceptar que las versiones más antiguas puedan mostrarse incorrectamente. - **Sin personalización**: Solo muestra contenido para la audiencia "All Users", eliminando la segmentación basada en país, atribución o atributos personalizados. Si una obtención más rápida supera estos inconvenientes para tu caso de uso, utiliza `getOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getOnboarding` como se describe [arriba](#fetch-onboarding). ::: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboardingForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` Parámetros: | Parámetro | Presencia | Descripción | |-----------------|-----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexiones inestables a internet, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no reciban los últimos datos, pero experimentarán tiempos de carga más rápidos independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la última versión de tus onboardings y asegurar la fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: flutter-present-onboardings --- --- title: "Presentar onboardings en Flutter SDK" description: "Aprende a presentar onboardings de forma efectiva para impulsar más conversiones." --- Si has personalizado un onboarding con el builder, no necesitas preocuparte por renderizarlo en el código de tu app Flutter para mostrárselo al usuario. Ese onboarding ya contiene tanto lo que debe mostrarse como la forma en que debe hacerse. Antes de empezar, asegúrate de que: 1. Tienes instalado el [SDK de Flutter de Adapty](sdk-installation-flutter) versión 3.8.0 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). El SDK de Flutter de Adapty ofrece dos formas de presentar onboardings: - **Pantalla independiente** - **Widget embebido** ## Presentar como pantalla independiente \{#present-as-standalone-screen\} Para mostrar un onboarding como pantalla independiente, usa el método `onboardingView.present()` en el `onboardingView` creado por el método `createOnboardingView`. Cada `view` solo puede usarse una vez. Si necesitas mostrar el onboarding de nuevo, llama a `createOnboardingView` otra vez para crear una nueva instancia de `onboardingView`. :::warning Reutilizar el mismo `onboardingView` sin recrearlo puede provocar un error `AdaptyUIError.viewAlreadyPresented`. ::: ```javascript showLineNumbers title="Flutter" try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Cerrar el onboarding \{#dismiss-the-onboarding\} Cuando necesites cerrar el onboarding por código, usa el método `dismiss()`: ```dart showLineNumbers title="Flutter" try { await onboardingView.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### Configurar el estilo de presentación en iOS \{#configure-ios-presentation-style\} Configura cómo se presenta el onboarding en iOS pasando el parámetro `iosPresentationStyle` al método `present()`. El parámetro acepta los valores `AdaptyUIIOSPresentationStyle.fullScreen` (predeterminado) o `AdaptyUIIOSPresentationStyle.pageSheet`. ```dart showLineNumbers try { await onboardingView.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## Embeber en la jerarquía de widgets \{#embed-in-widget-hierarchy\} Para embeber un onboarding dentro de tu árbol de widgets existente, usa el widget `AdaptyUIOnboardingPlatformView` directamente en la jerarquía de widgets de Flutter. ```javascript showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, // The onboarding object you fetched onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` :::note Para que la platform view de Android funcione, asegúrate de que tu `MainActivity` extiende `FlutterFragmentActivity`: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: ## Loader durante el onboarding \{#loader-during-onboarding\} Al presentar un onboarding, puede que notes una breve pantalla de carga entre tu splash screen y el onboarding mientras se inicializa la vista subyacente. Puedes gestionar esto de distintas formas según tus necesidades. #### Controlar el splash screen con onDidFinishLoading \{#control-splash-screen-using-ondidfinishloading\} :::note Este enfoque solo está disponible cuando el onboarding se embebe como widget. No está disponible para la presentación como pantalla independiente. ::: El enfoque multiplataforma recomendado es mantener visible tu splash screen o superposición personalizada hasta que el onboarding se haya cargado por completo y luego ocultarla manualmente. Al usar el widget embebido, superpón tu propio widget sobre él y oculta la superposición cuando se dispare `onDidFinishLoading`: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Hide your custom splash screen or overlay here }, // ... other callbacks ) ``` ### Personalizar el loader nativo \{#customize-native-loader\} :::important Este enfoque es específico de plataforma y requiere mantener código de UI nativo. No se recomienda a menos que ya mantengas capas nativas separadas en tu app. ::: Si necesitas personalizar el loader predeterminado, puedes reemplazarlo con layouts específicos de cada plataforma. Este enfoque requiere implementaciones separadas para Android e iOS: - **iOS**: Añade `AdaptyOnboardingPlaceholderView.xib` a tu proyecto de Xcode - **Android**: Crea `adapty_onboarding_placeholder_view.xml` en `res/layout` y define ahí un placeholder ## Personalizar cómo se abren los enlaces en los onboardings \{#customize-how-links-open-in-onboardings\} :::important La personalización de cómo se abren los enlaces en los onboardings está disponible a partir del SDK de Adapty v.3.15.1. ::: Por defecto, los enlaces en los onboardings se abren en un navegador in-app. Esto ofrece una experiencia fluida al mostrar las páginas web dentro de tu aplicación, sin que el usuario tenga que cambiar de app. Si prefieres abrir los enlaces en un navegador externo, puedes personalizar este comportamiento estableciendo el parámetro `externalUrlsPresentation` en `AdaptyWebPresentation.externalBrowser`:
Después puedes usar este ID en tu código y gestionarlo como una acción personalizada. Por ejemplo, si un usuario pulsa un botón personalizado como **Login** o **Allow notifications**, el método delegado `onboardingController` se activará con el caso `.custom(id:)` y el parámetro `actionId` corresponde al **Action ID** del builder. Puedes crear tus propios IDs, como "allowNotifications".
```javascript
// Full-screen presentation
void onboardingViewOnCustomAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
String actionId,
) {
switch (actionId) {
case 'login':
_login();
break;
case 'allow_notifications':
_allowNotifications();
break;
}
}
// Embedded widget
onCustomAction: (meta, actionId) {
_handleCustomAction(actionId);
}
```
:::important
Ten en cuenta que debes gestionar qué ocurre cuando un usuario cierra el onboarding. Por ejemplo, debes dejar de mostrar el propio onboarding.
:::
```javascript showLineNumbers title="Flutter"
// Full-screen presentation
void onboardingViewOnCloseAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
String actionId,
) {
await view.dismiss();
}
// Embedded widget
onCloseAction: (meta, actionId) {
Navigator.of(context).pop();
}
```
2. Haz clic en el nombre del grupo de suscripciones. Verás tus productos listados en la sección **Subscriptions**.
3. Asegúrate de que el producto que estás probando esté marcado como **Ready to Submit**.
4. Compara el ID del producto de la tabla con el que aparece en la pestaña [**Products**](https://app.adapty.io/products) del Adapty Dashboard. Si los IDs no coinciden, copia el ID del producto de la tabla y [crea un producto](create-product) con ese ID en el Adapty Dashboard.
## Paso 3. Comprueba la disponibilidad del producto \{#step-4-check-product-availability\}
1. Vuelve a **App Store Connect** y abre la misma sección **Subscriptions**.
2. Haz clic en el nombre del grupo de suscripciones para ver tus productos.
3. Selecciona el producto que estás probando.
4. Desplázate hasta la sección **Availability** y comprueba que todos los países y regiones requeridos estén listados.
## Paso 4. Comprueba los precios del producto \{#step-5-check-product-prices\}
1. De nuevo, ve a la sección **Monetization** → **Subscriptions** en **App Store Connect**.
2. Haz clic en el nombre del grupo de suscripciones.
3. Selecciona el producto que estás probando.
4. Desplázate hacia abajo hasta **Subscription Pricing** y despliega la sección **Current Pricing for New Subscribers**.
5. Asegúrate de que todos los precios requeridos estén listados.
## Paso 5. Comprueba que el estado de pago de la app, la cuenta bancaria y los formularios fiscales estén activos \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. En la página de inicio de [**App Store Connect**](https://appstoreconnect.apple.com/), haz clic en **Business**.
2. Selecciona el nombre de tu empresa.
3. Desplázate hacia abajo y comprueba que tu **Paid Apps Agreement**, tu **Bank Account** y tus **Tax forms** aparezcan como **Active**.
Siguiendo estos pasos, deberías poder resolver la advertencia `InvalidProductIdentifiers` y tener tus productos disponibles en la store.
## Paso 6. Recrea el producto si está bloqueado \{#step-6-recreate-the-product-if-its-stuck\}
Es posible que los pasos 1–5 pasen todos correctamente —estado `Approved`, Bundle ID coincidente, API key válida— y aun así el SDK devuelva `1000 noProductIDsFound`. En ese caso, puede que el producto esté bloqueado en el registro de Apple. El registro de productos de Apple entra ocasionalmente en un estado en el que un producto existe en la interfaz de App Store Connect pero no está expuesto en la ruta de búsqueda de StoreKit.
Elimina el producto en App Store Connect y vuelve a crearlo con el mismo ID de producto. Espera hasta 24 horas tras la recreación para que los cambios se propaguen.
---
# File: cantMakePayments-flutter
---
---
title: "Solución al error Code-1003 cantMakePayment en Flutter SDK"
description: "Resuelve el error de realización de pagos al gestionar suscripciones en Adapty."
---
El error 1003, `cantMakePayments`, indica que no es posible realizar compras in-app en este dispositivo.
Si encuentras el error `cantMakePayments`, normalmente se debe a una de estas razones:
- Restricciones del dispositivo: El error no está relacionado con Adapty. Consulta las soluciones más abajo.
- Configuración del modo Observer: El método `makePurchase` y el modo Observer no pueden usarse al mismo tiempo. Consulta la sección más abajo.
## Problema: Restricciones del dispositivo \{#issue-device-restrictions\}
| Problema | Solución |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Restricciones de Screen Time | Desactiva las restricciones de compras in-app en [Screen Time](https://support.apple.com/en-us/102470) |
| Cuenta suspendida | Contacta con el soporte de Apple para resolver problemas con la cuenta |
| Restricciones regionales | Usa una cuenta de App Store de una región compatible |
## Problema: Usar el modo Observer y makePurchase a la vez \{#issue-using-both-observer-mode-and-makepurchase\}
Si usas `makePurchases` para gestionar las compras, no necesitas el modo Observer. El [modo Observer](observer-vs-full-mode) solo es necesario si implementas la lógica de compra tú mismo.
Por lo tanto, si usas `makePurchase`, puedes eliminar sin problema la activación del modo Observer del código de inicialización del SDK.
---
# File: flutter-migration-guide-310
---
---
title: "Guía de migración al SDK de Adapty para Flutter 3.10.0"
description: ""
---
El SDK de Adapty 3.10.0 es una versión principal que incorpora mejoras que, sin embargo, pueden requerir algunos pasos de migración por tu parte:
1. Actualiza el método `makePurchase` para usar `AdaptyPurchaseParameters` en lugar de parámetros individuales.
2. Reemplaza `vendorProductIds` por `productIdentifiers` en el modelo `AdaptyPaywall`.
## Actualizar el método makePurchase \{#update-makepurchase-method\}
El método `makePurchase` ahora usa `AdaptyPurchaseParameters` en lugar de los argumentos individuales `subscriptionUpdateParams` e `isOfferPersonalized`. Esto proporciona mayor seguridad de tipos y permite una mayor extensibilidad de los parámetros de compra en el futuro.
```diff showLineNumbers
- final purchaseResult = await adapty.makePurchase(
- product: product,
- subscriptionUpdateParams: subscriptionUpdateParams,
- isOfferPersonalized: true,
- );
+ final parameters = AdaptyPurchaseParametersBuilder()
+ ..setSubscriptionUpdateParams(subscriptionUpdateParams)
+ ..setIsOfferPersonalized(true)
+ ..setObfuscatedAccountId('your-account-id')
+ ..setObfuscatedProfileId('your-profile-id');
+ final purchaseResult = await adapty.makePurchase(
+ product: product,
+ parameters: parameters.build(),
+ );
```
Si no necesitas parámetros adicionales, puedes usar simplemente:
```dart showLineNumbers
final purchaseResult = await adapty.makePurchase(
product: product,
);
```
## Actualizar el uso del modelo AdaptyPaywall \{#update-adaptyp-aywall-model-usage\}
La propiedad `vendorProductIds` ha quedado obsoleta en favor de `productIdentifiers`. La nueva propiedad devuelve objetos `AdaptyProductIdentifier` en lugar de cadenas de texto simples, lo que ofrece información de producto con una estructura más organizada.
```diff showLineNumbers
- paywall.vendorProductIds.map((vendorId) =>
- ListTextTile(title: vendorId)
- ).toList()
+ paywall.productIdentifiers.map((productId) =>
+ ListTextTile(title: productId.vendorProductId)
+ ).toList()
```
El objeto `AdaptyProductIdentifier` proporciona acceso al ID del producto del proveedor a través de la propiedad `vendorProductId`, manteniendo la misma funcionalidad y ofreciendo una mejor estructura para mejoras futuras.
## Compatibilidad con versiones anteriores \{#backward-compatibility\}
Ambos cambios mantienen la compatibilidad con versiones anteriores:
- Los parámetros antiguos en `makePurchase` están obsoletos, pero siguen funcionando
- La propiedad `vendorProductIds` está obsoleta, pero sigue siendo accesible
- El código existente seguirá funcionando, aunque verás advertencias de obsolescencia
Te recomendamos actualizar tu código para usar las nuevas API y garantizar la compatibilidad futura, además de aprovechar la mayor seguridad de tipos y extensibilidad.
---
# File: flutter-migration-guide-38
---
---
title: "Migrar el SDK de Adapty para Flutter a v. 3.8"
description: "Migra al SDK de Adapty para Flutter v3.8 para obtener mejor rendimiento y nuevas funciones de monetización."
---
El SDK 3.8.0 de Adapty es una versión mayor que incluye mejoras que pueden requerir algunos pasos de migración por tu parte.
1. Actualiza los nombres de la clase observadora y sus métodos.
2. Actualiza el nombre del método de paywalls de respaldo.
3. Actualiza el nombre de la clase de vista en los métodos de manejo de eventos.
## Actualiza los nombres de la clase observadora y sus métodos \{#update-observer-class-and-method-names\}
La clase observadora y su método de registro han sido renombrados:
```diff showLineNumbers
- class MyObserver extends AdaptyUIObserver {
+ class MyObserver extends AdaptyUIPaywallsEventsObserver {
@override
void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) {
// Handle action
}
}
// Register observer
- AdaptyUI().setObserver(this);
+ AdaptyUI().setPaywallsEventsObserver(this);
```
## Actualiza el nombre del método de paywalls de respaldo \{#update-fallback-paywalls-method-name\}
El método para configurar los paywalls de respaldo ha sido simplificado:
```diff showLineNumbers
try {
- await Adapty.setFallbackPaywalls(assetId);
+ await Adapty.setFallback(assetId);
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
// handle the error
}
```
## Actualiza el nombre de la clase de vista en los métodos de manejo de eventos \{#update-view-class-name-in-event-handling-methods\}
Todos los métodos de manejo de eventos ahora usan la nueva clase `AdaptyUIPaywallView` en lugar de `AdaptyUIView`:
```diff showLineNumbers
- void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action)
+ void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action)
- void paywallViewDidSelectProduct(AdaptyUIView view, AdaptyPaywallProduct product)
+ void paywallViewDidSelectProduct(AdaptyUIPaywallView view, AdaptyPaywallProduct product)
- void paywallViewDidStartPurchase(AdaptyUIView view, AdaptyPaywallProduct product)
+ void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product)
- void paywallViewDidFinishPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyProfile profile)
+ void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyProfile profile)
- void paywallViewDidFailPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyError error)
+ void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error)
- void paywallViewDidFinishRestore(AdaptyUIView view, AdaptyProfile profile)
+ void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile)
- void paywallViewDidFailRestore(AdaptyUIView view, AdaptyError error)
+ void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error)
- void paywallViewDidFailLoadingProducts(AdaptyUIView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error)
+ void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error)
- void paywallViewDidFailRendering(AdaptyUIView view, AdaptyError error)
+ void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error)
```
---
# File: migration-to-flutter-sdk-34
---
---
title: "Migrar Adapty Flutter SDK a la v. 3.4"
description: "Migra al Adapty Flutter SDK v3.4 para mejor rendimiento y nuevas funciones de monetización."
---
Adapty SDK 3.4.0 es una versión mayor que introduce mejoras que requieren pasos de migración por tu parte.
## Actualizar los archivos de paywall de respaldo \{#update-fallback-paywall-files\}
Actualiza tus archivos de paywall de respaldo para garantizar la compatibilidad con la nueva versión del SDK:
1. [Descarga los archivos de paywall de respaldo actualizados](fallback-paywalls) desde el Adapty Dashboard.
2. [Reemplaza los paywalls de respaldo existentes en tu app](flutter-use-fallback-paywalls) con los nuevos archivos.
## Actualizar la implementación del modo Observer \{#update-implementation-of-observer-mode\}
Si usas el modo Observer, asegúrate de actualizar su implementación.
Anteriormente, se usaban distintos métodos para reportar transacciones a Adapty. En la nueva versión, el método `reportTransaction` debe usarse de forma consistente tanto en Android como en iOS. Este método reporta explícitamente cada transacción a Adapty, asegurando que sea reconocida. Si se usó un paywall, pasa el ID de variación para vincular la transacción con él.
:::warning
**¡No omitas el reporte de transacciones!**
Si no llamas a `reportTransaction`, Adapty no reconocerá la transacción, no aparecerá en los análisis y no se enviará a las integraciones.
:::
```diff showLineNumbers
- // every time when calling transaction.finish()
- if (Platform.isAndroid) {
- try {
- await Adapty().restorePurchases();
- } on AdaptyError catch (adaptyError) {
- // handle the error
- } catch (e) {
- }
- }
try {
// every time when calling transaction.finish()
await Adapty().reportTransaction(
"YOUR_TRANSACTION_ID",
variationId: "PAYWALL_VARIATION_ID", // optional
);
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
// handle the error
}
```
---
# File: migration-to-flutter330
---
---
title: "Migrar el SDK de Adapty Flutter a v. 3.3"
description: "Migra al SDK de Adapty Flutter v3.3 para mejor rendimiento y nuevas funcionalidades de monetización."
---
Adapty SDK 3.3.0 es una versión mayor que incluye mejoras que pueden requerir algunos pasos de migración de tu parte.
1. Actualiza el método para proporcionar paywalls de respaldo.
2. Elimina el método `getProductsIntroductoryOfferEligibility`.
3. Actualiza las configuraciones de integración para Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase y Google Analytics, Mixpanel, OneSignal, Pushwoosh.
4. Actualiza la implementación del modo Observer.
## Actualiza el método para proporcionar paywalls de respaldo \{#update-method-for-providing-fallback-paywalls\}
Anteriormente, el método requería el paywall de respaldo como una cadena JSON (`jsonString`), pero ahora recibe la ruta al archivo de respaldo local (`assetId`).
```diff showLineNumbers
import 'dart:async' show Future;
import 'dart:io' show Platform;
-import 'package:flutter/services.dart' show rootBundle;
-final filePath = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json';
-final jsonString = await rootBundle.loadString(filePath);
+final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json';
try {
- await adapty.setFallbackPaywalls(jsonString);
+ await adapty.setFallbackPaywalls(assetId);
} on AdaptyError catch (adaptyError) {
// handle the error
} catch (e) {
}
```
Para ver el ejemplo de código completo, consulta la página [Usar paywalls de respaldo](flutter-use-fallback-paywalls).
## Elimina el método `getProductsIntroductoryOfferEligibility` \{#remove-getproductsintroductoryoffereligibility-method\}
Antes del SDK de Adapty iOS 3.3.0, el objeto de producto siempre incluía las ofertas, independientemente de si el usuario era elegible. Tenías que verificar la elegibilidad manualmente antes de usar la oferta.
Ahora, el objeto de producto solo incluye una oferta si el usuario es elegible. Esto significa que ya no necesitas verificar la elegibilidad: si hay una oferta presente, el usuario es elegible.
## Actualiza la configuración del SDK de integraciones de terceros \{#update-third-party-integration-sdk-configuration\}
Para garantizar que las integraciones funcionen correctamente con el SDK de Adapty Flutter 3.3.0 y versiones posteriores, actualiza las configuraciones de tu SDK para las siguientes integraciones tal como se describe en las secciones a continuación.
### Adjust \{#adjust\}
Actualiza el código de tu app como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Adjust](adjust#connect-your-app-to-adjust).
```diff showLineNumbers
import 'package:adjust_sdk/adjust.dart';
import 'package:adjust_sdk/adjust_config.dart';
try {
final adid = await Adjust.getAdid();
if (adid == null) {
// handle the error
}
+ await Adapty().setIntegrationIdentifier(
+ key: "adjust_device_id",
+ value: adid,
+ );
final attributionData = await Adjust.getAttribution();
var attribution = MapUn valor booleano que controla el [modo Observer](observer-vs-full-mode). Actívalo si gestionas las compras y el estado de las suscripciones tú mismo y usas Adapty solo para enviar eventos de suscripción y analíticas.
El valor predeterminado es `false`.
🚧 Al ejecutarse en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlas tú.
| | **withCustomerUserId** | opcional | Un identificador del usuario en tu sistema. Lo enviamos en eventos de suscripción y analíticos para atribuir los eventos al perfil correcto. También puedes buscar clientes por `customerUserId` en el menú [**Profiles and Segments**](https://app.adapty.io/profiles/users). | | **withIdfaCollectionDisabled** | opcional |Ponlo en `true` para deshabilitar la recopilación y el uso compartido del IDFA.
la dirección IP del usuario.
El valor predeterminado es `false`.
Para más detalles sobre la recopilación del IDFA, consulta la sección [Integración de analíticas](analytics-integration#disable-collection-of-advertising-identifiers).
| | **withIpAddressCollectionDisabled** | opcional |Ponlo en `true` para deshabilitar la recopilación y el uso compartido de la dirección IP del usuario.
El valor predeterminado es `false`.
| ### Activar el módulo AdaptyUI del SDK de Adapty \{#activate-adaptyui-module-of-adapty-sdk\} Solo necesitas configurar el módulo AdaptyUI si planeas usar el [Paywall Builder](adapty-paywall-builder): ```dart showLineNumbers title="Dart" try { final mediaCache = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 100 * 1024 * 1024, // 100MB memoryStorageCountLimit: 2147483647, // 2^31 - 1, max int value in Dart diskStorageSizeLimit: 100 * 1024 * 1024, // 100MB ); await AdaptyUI().activate( configuration: AdaptyUIConfiguration(mediaCache: mediaCache), observer:
### Durante el inicio de sesión/registro \{#during-loginsignup\}
Si identificas a los usuarios después del inicio de la app (por ejemplo, tras iniciar sesión o registrarse), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario**, Adapty pasará a trabajar con el perfil asociado a ese customer user ID.
:::important
Los customer user IDs deben ser únicos para cada usuario. Si defines el valor del parámetro de forma fija, todos los usuarios se considerarán como uno solo.
:::
Siempre usa `await` con `identify` antes de llamar a otros métodos del SDK. Las llamadas concurrentes producen `#3006 profileWasChanged` o recaen sobre el perfil anónimo. Consulta [Orden de llamadas en el SDK de iOS](ios-sdk-call-order).
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués brasileño.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos utilizarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En ese caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que la CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo de espera, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede estar compuesta por diferentes solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) con una lista de IDs de producto, el identificador del paywall, Remote Config y otras propiedades. | ## Obtener la configuración de vista de un paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el toggle **Show on device** en el paywall builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperarse. ::: Después de obtener el paywall, comprueba si incluye una configuración de vista, lo que indica que fue creado con Paywall Builder. Esto te guiará sobre cómo mostrar el paywall. Si la configuración de vista está presente, trátalo como un paywall de Paywall Builder; si no, [trátalo como un paywall con Remote Config](present-remote-config-paywalls). Usa el método `getPaywallConfiguration` para cargar la configuración de vista. ```swift showLineNumbers guard paywall.hasViewConfiguration else { // use your custom logic return } do { let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall, products: products ) // use loaded configuration } catch { // handle the error } ``` Parámetros: | Parámetro | Presencia | Descripción | | :----------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | obligatorio | Un objeto `AdaptyPaywall` para obtener un controlador para el paywall deseado. | | **loadTimeout** | por defecto: 5 seg | Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo de espera, se devolverán los datos en caché o el respaldo local. Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede estar compuesta por diferentes solicitudes internamente. | | **products** | opcional | Proporciona un array de `AdaptyPaywallProducts` para optimizar el tiempo de visualización de los productos en pantalla. Si se pasa `nil`, AdaptyUI obtendrá automáticamente los productos necesarios. | :::note Si usas varios idiomas, aprende cómo añadir una [localización de Paywall Builder](add-paywall-locale-in-adapty-paywall-builder) y cómo usar los códigos de idioma correctamente [aquí](localizations-and-locale-codes). ::: Una vez cargado, [presenta el paywall](ios-present-paywalls). ## Obtener un paywall para la audiencia predeterminada para cargarlo más rápido \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Normalmente, los paywalls se obtienen casi al instante, así que no necesitas preocuparte por acelerar este proceso. Sin embargo, si tienes muchas audiencias y paywalls y tus usuarios tienen una conexión a internet débil, obtener un paywall puede tardar más de lo deseable. En esos casos, puede que quieras mostrar un paywall predeterminado para garantizar una experiencia de usuario fluida en lugar de no mostrar ningún paywall. Para solucionar esto, puedes usar el método `getPaywallForDefaultAudience`, que obtiene el paywall del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el paywall con el método `getPaywall`, como se detalla en la sección [Obtener información del paywall](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) anterior. :::warning Por qué recomendamos usar `getPaywall` El método `getPaywallForDefaultAudience` tiene algunos inconvenientes importantes: - **Posibles problemas de compatibilidad con versiones anteriores**: Si necesitas mostrar paywalls diferentes para distintas versiones de la app (actual y futuras), puedes encontrarte con dificultades. Tendrás que diseñar paywalls compatibles con la versión actual (heredada) o aceptar que los usuarios con la versión actual (heredada) puedan tener problemas con paywalls que no se renderizan. - **Pérdida de targeting**: Todos los usuarios verán el mismo paywall diseñado para la audiencia **All Users**, lo que significa que perderás el targeting personalizado (incluyendo por países, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a aceptar estos inconvenientes para beneficiarte de una obtención más rápida del paywall, usa el método `getPaywallForDefaultAudience` como se indica a continuación. De lo contrario, usa `getPaywall` descrito [anteriormente](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder). ::: ```swift showLineNumbers Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` :::note El método `getPaywallForDefaultAudience` está disponible a partir de la versión 2.11.2 del SDK de iOS. ::: | Parámetro | Presencia | Descripción | |---------|--------|-----------| | **placementId** | obligatorio | El identificador del [Placement](placements). Es el valor que especificaste al crear un placement en tu Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués brasileño.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos utilizarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En ese caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
| ## Personalizar recursos \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los recursos personalizados. Las imágenes y vídeos principales tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de recursos personalizados, puedes apuntar a estos elementos por sus IDs y personalizar su comportamiento. Para otras imágenes y vídeos, necesitas [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta función, actualiza el SDK de Adapty para iOS a la versión 3.7.0 o superior. ::: Aquí tienes un ejemplo de cómo proporcionar recursos personalizados mediante un diccionario simple: ```swift showLineNumbers let customAssets: [String: AdaptyCustomAsset] = [ // Show a local image using a custom ID "custom_image": .image( .uiImage(value: UIImage(named: "image_name")!) ), // Show a local preview image while a remote main image is loading "hero_image": .image( .remote( url: URL(string: "https://example.com/image.jpg")!, preview: UIImage(named: "preview_image") ) ), // Show a local video with a preview image "hero_video": .video( .file( url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!, preview: .uiImage(value: UIImage(named: "video_preview")!) ) ), ] let paywallConfig = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall, assetsResolver: customAssets ) ``` :::note Si no se encuentra un recurso, el paywall usará su apariencia predeterminada. ::: ## Configurar temporizadores definidos por el desarrollador \{#set-up-developer-defined-timers\} Para usar temporizadores personalizados en tu app móvil, crea un objeto que siga el protocolo `AdaptyTimerResolver`. Este objeto define cómo debe renderizarse cada temporizador personalizado. Si lo prefieres, puedes usar directamente un diccionario `[String: Date]`, ya que ya cumple con este protocolo. Aquí tienes un ejemplo: ```swift showLineNumbers @MainActor struct AdaptyTimerResolverImpl: AdaptyTimerResolver { func timerEndAtDate(for timerId: String) -> Date { switch timerId { case "CUSTOM_TIMER_6H": Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours case "CUSTOM_TIMER_NY": Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0) default: Date(timeIntervalSinceNow: 3600.0) // 1 hour } } } ``` En este ejemplo, `CUSTOM_TIMER_NY` y `CUSTOM_TIMER_6H` son los **Timer ID** de los temporizadores definidos por el desarrollador que configuraste en el Adapty Dashboard. El `timerResolver` garantiza que tu app actualice dinámicamente cada temporizador con el valor correcto. Por ejemplo: - `CUSTOM_TIMER_NY`: El tiempo restante hasta el final del temporizador, como el día de Año Nuevo. - `CUSTOM_TIMER_6H`: El tiempo restante en un período de 6 horas que comenzó cuando el usuario abrió el paywall. --- # File: ios-present-paywalls --- --- title: "Presentar paywalls del nuevo Paywall Builder en el SDK de iOS" description: "Descubre cómo presentar paywalls en iOS para aumentar las conversiones y los ingresos." --- Si has personalizado un paywall con el Paywall Builder, no necesitas preocuparte por renderizarlo en el código de tu app para mostrárselo al usuario. Ese paywall ya contiene tanto lo que debe mostrarse como la forma en que debe hacerlo. :::warning Esta guía es para **[paywalls del nuevo Paywall Builder](adapty-paywall-builder)**. El proceso para presentar paywalls varía según la versión del Paywall Builder con la que se diseñaron, si son paywalls de Remote Config o si usas el [modo Observer](observer-vs-full-mode). - Para presentar **paywalls de Remote Config**, consulta [Renderizar paywall diseñado con Remote Config](present-remote-config-paywalls). - Para presentar **paywalls en modo Observer**, consulta [iOS - Presentar paywalls del Paywall Builder en modo Observer](ios-present-paywall-builder-paywalls-in-observer-mode) ::: Para obtener el objeto `AdaptyUI.PaywallConfiguration` que se usa a continuación, consulta [Obtener paywalls del Paywall Builder y su configuración](get-pb-paywalls). ## Presentar paywalls en SwiftUI \{#present-paywalls-in-swiftui\} ### Presentar como vista modal \{#present-as-a-modal-view\} Para mostrar el paywall visual en la pantalla del dispositivo como vista modal, usa el modificador `.paywall` en SwiftUI: ```swift showLineNumbers title="SwiftUI" @State var paywallPresented = false // ensure that you manage this variable state and set it to `true` at the moment you want to show the paywall var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywallConfiguration:
## El número de vistas del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El contador de vistas del paywall muestra el doble del número esperado.
**Causa**: Es posible que estés llamando a `logShowPaywall` en tu código, lo que duplica el contador de vistas si usas el Paywall Builder. En los paywalls diseñados con el Paywall Builder, el seguimiento de analíticas es automático, por lo que no necesitas usar este método.
**Solución**: Asegúrate de no llamar a `logShowPaywall` en tu código si usas el Paywall Builder.
## Otros problemas \{#other-issues\}
**Problema**: Estás experimentando otros problemas relacionados con el Paywall Builder que no se tratan arriba.
**Solución**: Migra el SDK a la versión más reciente siguiendo las [guías de migración](ios-sdk-migration-guides) si es necesario. Muchos problemas se resuelven en versiones más nuevas del SDK.
---
# File: ios-quickstart-manual
---
---
title: "Habilitar compras en tu paywall personalizado en iOS SDK"
description: "Integra el SDK de Adapty en tus paywalls personalizados de iOS para habilitar compras in-app."
---
Esta guía describe cómo integrar Adapty en tus paywalls personalizados. Mantén el control total sobre la implementación del paywall, mientras el SDK de Adapty obtiene los productos, gestiona las nuevas compras y restaura las anteriores.
:::important
**Esta guía es para desarrolladores que implementan paywalls personalizados.** Si quieres la forma más sencilla de habilitar compras, usa el [Adapty Paywall Builder](ios-quickstart-paywalls). Con Paywall Builder, creas paywalls en un editor visual sin código, Adapty gestiona toda la lógica de compras automáticamente y puedes probar distintos diseños sin volver a publicar tu app.
:::
## Antes de empezar \{#before-you-start\}
### Configura los productos \{#set-up-products\}
Para habilitar las compras in-app, necesitas entender tres conceptos clave:
- [**Productos**](product) – cualquier cosa que los usuarios pueden comprar (suscripciones, consumibles, acceso de por vida)
- [**Paywalls**](paywalls) – configuraciones que definen qué productos ofrecer. En Adapty, los paywalls son la única forma de recuperar productos, pero este diseño te permite modificar productos, precios y ofertas sin tocar el código de tu app.
- [**Placements**](placements) – dónde y cuándo mostrar los paywalls en tu app (como `main`, `onboarding`, `settings`). Configuras los paywalls para los placements en el dashboard y luego los solicitas por ID de placement en tu código. Esto facilita ejecutar pruebas A/B y mostrar diferentes paywalls a distintos usuarios.
Asegúrate de entender estos conceptos aunque trabajes con tu paywall personalizado. Básicamente, son tu forma de gestionar los productos que vendes en tu app.
Para implementar tu paywall personalizado, necesitarás crear un **paywall** y añadirlo a un **placement**. Esta configuración te permite recuperar tus productos. Para entender qué tienes que hacer en el dashboard, sigue la guía de inicio rápido [aquí](quickstart).
### Gestión de usuarios \{#manage-users\}
Puedes trabajar con o sin autenticación backend en tu lado.
Sin embargo, el SDK de Adapty gestiona los usuarios anónimos e identificados de forma diferente. Lee la [guía de inicio rápido de identificación](ios-quickstart-identify) para entender los detalles y asegurarte de que estás trabajando con los usuarios correctamente.
## Paso 1. Obtener productos \{#step-1-get-products\}
Para recuperar productos para tu paywall personalizado, necesitas:
1. Obtener el objeto `paywall` pasando el ID del [placement](placements) al método `getPaywall`.
2. Obtener el array de productos para este paywall usando el método `getPaywallProducts`.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este escenario, los usuarios podrían no obtener los datos más recientes, pero disfrutarán de tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede estar compuesta por diferentes peticiones internamente.
| ¡No escribas los IDs de producto directamente en el código! Como los paywalls se configuran de forma remota, los productos disponibles, su número y las ofertas especiales (como pruebas gratuitas) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, tu app debería mostrar esos 2 productos. Sin embargo, si más adelante obtienes 3 productos, tu app debería mostrar los 3 sin necesidad de cambios en el código. Lo único que debes incluir directamente en el código es el ID del placement. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) con: una lista de IDs de producto, el identificador del paywall, Remote Config y varias otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tienes el paywall, puedes consultar el array de productos que le corresponde:opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En este escenario, los usuarios podrían no obtener los datos más recientes, pero disfrutarán de tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
| --- # File: present-remote-config-paywalls --- --- title: "Mostrar un paywall diseñado con Remote Config en iOS SDK" description: "Descubre cómo presentar paywalls de Remote Config en Adapty para personalizar la experiencia del usuario." --- Si has personalizado un paywall usando Remote Config, necesitarás implementar el renderizado en el código de tu app para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú decides qué incluir y cómo se ve tu paywall. Te proporcionamos un método para obtener la configuración remota, dándote autonomía para mostrar tu paywall personalizado configurado mediante Remote Config. No olvides [comprobar si un usuario es elegible para una oferta introductoria en iOS](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios) y adaptar la vista del paywall para gestionar el caso en que sea elegible. ## Obtener el Remote Config del paywall y mostrarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores necesarios.Si la solicitud fue exitosa, la respuesta contiene este objeto. Un objeto [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas de un usuario dentro de la app.
Comprueba el estado del nivel de acceso para verificar si el usuario tiene el acceso requerido a la app.
| :::warning **Nota:** si todavía usas una versión de StoreKit de Apple inferior a v2.0 y una versión de Adapty SDK inferior a v.2.9.0, debes proporcionar el [secreto compartido de Apple App Store](app-store-connection-configuration#step-5-enter-app-store-shared-secret). Este método está actualmente deprecado por Apple. ::: ## Compras in-app desde el App Store \{#in-app-purchases-from-the-app-store\} Cuando un usuario inicia una compra en el App Store y la transacción se traslada a tu app, tienes dos opciones: - **Procesar la transacción de inmediato:** Devuelve `true` en `shouldAddStorePayment`. Esto mostrará la pantalla del sistema de compra de Apple de inmediato. - **Guardar el objeto del producto para procesarlo más tarde:** Devuelve `false` en `shouldAddStorePayment` y después llama a `makePurchase` con el producto guardado cuando sea oportuno. Esto puede ser útil si necesitas mostrar algo personalizado al usuario antes de iniciar la compra. Aquí tienes el código completo: ```swift showLineNumbers title="Swift" final class YourAdaptyDelegateImplementation: AdaptyDelegate { nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool { // 1a. // Return `true` to continue the transaction in your app. The Apple purchase system screen will show automatically. // 1b. // Store the product object and return `false` to defer or cancel the transaction. false } // 2. Continue the deferred purchase later on by passing the product to `makePurchase` when the timing is appropriate func continueDeferredPurchase() async { let storedProduct: AdaptyDeferredProduct = // get the product object from 1b. do { try await Adapty.makePurchase(product: storedProduct) } catch { // handle the error } } } ``` ## Canjear códigos de oferta en iOS \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';Un objeto [`AdaptyProfile`](https://swift.adapty.io/documentation/adapty/adaptyprofile). Este modelo contiene información sobre niveles de acceso, suscripciones y compras únicas.
Comprueba el **estado del nivel de acceso** para determinar si el usuario tiene acceso a la app.
| :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: --- # File: ios-transaction-management --- --- title: "Gestión avanzada de transacciones en el SDK de iOS" description: "Finaliza transacciones manualmente en tu app de iOS con el SDK de Adapty." --- :::note La gestión avanzada de transacciones está disponible en el SDK de Adapty para iOS a partir de la versión 3.12. ::: La gestión avanzada de transacciones en Adapty te da mayor control sobre cómo se procesan, verifican y finalizan las transacciones. Esta funcionalidad introduce tres características opcionales que trabajan en conjunto: | Característica | Propósito | |-------------------------------------------------------------|----------| | [`appAccountToken`](#assign-appaccounttoken) | Vincula las transacciones de Apple con tu ID de usuario interno | | [`jwsTransaction`](#access-the-jws-representation) | Proporciona el payload de transacción firmado por Apple para validación | | [Finalización manual](#control-transaction-finishing-behavior) | Permite finalizar transacciones solo después de que tu backend confirme el éxito | En conjunto, estas herramientas te permiten construir flujos de validación personalizados robustos mientras Adapty sigue sincronizando las transacciones con su backend. :::important La mayoría de las apps no necesitan esto. Por defecto, Adapty valida y finaliza automáticamente las transacciones de StoreKit. Usa esta guía solo si ejecutas tu propia validación en el backend o quieres controlar por completo el ciclo de vida de las compras. ::: ## Asignar `appAccountToken` \{#assign-appaccounttoken\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)) es un **UUID** que te permite vincular las transacciones de la App Store con la identidad interna de tus usuarios. StoreKit asocia este token con cada transacción, de modo que tu backend puede relacionar los datos de la App Store con tus usuarios. Usa un UUID estable generado por usuario y reutilízalo para la misma cuenta en todos los dispositivos. Esto garantiza que las compras y las notificaciones de la App Store queden correctamente vinculadas. Puedes establecer el token de dos formas: durante la activación del SDK o al identificar al usuario. :::important Siempre debes pasar `appAccountToken` junto con `customerUserId`. Si solo pasas el token, no se incluirá en la transacción. :::Para StoreKit 1: un objeto [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction).
Para StoreKit 2: objeto [Transaction](https://developer.apple.com/documentation/storekit/transaction).
|
phoneNumber
firstName
lastName
| String | | gender | Enum, los valores permitidos son: `female`, `male`, `other` | | birthday | Date | ### Atributos de usuario personalizados \{#custom-user-attributes\} Puedes definir tus propios atributos personalizados, que normalmente están relacionados con el uso de tu app. Por ejemplo, en apps de fitness pueden ser el número de entrenamientos por semana; en apps de aprendizaje de idiomas, el nivel de conocimiento del usuario, etc. Puedes usarlos en segmentos para crear paywalls y ofertas dirigidas, y también en analíticas para identificar qué métricas de producto influyen más en los ingresos. ```swift showLineNumbers do { builder = try builder.with(customAttribute: "value1", forKey: "key1") } catch { // handle key/value validation error } ``` Para eliminar una clave existente, usa el método `.withRemoved(customAttributeForKey:)`: ```swift showLineNumbers do { builder = try builder.withRemoved(customAttributeForKey: "key2") } catch { // handle error } ``` A veces necesitas saber qué atributos personalizados ya están definidos. Para ello, usa el campo `customAttributes` del objeto `AdaptyProfile`. :::warning Ten en cuenta que el valor de `customAttributes` puede estar desactualizado, ya que los atributos de usuario pueden enviarse desde distintos dispositivos en cualquier momento, por lo que los atributos en el servidor podrían haber cambiado desde la última sincronización. ::: ### Límites \{#limits\} - Hasta 30 atributos personalizados por usuario. - Los nombres de clave tienen hasta 30 caracteres. El nombre de la clave puede incluir caracteres alfanuméricos y cualquiera de los siguientes: `_` `-` `.` - El valor puede ser una cadena de texto o un número decimal con un máximo de 50 caracteres. --- # File: subscription-status --- --- title: "Comprobar el estado de suscripción en iOS SDK" description: "Rastrea y gestiona el estado de suscripción de los usuarios en Adapty para mejorar la retención de clientes." --- Con Adapty, hacer seguimiento del estado de suscripción es muy sencillo. No tienes que insertar manualmente los IDs de producto en tu código. En su lugar, puedes confirmar fácilmente el estado de suscripción de un usuario comprobando si tiene un [nivel de acceso](access-level) activo. Antes de empezar a comprobar el estado de suscripción, configura las [Notificaciones del servidor de App Store](enable-app-store-server-notifications). ## Nivel de acceso y el objeto AdaptyProfile \{#access-level-and-the-adaptyprofile-object\} Los niveles de acceso son propiedades del objeto [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile). Te recomendamos recuperar el perfil cuando tu app arranque, por ejemplo al [identificar a un usuario](identifying-users#set-customer-user-id-on-configuration), y actualizarlo cada vez que se produzcan cambios. Así podrás usar el objeto de perfil sin tener que solicitarlo repetidamente. Para recibir notificaciones de las actualizaciones del perfil, escucha los cambios tal como se describe en la sección [Escuchar actualizaciones del estado de suscripción](subscription-status#listening-for-subscription-status-updates) más abajo. :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: ## Obtener el nivel de acceso desde el servidor \{#retrieving-the-access-level-from-the-server\} Para obtener el nivel de acceso desde el servidor, usa el método `.getProfile()`:Un objeto [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile). En general, solo necesitas comprobar el estado del nivel de acceso del perfil para determinar si el usuario tiene acceso premium a la app.
El método `.getProfile` devuelve el resultado más actualizado, ya que siempre intenta consultar la API. Si por algún motivo (por ejemplo, sin conexión a internet) el SDK de Adapty no puede obtener información del servidor, se devolverán los datos de la caché. También es importante destacar que el SDK de Adapty actualiza la caché de `AdaptyProfile` periódicamente para mantener esta información lo más actualizada posible.
| El método `.getProfile()` te proporciona el perfil del usuario a partir del cual puedes obtener el estado del nivel de acceso. Puedes tener múltiples niveles de acceso por app. Por ejemplo, si tienes una app de noticias y vendes suscripciones a diferentes temáticas de forma independiente, puedes crear los niveles de acceso "sports" y "science". Pero la mayoría de las veces solo necesitarás un nivel de acceso; en ese caso, puedes usar simplemente el nivel de acceso predeterminado "premium". A continuación tienes un ejemplo para comprobar el nivel de acceso predeterminado "premium":opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita arriba y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el límite, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que, en casos excepcionales, este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede implicar distintas solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Un objeto [`AdaptyOnboarding`](https://swift.adapty.io/documentation/adapty/adaptyonboarding) con: el identificador y la configuración del onboarding, Remote Config y varias otras propiedades. | ## Acelerar la obtención del onboarding con el onboarding de audiencia predeterminada \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Normalmente, los onboardings se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, en casos en los que tienes muchas audiencias y onboardings, y tus usuarios tienen una conexión a internet débil, la obtención de un onboarding puede tardar más de lo deseado. En esas situaciones, puede que quieras mostrar un onboarding predeterminado para garantizar una experiencia fluida en lugar de no mostrar ninguno. Para abordar esto, puedes usar el método `getOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, como se detalla en la sección [Obtener un onboarding](#fetch-onboarding) anterior. :::warning Considera usar `getOnboarding` en lugar de `getOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: Puede generar problemas al soportar múltiples versiones de la app, lo que requiere diseños compatibles con versiones anteriores o aceptar que las versiones más antiguas puedan mostrarse incorrectamente. - **Sin personalización**: Solo muestra contenido para la audiencia "All Users", eliminando la segmentación basada en país, atribución o atributos personalizados. Si la velocidad de obtención supera estos inconvenientes para tu caso de uso, utiliza `getOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getOnboarding` como se describe [arriba](#fetch-onboarding). ::: ```swift showLineNumbers Adapty.getOnboardingForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(onboarding): // the requested onboarding case let .failure(error): // handle the error } } ``` Parámetros: | Parámetro | Presencia | Descripción | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita arriba y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: ios-present-onboardings --- --- title: "Mostrar onboardings en el SDK de iOS" description: "Descubre cómo mostrar onboardings en iOS para aumentar las conversiones y los ingresos." --- Si has personalizado un onboarding con el builder, no necesitas preocuparte por renderizarlo en el código de tu app para mostrárselo al usuario. Ese onboarding ya incluye tanto lo que debe mostrarse como la forma en que debe hacerlo. Antes de empezar, asegúrate de que: 1. Tienes instalado el [SDK de Adapty para iOS](sdk-installation-ios) 3.8.0 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). ## Mostrar onboardings en Swift \{#present-onboardings-in-swift\} Para mostrar el onboarding visual en la pantalla del dispositivo, sigue estos pasos: 1. Obtén la configuración de la vista del onboarding con el método `.getOnboardingConfiguration`. 2. Inicializa el onboarding visual que quieres mostrar usando el método `.onboardingController`: Parámetros de la solicitud: | Parámetro | Presencia | Descripción | |:-------------------------------|:-----------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onboarding configuration** | obligatorio | Un objeto `AdaptyUI.OnboardingConfiguration` con todas las propiedades del onboarding. Usa el método `AdaptyUI.getOnboardingConfiguration` para obtenerlo. | | **delegate** | obligatorio | Un `AdaptyOnboardingControllerDelegate` para escuchar los eventos del onboarding. | Devuelve: | Objeto | Descripción | |:-------------------------------|:---------------------------------------------------------------| | **AdaptyOnboardingController** | Un objeto que representa la pantalla del onboarding solicitado | 3. Una vez creado el objeto correctamente, puedes mostrarlo en la pantalla del dispositivo: ```swift showLineNumbers title="Swift" import Adapty import AdaptyUI // 0. Get an onboarding if you haven't done it yet let onboarding = try await Adapty.getOnboarding(placementId: "YOUR_PLACEMENT_ID") // 1. Obtain the onboarding view configuration: let configuration = try AdaptyUI.getOnboardingConfiguration(forOnboarding: onboarding) // 2. Create Onboarding View Controller let onboardingController = try AdaptyUI.onboardingController( with: configuration, delegate:
Luego puedes usar este ID en tu código y gestionarlo como una acción personalizada. Por ejemplo, si un usuario pulsa un botón personalizado como **Login** o **Allow notifications**, se activará el método delegado `onboardingController` con el caso `.custom(id:)` y el parámetro `actionId` corresponde al **Action ID** del builder. Puedes crear tus propios IDs, como "allowNotifications".
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onCustomAction action: AdaptyOnboardingsCustomAction) {
if action.actionId == "allowNotifications" {
// Request notification permissions
}
}
func onboardingController(_ controller: AdaptyOnboardingController, didFailWithError error: AdaptyUIError) {
// Handle errors
}
```
:::important
Ten en cuenta que debes gestionar lo que ocurre cuando el usuario cierra el onboarding. Por ejemplo, debes dejar de mostrar el onboarding.
:::
Por ejemplo:
```swift showLineNumbers
func onboardingController(_ controller: AdaptyOnboardingController, onCloseAction action: AdaptyOnboardingsCloseAction) {
controller.dismiss(animated: true)
}
```
2. Haz clic en el nombre del grupo de suscripciones. Verás tus productos listados en la sección **Subscriptions**.
3. Asegúrate de que el producto que estás probando figure como **Ready to Submit**. Si no es así, sigue las instrucciones de la página [Producto en App Store](app-store-products).
4. Compara el ID del producto de la tabla con el que aparece en la pestaña [**Products**](https://app.adapty.io/products) del Adapty Dashboard. Si los IDs no coinciden, copia el ID del producto de la tabla y [crea un producto](create-product) con ese ID en el Adapty Dashboard.
## Paso 3. Verifica la disponibilidad del producto \{#step-4-check-product-availability\}
1. Vuelve a **App Store Connect** y abre la misma sección **Subscriptions**.
2. Haz clic en el nombre del grupo de suscripciones para ver tus productos.
3. Selecciona el producto que estás probando.
4. Desplázate hasta la sección **Availability** y comprueba que todos los países y regiones necesarios están listados.
## Paso 4. Verifica los precios del producto \{#step-5-check-product-prices\}
1. De nuevo, ve a la sección **Monetization** → **Subscriptions** en **App Store Connect**.
2. Haz clic en el nombre del grupo de suscripciones.
3. Selecciona el producto que estás probando.
4. Desplázate hacia abajo hasta **Subscription Pricing** y expande la sección **Current Pricing for New Subscribers**.
5. Asegúrate de que todos los precios necesarios están listados.
## Paso 5. Verifica que el estado de pago de la app, la cuenta bancaria y los formularios fiscales estén activos
1. En la página de inicio de [**App Store Connect**](https://appstoreconnect.apple.com/), haz clic en **Business**.
2. Selecciona el nombre de tu empresa.
3. Desplázate hacia abajo y comprueba que tu **Paid Apps Agreement**, **Bank Account** y **Tax forms** aparecen todos como **Active**.
Siguiendo estos pasos, deberías poder resolver la advertencia `InvalidProductIdentifiers` y publicar tus productos en el store.
## Paso 6. Vuelve a crear el producto si está bloqueado
Los pasos 1–5 pueden superarse correctamente — estado `Approved`, Bundle ID coincidente, API key válida — y aun así el SDK devuelve `1000 noProductIDsFound`. En ese caso, puede que el producto esté bloqueado en el registro de Apple. El registro de productos de Apple entra ocasionalmente en un estado en el que un producto existe en la interfaz de App Store Connect pero no queda expuesto en la ruta de consulta de StoreKit.
Elimina el producto en App Store Connect y vuelve a crearlo con el mismo ID de producto. Espera hasta 24 horas tras la recreación para que se propague.
---
# File: cantMakePayments
---
---
title: "Solución para el error Code-1003 cantMakePayment"
description: "Resuelve el error de realización de pagos al gestionar suscripciones en Adapty."
---
El error 1003, `cantMakePayments`, indica que no es posible realizar compras in-app en este dispositivo.
Si encuentras el error `cantMakePayments`, normalmente se debe a una de estas razones:
- Restricciones del dispositivo: El error no está relacionado con Adapty. Consulta las soluciones más abajo.
- Configuración del modo Observer: El método `makePurchase` y el modo Observer no pueden usarse al mismo tiempo. Consulta la sección más abajo.
## Problema: Restricciones del dispositivo \{#issue-device-restrictions\}
| Problema | Solución |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Restricciones de Screen Time | Desactiva las restricciones de compras in-app en [Screen Time](https://support.apple.com/en-us/102470) |
| Cuenta suspendida | Contacta con el soporte de Apple para resolver problemas con la cuenta |
| Restricciones regionales | Usa una cuenta de App Store de una región compatible |
## Problema: Usar el modo Observer y makePurchase a la vez \{#issue-using-both-observer-mode-and-makepurchase\}
Si usas `makePurchases` para gestionar las compras, no necesitas el modo Observer. El [modo Observer](observer-vs-full-mode) solo es necesario si implementas la lógica de compra tú mismo.
Por lo tanto, si usas `makePurchase`, puedes eliminar sin problema la activación del modo Observer del código de inicialización del SDK.
---
# File: migration-to-ios-315
---
---
title: "Migrar Adapty iOS SDK a la v. 3.15"
description: "Migra al Adapty iOS SDK v3.15 para mejorar el rendimiento y acceder a nuevas funciones de monetización."
---
Si usas [Paywall Builder](adapty-paywall-builder) en [modo Observer](observer-vs-full-mode), a partir del iOS SDK 3.15 necesitas implementar un nuevo método `observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)`. Este método ofrece mayor control sobre la lógica de restauración, permitiéndote gestionar las restauraciones de compras en tu propio flujo personalizado. Para ver todos los detalles de implementación, consulta [Presentar paywalls de Paywall Builder en modo Observer](ios-present-paywall-builder-paywalls-in-observer-mode).
```diff showLineNumbers
func observerMode(didInitiatePurchase product: AdaptyPaywallProduct,
onStartPurchase: @escaping () -> Void,
onFinishPurchase: @escaping () -> Void) {
// use the product object to handle the purchase
// use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase
}
+ func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void,
+ onFinishRestore: @escaping () -> Void) {
+ // use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore
+ }
```
---
# File: migration-to-ios-sdk-34
---
---
title: "Migrar el SDK de Adapty para iOS a la v. 3.4"
description: "Migra al SDK de Adapty para iOS v3.4 para obtener mejor rendimiento y nuevas funciones de monetización."
---
El SDK de Adapty 3.4.0 es una versión principal que introduce mejoras que requieren pasos de migración por tu parte.
## Actualizar la activación del SDK de Adapty \{#update-adapty-sdk-activation\}
### Durante el login/registro \{#during-loginsignup\}
Si identificas a los usuarios después de que arranque la app (por ejemplo, tras iniciar sesión o registrarse), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario antes**, Adapty cambiará a trabajar con el perfil asociado a ese customer user ID.
:::important
Los customer user IDs deben ser únicos para cada usuario. Si hardcodeas el valor del parámetro, todos los usuarios se considerarán como uno solo.
:::
Espera a que `identify` se complete (en su callback `onSuccess`) antes de llamar a otros métodos del SDK. Las llamadas concurrentes pueden acabar en el perfil anónimo. Consulta [Orden de llamadas en el SDK de Kotlin Multiplatform](kmp-sdk-call-order).
```kotlin showLineNumbers
Adapty.identify("YOUR_USER_ID") // Único para cada usuario
.onSuccess {
// identify exitoso
}
.onError { error ->
// gestionar el error
}
```
### Durante la activación del SDK \{#during-the-sdk-activation\}
Si ya conoces el customer user ID cuando activas el SDK, puedes enviarlo en el método `activate` en lugar de llamar a `identify` por separado.
Si conoces un customer user ID pero solo lo estableces después de la activación, eso significa que, al activarse, Adapty creará un nuevo perfil anónimo y cambiará al existente solo cuando llames a `identify`.
Puedes pasar un customer user ID existente (uno que hayas usado antes) o uno nuevo. Si pasas uno nuevo, el nuevo perfil creado en la activación se vinculará automáticamente al customer user ID.
:::note
Por defecto, la creación de perfiles anónimos no afecta a los dashboards de análisis, porque las instalaciones se cuentan en función de los ID de dispositivo.
Un ID de dispositivo representa una única instalación de la app desde el store en un dispositivo y solo se regenera tras reinstalar la app.
No depende de si es una primera instalación o una repetida, ni de si se usa un customer user ID existente.
Crear un perfil (al activar el SDK o al cerrar sesión), iniciar sesión o actualizar la app sin reinstalarla no genera eventos de instalación adicionales.
Si quieres contar las instalaciones en función de usuarios únicos en lugar de dispositivos, ve a **App settings** y configura [**Installs definition for analytics**](general#4-installs-definition-for-analytics).
:::
```kotlin showLineNumbers
AdaptyConfig.Builder("PUBLIC_SDK_KEY")
.withCustomerUserId("user123") // Los customer user IDs deben ser únicos para cada usuario. Si hardcodeas el valor del parámetro, todos los usuarios se considerarán como uno solo.
.build()
```
### Cerrar sesión de usuarios \{#log-users-out\}
Si tienes un botón para cerrar la sesión de los usuarios, usa el método `logout`.
:::important
Cerrar la sesión de los usuarios crea un nuevo perfil anónimo para el usuario.
:::
```kotlin showLineNumbers
Adapty.logout()
.onSuccess {
// cierre de sesión exitoso
}
.onError { error ->
// gestionar el error
}
```
:::info
Para volver a iniciar sesión en la app, usa el método `identify`.
:::
### Permitir compras sin inicio de sesión \{#allow-purchases-without-login\}
Si tus usuarios pueden realizar compras tanto antes como después de iniciar sesión en tu app, debes asegurarte de que mantendrán el acceso una vez que inicien sesión:
1. Cuando un usuario sin sesión iniciada realiza una compra, Adapty la vincula a su ID de perfil anónimo.
2. Cuando el usuario inicia sesión en su cuenta, Adapty pasa a trabajar con su perfil identificado.
- Si es un nuevo customer user ID (por ejemplo, la compra se realizó antes del registro), Adapty asigna el customer user ID al perfil actual, por lo que todo el historial de compras se mantiene.
- Si es un customer user ID existente (el customer user ID ya está vinculado a un perfil), debes obtener el nivel de acceso real tras el cambio de perfil. Puedes llamar a [`getProfile`](kmp-check-subscription-status) justo después de la identificación, o [escuchar las actualizaciones del perfil](kmp-check-subscription-status) para que los datos se sincronicen automáticamente.
## Próximos pasos \{#next-steps\}
¡Enhorabuena! Has implementado la lógica de pago in-app en tu app. ¡Te deseamos lo mejor con la monetización de tu app!
Para sacar aún más partido a Adapty, puedes explorar estos temas:
- [**Pruebas**](troubleshooting-test-purchases): Asegúrate de que todo funciona correctamente
- [**Integraciones**](configuration): Integra con servicios de atribución de marketing y análisis en una sola línea de código
- [**Establecer atributos de perfil personalizados**](kmp-setting-user-attributes): Añade atributos personalizados a los perfiles de usuario y crea segmentos para lanzar pruebas A/B o mostrar diferentes paywalls a distintos usuarios
---
# File: adapty-cursor-kmp
---
---
title: "Integra Adapty en tu app de Kotlin Multiplatform con ayuda de IA"
description: "Una guía paso a paso para integrar Adapty en tu app de Kotlin Multiplatform usando Cursor, Context7, ChatGPT, Claude u otras herramientas de IA."
---
Esta página cubre dos formas de integrar Adapty en tu app de Kotlin Multiplatform. Usa la skill de integración del SDK que se describe a continuación para un flujo automatizado de principio a fin, o sigue el recorrido manual más adelante.
## Usa la skill de integración del SDK (beta) \{#use-the-sdk-integration-skill-beta\}
La [skill adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza la integración de extremo a extremo: configuración del dashboard, instalación del SDK, paywall y verificación por etapas. El recorrido manual más adelante es la alternativa si tu herramienta no admite el formato Claude Skills.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
### Instalación \{#install\}
Elige el formato para tu herramienta. La lista completa está en el [README de la skill](https://github.com/adaptyteam/adapty-sdk-integration-skill).
- **Claude Code**: Ejecuta `claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill` y luego `claude plugin install adapty-sdk-integration@adapty` desde tu terminal.
- **GitHub Copilot CLI**: Ejecuta `gh skill install adaptyteam/adapty-sdk-integration-skill`.
- **Gemini CLI**: Ejecuta `gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill`.
- **OpenAI Codex u otra herramienta**: Clona el repositorio y copia `plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` en el directorio de skills de tu herramienta.
### Ejecución \{#run\}
En tu proyecto, ejecuta `/adapty-sdk-integration`. La skill detecta tu plataforma y hace algunas preguntas de configuración. Luego recorre la configuración del dashboard, la instalación del SDK, el paywall y la verificación, consultando la documentación de Adapty relevante en cada etapa.
:::note
La skill está en beta. Si se detiene o se comporta de forma inesperada, el recorrido manual que aparece más abajo cubre cada etapa paso a paso.
:::
## Antes de empezar: configuración del dashboard \{#before-you-start-dashboard-setup\}
Adapty requiere cierta configuración en el dashboard antes de escribir código con el SDK. Puedes hacerlo con una skill de LLM interactiva o manualmente desde el Dashboard.
### Con la skill (recomendado) \{#skill-approach-recommended\}
La skill de la CLI de Adapty permite que tu LLM configure tu app, productos, niveles de acceso, paywalls y placements directamente, sin necesidad de abrir el Dashboard en cada paso. Solo necesitas [conectar tus stores](integrate-payments) en el Dashboard.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Una vez añadida la skill, ejecuta `/adapty-cli` en tu agente. Te guiará por cada paso, incluyendo cuándo abrir el Dashboard para conectar tus stores.
### Con el Dashboard \{#dashboard-approach\}
Si prefieres configurarlo todo manualmente, esto es lo que necesitas antes de escribir código. Tu LLM no puede consultar los valores del dashboard por ti — tendrás que proporcionárselos.
1. **Conecta tus stores**: En el Adapty Dashboard, ve a **App settings → General**. Conecta tanto App Store como Google Play si tu app KMP tiene como objetivo ambas plataformas. Esto es necesario para que las compras funcionen.
[Conectar stores](integrate-payments)
2. **Copia tu clave pública del SDK**: En el Adapty Dashboard, ve a **App settings → General** y busca la sección **API keys**. En el código, esta es la cadena que pasas al constructor de configuración de Adapty.
3. **Crea al menos un producto**: En el Adapty Dashboard, ve a la página **Products**. No haces referencia a los productos directamente en el código — Adapty los entrega a través de los paywalls.
[Añadir productos](quickstart-products)
4. **Crea un paywall y un placement**: En el Adapty Dashboard, crea un paywall en la página **Paywalls** y asígnalo a un placement en la página **Placements**. En el código, el ID del placement es la cadena que pasas a `Adapty.getPaywall("YOUR_PLACEMENT_ID")`.
[Crear paywall](quickstart-paywalls)
5. **Configura los niveles de acceso**: En el Adapty Dashboard, configúralos por producto en la página **Products**. En el código, la cadena se comprueba en `profile.accessLevels["premium"]?.isActive`. El nivel de acceso `premium` predeterminado funciona para la mayoría de las apps. Si los usuarios de pago tienen acceso a funciones diferentes según el producto (por ejemplo, un plan `basic` frente a un plan `pro`), [crea niveles de acceso adicionales](assigning-access-level-to-a-product) antes de empezar a programar.
:::tip
Una vez que tengas los cinco, estás listo para escribir código. Dile a tu LLM: "Mi clave pública del SDK es X, mi ID de placement es Y" para que pueda generar código correcto de inicialización y obtención del paywall.
:::
### Configura cuando estés listo \{#set-up-when-ready\}
Esto no es necesario para empezar a programar, pero lo necesitarás a medida que tu integración madure:
- **Pruebas A/B**: Configúralas en la página **Placements**. No se necesita ningún cambio de código.
[Pruebas A/B](ab-tests)
- **Paywalls y placements adicionales**: Añade más llamadas a `getPaywall` con diferentes IDs de placement.
- **Integraciones de analíticas**: Configúralas en la página **Integrations**. La configuración varía según la integración. Consulta [integraciones de analíticas](analytics-integration) e [integraciones de atribución](attribution-integration).
## Dale documentación de Adapty a tu LLM \{#feed-adapty-docs-to-your-llm\}
### Usa Context7 (recomendado) \{#use-context7-recommended\}
[Context7](https://context7.com) es un servidor MCP que da a tu LLM acceso directo a la documentación actualizada de Adapty. Tu LLM obtiene los documentos correctos automáticamente según lo que preguntes — sin necesidad de pegar URLs manualmente.
Context7 funciona con **Cursor**, **Claude Code**, **Windsurf** y otras herramientas compatibles con MCP. Para configurarlo, ejecuta:
```
npx ctx7 setup
```
Esto detecta tu editor y configura el servidor Context7. Para la configuración manual, consulta el [repositorio de Context7 en GitHub](https://github.com/upstash/context7).
Una vez configurado, haz referencia a la librería de Adapty en tus prompts:
```
Use the adaptyteam/adapty-docs library to look up how to install the Kotlin Multiplatform SDK
```
:::warning
Aunque Context7 elimina la necesidad de pegar enlaces a la documentación manualmente, el orden de implementación es importante. Sigue el [recorrido de implementación](#implementation-walkthrough) que aparece a continuación paso a paso para asegurarte de que todo funciona.
:::
### Usa documentación en texto plano \{#use-plain-text-docs\}
Puedes acceder a cualquier artículo de Adapty en texto plano Markdown. Añade `.md` al final de su URL o haz clic en **Copy for LLM** bajo el título del artículo. Por ejemplo: [adapty-cursor-kmp.md](https://adapty.io/docs/es/adapty-cursor-kmp.md).
Cada etapa del [recorrido de implementación](#implementation-walkthrough) que aparece a continuación incluye un bloque "Envía esto a tu LLM" con enlaces `.md` para pegar.
Para obtener más documentación a la vez, consulta los [archivos de índice y subconjuntos por plataforma](#plain-text-doc-index-files) que aparecen más abajo.
## Recorrido de implementación \{#implementation-walkthrough\}
El resto de esta guía recorre la integración de Adapty en orden de implementación. Cada etapa incluye los documentos que debes enviar a tu LLM, lo que deberías ver cuando termines y los problemas más comunes.
### Planifica tu integración \{#plan-your-integration\}
Antes de lanzarte al código, pide a tu LLM que analice tu proyecto y cree un plan de implementación. Si tu herramienta de IA admite un modo de planificación (como el modo plan de Cursor o Claude Code), úsalo para que el LLM pueda leer tanto la estructura de tu proyecto como la documentación de Adapty antes de escribir código.
Dile a tu LLM qué enfoque usas para las compras — esto afecta a las guías que debe seguir:
- [**Adapty Paywall Builder**](adapty-paywall-builder): Creas los paywalls en el constructor no-code de Adapty y el SDK los renderiza automáticamente.
- [**Paywalls creados manualmente**](kmp-making-purchases): Construyes tu propia interfaz de paywall en código pero sigues usando Adapty para obtener productos y gestionar compras.
- [**Modo Observer**](observer-vs-full-mode): Mantienes tu infraestructura de compras existente y usas Adapty solo para analíticas e integraciones.
¿No sabes cuál elegir? Lee la [tabla comparativa del inicio rápido](kmp-quickstart-paywalls).
### Instala y configura el SDK \{#install-and-configure-the-sdk\}
Añade la dependencia del SDK de Adapty mediante Gradle y actívalo con tu clave pública del SDK. Esta es la base — todo lo demás depende de esto.
**Guía:** [Instalar y configurar el SDK de Adapty](sdk-installation-kotlin-multiplatform)
Envía esto a tu LLM:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/es/sdk-installation-kotlin-multiplatform.md
```
:::tip[Punto de control]
- **Esperado:** La app compila y se ejecuta. El Logcat (Android) o la consola de Xcode (iOS) muestra el log de activación de Adapty.
- **Problema frecuente:** "Public API key is missing" → comprueba que hayas sustituido el marcador de posición por tu clave real de App settings.
:::
### Muestra paywalls y gestiona compras \{#show-paywalls-and-handle-purchases\}
Obtén un paywall por ID de placement, muéstralo y gestiona los eventos de compra. Las guías que necesitas dependen de cómo gestionas las compras.
Prueba cada compra en el sandbox a medida que avanzas — no esperes hasta el final. Consulta [Probar compras en sandbox](test-purchases-in-sandbox) para las instrucciones de configuración.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda, a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `AdaptyPaywallFetchPolicy.Default` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban la información más actualizada.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` para devolver datos en caché si existen. En ese caso, los usuarios podrían no recibir los datos más recientes, pero tendrán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché actualizada regularmente descrita arriba y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para que siempre obtengas la versión más reciente de tus paywalls, garantizando fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el límite, se devolverán datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo indicado en `loadTimeout`, ya que la operación puede estar compuesta de distintas solicitudes internas.
Para Kotlin Multiplatform: puedes crear `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` proviene de `import com.adapty.utils.seconds`), o `TimeInterval.seconds(5)`. Para no establecer límite, usa `TimeInterval.INFINITE`.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Un objeto [`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/) con una lista de IDs de productos, el identificador del paywall, Remote Config y otras propiedades. | ## Obtener la configuración de vista de un paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el toggle **Show on device** en el Paywall Builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperarse. ::: Tras obtener el paywall, comprueba si incluye un `ViewConfiguration`, lo que indica que fue creado con Paywall Builder. Esto te orientará sobre cómo mostrar el paywall. Si el `ViewConfiguration` está presente, trátalo como un paywall de Paywall Builder; si no lo está, [manéjalo como un paywall de Remote Config](present-remote-config-paywalls-kmp). Usa el método `createPaywallView` para cargar la configuración de vista. ```kotlin showLineNumbers if (paywall.hasViewConfiguration) { AdaptyUI.createPaywallView( paywall = paywall, loadTimeout = 5.seconds, preloadProducts = true ).onSuccess { paywallView -> // use paywallView }.onError { error -> // handle the error } } else { // use your custom logic } ``` | Parámetro | Presencia | Descripción | | :--------------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | obligatorio | Un objeto `AdaptyPaywall` para obtener un controlador del paywall deseado. | | **loadTimeout** | opcional | Este valor limita el tiempo de espera para este método. Si se alcanza el límite, se devolverán datos en caché o el fallback local. Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo indicado en `loadTimeout`, ya que la operación puede estar compuesta de distintas solicitudes internas. Puedes usar funciones de extensión como `5.seconds` de `kotlin.time.Duration.Companion`. | | **preloadProducts** | opcional | Establécelo en `true` para precargar productos y mejorar el rendimiento. Cuando está activado, los productos se cargan con antelación, reduciendo el tiempo necesario para mostrar el paywall. | | **productPurchaseParams** | opcional | Un mapa de [`AdaptyProductIdentifier`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-product-identifier/) a [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/). Úsalo para configurar parámetros específicos de compra, como ofertas personalizadas o parámetros de actualización de suscripción para productos individuales del paywall. | :::note Si usas varios idiomas, aprende a añadir una [localización al Paywall Builder](add-paywall-locale-in-adapty-paywall-builder). ::: Una vez cargado, [presenta el paywall](kmp-present-paywalls). ## Obtener un paywall para la audiencia por defecto y cargarlo más rápido \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Normalmente, los paywalls se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, si tienes muchas audiencias y paywalls y tus usuarios tienen una conexión a internet débil, puede que obtener un paywall tarde más de lo deseable. En esas situaciones, puede que prefieras mostrar un paywall por defecto para garantizar una buena experiencia de usuario en lugar de no mostrar ninguno. Para resolver esto, puedes usar el método `getPaywallForDefaultAudience`, que obtiene el paywall del placement indicado para la audiencia **All Users**. No obstante, es fundamental entender que el enfoque recomendado es obtener el paywall con el método `getPaywall`, tal como se detalla en la sección [Obtener un paywall diseñado con Paywall Builder](#fetch-paywall-designed-with-paywall-builder) anterior. :::warning Por qué recomendamos usar `getPaywall` El método `getPaywallForDefaultAudience` tiene algunas desventajas importantes: - **Posibles problemas de compatibilidad con versiones anteriores**: si necesitas mostrar paywalls distintos para diferentes versiones de la app (actual y futuras), pueden surgir complicaciones. Tendrás que diseñar paywalls que sean compatibles con la versión actual (antigua) o asumir que los usuarios con esa versión puedan encontrar problemas con paywalls que no se renderizan correctamente. - **Pérdida de segmentación**: todos los usuarios verán el mismo paywall diseñado para la audiencia **All Users**, lo que significa que pierdes la segmentación personalizada (incluyendo por países, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a aceptar estas desventajas para beneficiarte de una carga más rápida del paywall, usa el método `getPaywallForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getPaywall` descrito [arriba](#fetch-paywall-designed-with-paywall-builder). ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | Parámetro | Presencia | Descripción | |---------|--------|-----------| | **placementId** | obligatorio | El identificador del [placement](placements). Es el valor que especificaste al crear un placement en tu Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda, a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `AdaptyPaywallFetchPolicy.Default` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban la información más actualizada.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` para devolver datos en caché si existen. En ese caso, los usuarios podrían no recibir los datos más recientes, pero tendrán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché se mantiene al reiniciar la app y solo se borra al desinstalarla o mediante limpieza manual.
| ## Personalizar assets \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los assets personalizados. Las imágenes y vídeos destacados tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de assets personalizados, puedes apuntar a estos elementos por sus IDs y personalizar su comportamiento. Para otras imágenes y vídeos, necesitas [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta funcionalidad, actualiza el SDK de Adapty a la versión 3.7.0 o superior. ::: A continuación se muestra un ejemplo de cómo proporcionar assets personalizados a través de un mapa: :::info El SDK de Kotlin Multiplatform solo admite assets locales. Para contenido remoto, debes descargar y almacenar en caché los assets localmente antes de usarlos como assets personalizados. ::: ```kotlin showLineNumbers // Import generated Res class for accessing resources viewModelScope.launch { // Get URIs for bundled resources using Res.getUri() val heroImagePath = Res.getUri("files/images/hero_image.png") val demoVideoPath = Res.getUri("files/videos/demo_video.mp4") // Or read image as byte data val imageByteData = Res.readBytes("files/images/avatar.png") // Create custom assets map val customAssets: Map
## El número de vistas del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El contador de vistas del paywall muestra el doble del número esperado.
**Motivo**: Es posible que estés llamando a `logShowPaywall` en tu código, lo que duplica el contador de vistas si estás usando el Paywall Builder. Para paywalls diseñados con el Paywall Builder, las analíticas se registran automáticamente, por lo que no es necesario usar este método.
**Solución**: Asegúrate de no estar llamando a `logShowPaywall` en tu código si estás usando el Paywall Builder.
---
# File: kmp-implement-paywalls-manually
---
---
title: "Implement paywalls manually in Kotlin Multiplatform SDK"
description: "Learn how to implement paywalls manually in your Kotlin Multiplatform app with Adapty SDK."
---
## Accept purchases
If you are working with paywalls you've implemented yourself, you can delegate handling purchases to Adapty, using the `makePurchase` method. This way, we will handle all the user scenarios, and you will only need to handle the purchase results.
:::important
`makePurchase` works with products created in the Adapty dashboard. Make sure you configure products and ways to retrieve them in the dashboard by following the [quickstart guide](quickstart).
:::
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `AdaptyPaywallFetchPolicy.Default` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que los usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, los usuarios puede que no obtengan los datos más recientes, pero tendrán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza con regularidad, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](kmp-use-fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que la CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls mientras se asegura la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 s |Este valor limita el tiempo de espera de este método. Si se alcanza el tiempo de espera, se devolverán datos en caché o el fallback local.
Ten en cuenta que en casos raros este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede estar compuesta por diferentes solicitudes internamente.
| ¡No hardcodees los IDs de productos! Dado que los paywalls se configuran de forma remota, los productos disponibles, el número de productos y las ofertas especiales (como pruebas gratuitas) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, tu app debería mostrar esos 2 productos. Sin embargo, si más tarde obtienes 3 productos, tu app debería mostrar los 3 sin requerir ningún cambio en el código. Lo único que debes hardcodear es el ID del placement. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/) con: una lista de IDs de productos, el identificador del paywall, Remote Config y varias otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tienes el paywall, puedes consultar el array de productos que le corresponde: ```kotlin showLineNumbers Adapty.getPaywallProducts(paywall).onSuccess { products -> // the requested products }.onError { error -> // handle the error } ``` Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Lista de objetos [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) con: identificador del producto, nombre del producto, precio, moneda, duración de la suscripción y varias otras propiedades. | Al implementar tu propio diseño de paywall, probablemente necesitarás acceder a estas propiedades del objeto [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/). A continuación se muestran las propiedades más usadas, pero consulta el documento enlazado para obtener información completa sobre todas las propiedades disponibles. | Propiedad | Descripción | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Para mostrar el título del producto, usa `product.localizedTitle`. Ten en cuenta que la localización se basa en el país de la store seleccionado por el usuario, no en el idioma del dispositivo. | | **Price** | Para mostrar una versión localizada del precio, usa `product.price.localizedString`. Esta localización se basa en la información de idioma del dispositivo. También puedes acceder al precio como número usando `product.price.amount`. El valor se proporcionará en la moneda local. Para obtener el símbolo de moneda correspondiente, usa `product.price.currencySymbol`. | | **Subscription Period** | Para mostrar el período (por ejemplo, semana, mes, año, etc.), usa `product.subscriptionDetails?.localizedSubscriptionPeriod`. Esta localización se basa en el idioma del dispositivo. Para obtener el período de suscripción de forma programática, usa `product.subscriptionDetails?.subscriptionPeriod`. Desde ahí puedes acceder al enum `unit` para obtener la duración (es decir, DAY, WEEK, MONTH, YEAR o UNKNOWN). El valor `numberOfUnits` te dará el número de unidades del período. Por ejemplo, para una suscripción trimestral, verías `MONTH` en la propiedad unit y `3` en la propiedad numberOfUnits. | | **Introductory Offer** | Para mostrar un distintivo u otro indicador de que una suscripción incluye una oferta introductoria, consulta la propiedad `product.subscriptionDetails?.introductoryOfferPhases`. Esta es una lista que puede contener hasta dos fases de descuento: la fase de prueba gratuita y la fase de precio introductorio. Dentro de cada objeto de fase encontrarás las siguientes propiedades útiles:opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `AdaptyPaywallFetchPolicy.Default` |Por defecto, el SDK intentará cargar datos del servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que los usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` para devolver datos en caché si existen. En este caso, los usuarios puede que no obtengan los datos más recientes, pero tendrán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza con regularidad, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante una limpieza manual.
| --- # File: present-remote-config-paywalls-kmp --- --- title: "Renderizar un paywall diseñado con Remote Config en el SDK de Kotlin Multiplatform" description: "Descubre cómo presentar paywalls de Remote Config en el SDK de Adapty para Kotlin Multiplatform y personalizar la experiencia del usuario." --- Si has personalizado un paywall usando Remote Config, necesitarás implementar el renderizado en el código de tu aplicación móvil para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú decides qué incluir y cómo se ve tu paywall. Te proporcionamos un método para obtener la configuración remota, dándote la autonomía para mostrar tu paywall personalizado configurado mediante Remote Config. ## Obtener el Remote Config del paywall y presentarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores necesarios. ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> val headerText = paywall.remoteConfig?.dataMap?.get("header_text") as? String // use the remote config values }.onError { error -> // handle the error } ``` En este punto, una vez que hayas recibido todos los valores necesarios, es el momento de renderizarlos y ensamblarlos en una página visualmente atractiva. Asegúrate de que el diseño se adapte a las distintas pantallas y orientaciones de dispositivos móviles, ofreciendo una experiencia fluida y amigable en todos los dispositivos. :::warning Asegúrate de [registrar el evento de visualización del paywall](present-remote-config-paywalls-kmp#track-paywall-view-events) como se describe a continuación, para que los análisis de Adapty puedan capturar información para los embudos y las pruebas A/B. ::: Cuando hayas terminado de mostrar el paywall, continúa configurando el flujo de compra. Cuando el usuario realice una compra, simplemente llama a `.makePurchase()` con el producto de tu paywall. Para más detalles sobre el método `.makePurchase()`, consulta [Realizar compras](kmp-making-purchases). Te recomendamos [crear un paywall de respaldo llamado fallback paywall](kmp-use-fallback-paywalls). Este respaldo se mostrará al usuario cuando no haya conexión a internet ni caché disponible, garantizando una experiencia fluida incluso en esas situaciones. ## Registrar eventos de visualización del paywall \{#track-paywall-view-events\} Adapty te ayuda a medir el rendimiento de tus paywalls. Aunque los datos de compras se recopilan automáticamente, el registro de las visualizaciones de paywalls requiere tu intervención, ya que solo tú sabes cuándo un cliente ve un paywall. Para registrar un evento de visualización de paywall, simplemente llama a `.logShowPaywall(paywall)` y se reflejará en las métricas de tu paywall en los embudos y las pruebas A/B. :::important No es necesario llamar a `.logShowPaywall(paywall)` si estás mostrando paywalls creados en el [Paywall Builder](adapty-paywall-builder). ::: ```kotlin showLineNumbers Adapty.logShowPaywall(paywall = paywall) .onSuccess { // paywall view logged successfully } .onError { error -> // handle the error } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :------- |:-------------------------------------------------------------------------------------------------------| | **paywall** | obligatorio | Un objeto [`AdaptyPaywall`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/). | --- # File: kmp-making-purchases --- --- title: "Realizar compras en app móvil con el SDK de Kotlin Multiplatform" description: "Guía para gestionar compras in-app y suscripciones con Adapty." --- Mostrar paywalls dentro de tu app es un paso fundamental para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, simplemente mostrar estos paywalls es suficiente para gestionar las compras solo si usas el [Paywall Builder](adapty-paywall-builder) para personalizar tus paywalls. Si no usas el Paywall Builder, debes utilizar un método aparte llamado `.makePurchase()` para completar una compra y desbloquear el contenido deseado. Este método actúa como la puerta de entrada para que los usuarios interactúen con los paywalls y procedan con sus transacciones. Si tu paywall tiene una oferta promocional activa para el producto que el usuario quiere comprar, Adapty la aplicará automáticamente en el momento de la compra. :::warning Ten en cuenta que la oferta introductoria solo se aplicará automáticamente si usas los paywalls configurados con el Paywall Builder. En otros casos, necesitarás [verificar la elegibilidad del usuario para una oferta introductoria en iOS](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios). Saltarte este paso puede provocar que tu app sea rechazada durante la revisión. Además, podría dar lugar a cobrar el precio completo a usuarios que sí son elegibles para una oferta introductoria. ::: Asegúrate de haber [completado la configuración inicial](quickstart) sin saltarte ningún paso. Sin ella, no podemos validar las compras. ## Realizar una compra \{#make-purchase\} :::note **¿Usas el [Paywall Builder](adapty-paywall-builder)?** Las compras se procesan automáticamente; puedes saltarte este paso. **¿Buscas una guía paso a paso?** Consulta la [guía de inicio rápido](kmp-implement-paywalls-manually) para instrucciones de implementación completas con todo el contexto. ::: ```kotlin showLineNumbers Adapty.makePurchase(product = product).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // Grant access to the paid features } } is AdaptyPurchaseResult.UserCanceled -> { // Handle the case where the user canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Handle deferred purchases (e.g., the user will pay offline with cash) } } }.onError { error -> // Handle the error } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------| | **Product** | obligatorio | Un objeto [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) obtenido del paywall. | Parámetros de la respuesta: | Parámetro | Descripción | |---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |Si la solicitud fue exitosa, la respuesta contiene este objeto. Un objeto [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas de un usuario dentro de la app.
Comprueba el estado del nivel de acceso para verificar si el usuario tiene el acceso requerido a la app.
| :::warning **Nota:** si aún usas una versión de StoreKit de Apple inferior a v2.0 y una versión del SDK de Adapty inferior a v.2.9.0, necesitas proporcionar el [secreto compartido de App Store de Apple](app-store-connection-configuration#step-5-enter-app-store-shared-secret). Este método está actualmente obsoleto según Apple. ::: ## Cambiar suscripción al realizar una compra \{#change-subscription-when-making-a-purchase\} Cuando un usuario elige una nueva suscripción en lugar de renovar la actual, el comportamiento depende del store. En Google Play, la suscripción no se actualiza automáticamente. Tendrás que gestionar el cambio en el código de tu app como se describe a continuación. Para reemplazar la suscripción por otra en Android, llama al método `.makePurchase()` con el parámetro adicional: ```kotlin showLineNumbers val subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters( oldSubVendorProductId = "old_subscription_product_id", replacementMode = AdaptyAndroidSubscriptionUpdateReplacementMode.CHARGE_FULL_PRICE ) val purchaseParams = AdaptyPurchaseParameters.Builder() .setSubscriptionUpdateParams(subscriptionUpdateParams) .build() Adapty.makePurchase( product = product, parameters = purchaseParams ).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // successful cross-grade } is AdaptyPurchaseResult.UserCanceled -> { // user canceled the purchase flow } is AdaptyPurchaseResult.Pending -> { // the purchase has not been finished yet, e.g. user will pay offline by cash } } }.onError { error -> // Handle the error } ``` Parámetro adicional de la solicitud: | Parámetro | Presencia | Descripción | |:---------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **parameters** | opcional | Un objeto [`AdaptyAndroidSubscriptionUpdateParameters`](https://kmp.adapty.io/////adapty/com.adapty.kmp.models/-adapty-android-subscription-update-parameters/) pasado a través de [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/). | Puedes leer más sobre las suscripciones y los modos de reemplazo en la documentación de Google para desarrolladores: - [Acerca de los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Recomendaciones de Google para los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Modo de reemplazo [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Nota: este método solo está disponible para actualizaciones de suscripción. No se admiten cambios a un nivel inferior. - Modo de reemplazo [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Nota: el cambio de suscripción real solo ocurrirá cuando finalice el período de facturación de la suscripción actual. ## Canjear códigos de oferta en iOS \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';Un objeto [`AdaptyProfile`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-profile/). Este modelo contiene información sobre los niveles de acceso, suscripciones y compras no relacionadas con suscripciones.
Comprueba el **estado del nivel de acceso** para determinar si el usuario tiene acceso a la app.
| :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: --- # File: implement-observer-mode-kmp --- --- title: "Implementar el modo Observer en el SDK de Kotlin Multiplatform" description: "Implementa el modo Observer en Adapty para rastrear eventos de suscripción de usuarios en el SDK de Kotlin Multiplatform." --- Si ya tienes tu propia infraestructura de compras y no estás listo para migrar completamente a Adapty, puedes explorar el [modo Observer](observer-vs-full-mode). En su forma básica, el modo Observer ofrece analíticas avanzadas e integración fluida con sistemas de atribución y analítica. Si esto cubre tus necesidades, solo tienes que: 1. Activarlo al configurar el SDK de Adapty estableciendo el parámetro `observerMode` en `true`. Sigue las instrucciones de configuración para [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform). 2. [Reportar transacciones](report-transactions-observer-mode-kmp) desde tu infraestructura de compras existente a Adapty. ## Configuración del modo Observer \{#observer-mode-setup\} Activa el modo Observer si gestionas las compras y el estado de las suscripciones por tu cuenta y usas Adapty para enviar eventos de suscripción y analíticas. :::important Cuando se ejecuta en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlo tú mismo. ::: ```kotlin showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withObserverMode(true) // default false .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised in observer mode") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` Parámetros: | Parámetro | Descripción | | --------------------------- | ------------------------------------------------------------ | | observerMode | Un valor booleano que controla el [modo Observer](observer-vs-full-mode). El valor predeterminado es `false`. | ## Usar paywalls de Adapty en el modo Observer \{#using-adapty-paywalls-in-observer-mode\} Si también quieres usar las paywalls y las funciones de pruebas A/B de Adapty, puedes hacerlo, pero requiere una configuración adicional en el modo Observer. Esto es lo que necesitas hacer además de los pasos anteriores: 1. Muestra los paywalls de la forma habitual para [paywalls con Remote Config](present-remote-config-paywalls-kmp). 3. [Asocia los paywalls](report-transactions-observer-mode-kmp) con las transacciones de compra. --- # File: report-transactions-observer-mode-kmp --- --- title: "Reportar transacciones en el modo Observer en el SDK de Kotlin Multiplatform" description: "Reporta transacciones de compra en el modo Observer de Adapty para obtener información sobre usuarios y seguimiento de ingresos en el SDK de Kotlin Multiplatform." --- En el modo Observer, el SDK de Adapty no puede rastrear por sí solo las compras realizadas a través de tu sistema de compras existente. Necesitas reportar las transacciones desde tu app store. Es fundamental configurar esto **antes** de publicar tu app para evitar errores en los análisis. Usa `reportTransaction` para reportar de forma explícita cada transacción y que Adapty pueda reconocerla. :::warning **¡No omitas el reporte de transacciones!** Si no llamas a `reportTransaction`, Adapty no reconocerá la transacción, no aparecerá en los análisis y no se enviará a las integraciones. ::: Si usas paywalls de Adapty, incluye el `variationId` al reportar una transacción. Esto vincula la compra con el paywall que la originó, garantizando un análisis preciso del paywall. ```kotlin showLineNumbers Adapty.reportTransaction( transactionId = "your_transaction_id", variationId = paywall.variationId ).onSuccess { profile -> // Transaction reported successfully // profile contains updated user data }.onError { error -> // handle the error } ``` Parámetros: | Parámetro | Presencia | Descripción | | --------------- | ---------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | obligatorio | El ID de transacción de tu compra en el app store. Normalmente es el token de compra o el identificador de transacción devuelto por el store. | | variationId | opcional | El identificador de cadena de la variante. Puedes obtenerlo usando la propiedad `variationId` del objeto [AdaptyPaywall](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/). | --- # File: kmp-troubleshoot-purchases --- --- title: "Solucionar problemas de compras en el SDK de Kotlin Multiplatform" description: "Solucionar problemas de compras en el SDK de Kotlin Multiplatform" --- Esta guía te ayuda a resolver problemas comunes al implementar compras manualmente en el SDK de Kotlin Multiplatform. ## makePurchase se llama correctamente, pero el perfil no se actualiza \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **Problema**: El método `makePurchase` se completa correctamente, pero el perfil del usuario y el estado de la suscripción no se actualizan en Adapty. **Causa**: Esto normalmente indica una configuración incompleta de Google Play Store. **Solución**: Asegúrate de haber completado todos los [pasos de configuración de Google Play](initial-android). ## makePurchase se invoca dos veces \{#makepurchase-is-invoked-twice\} **Problema**: El método `makePurchase` se está llamando varias veces para la misma compra. **Causa**: Esto suele ocurrir cuando el flujo de compra se activa varias veces debido a problemas de gestión del estado de la interfaz o por interacciones rápidas del usuario. **Solución**: Asegúrate de haber completado todos los [pasos de configuración de Google Play](initial-android). ## AdaptyError.cantMakePayments en el modo observador \{#adaptye-rror-cantmakepayments-in-observer-mode\} **Problema**: Estás recibiendo `AdaptyError.cantMakePayments` al usar `makePurchase` en el modo observador. **Causa**: En el modo observador, debes gestionar las compras por tu cuenta, no usar el método `makePurchase` de Adapty. **Solución**: Si usas `makePurchase` para las compras, desactiva el modo observador. Tienes que elegir entre usar `makePurchase` o gestionar las compras por tu cuenta en el modo observador. Consulta [Implementar el modo observador](implement-observer-mode-kmp) para más detalles. ## Error de Adapty: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **Problema**: Estás recibiendo un error de facturación no disponible de Google Play Store. **Causa**: Este error no está relacionado con Adapty. Es un error de la biblioteca Google Play Billing que indica que la facturación no está disponible en el dispositivo. **Solución**: Este error no está relacionado con Adapty. Puedes consultarlo en la documentación de Play Store: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers. ## No se encuentran makePurchasesCompletionHandlers \{#not-found-makepurchasescompletionhandlers\} **Problema**: Estás teniendo problemas porque no se encuentran los `makePurchasesCompletionHandlers`. **Causa**: Esto suele estar relacionado con problemas en las pruebas en sandbox. **Solución**: Crea un nuevo usuario de sandbox e inténtalo de nuevo. Esto suele resolver los problemas con los manejadores de finalización de compras en sandbox. --- # File: kmp-user --- --- title: "Users & access in Kotlin Multiplatform SDK" description: "Learn how to work with users and access levels in your Kotlin Multiplatform app with Adapty SDK." --- This page contains all guides for working with users and access levels in your Kotlin Multiplatform app. Choose the topic you need: - **[Identify users](kmp-identifying-users)** - Learn how to identify users in your app - **[Update user data](kmp-setting-user-attributes)** - Set user attributes and profile data - **[Listen for subscription status changes](kmp-listen-subscription-changes)** - Monitor subscription changes in real-time - **[Kids Mode](kids-mode-kmp)** - Implement Kids Mode for your app --- # File: kmp-identifying-users --- --- title: "Identificar usuarios en Kotlin Multiplatform SDK" description: "Identifica usuarios en Adapty para mejorar las experiencias de suscripción personalizadas." --- Adapty crea un ID de perfil interno para cada usuario. Sin embargo, si tienes tu propio sistema de autenticación, deberías establecer tu propio Customer User ID. Puedes encontrar usuarios por su Customer User ID en la sección [Perfiles](profiles-crm) y usarlo en la [API del lado del servidor](getting-started-with-server-side-api), que se enviará a todas las integraciones. ### Configurar el ID de usuario del cliente durante la configuración \{#setting-customer-user-id-on-configuration\} Si tienes un ID de usuario durante la configuración, pásalo como parámetro `customerUserId` al método `.activate()`: ```kotlin showLineNumbers Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("YOUR_USER_ID") .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } } ``` :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: ### Configuración del ID de usuario tras la inicialización \{#setting-customer-user-id-after-configuration\} Si no tienes un ID de usuario en la configuración del SDK, puedes establecerlo más adelante en cualquier momento con el método `.identify()`. Los casos más habituales para usar este método son tras el registro o la autenticación, cuando el usuario pasa de ser anónimo a estar autenticado. ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID").onSuccess { // successful identify }.onError { error -> // handle the error } ``` Parámetros de la solicitud: - **Customer User ID** (obligatorio): un identificador de usuario de tipo string. :::warning Reenvío de datos significativos del usuario En algunos casos, como cuando un usuario vuelve a iniciar sesión en su cuenta, los servidores de Adapty ya tienen información sobre ese usuario. En estos escenarios, el SDK de Adapty cambiará automáticamente para trabajar con el nuevo usuario. Si enviaste algún dato al usuario anónimo, como atributos personalizados o atribuciones de redes de terceros, deberás reenviar esos datos para el usuario identificado. También es importante tener en cuenta que debes volver a solicitar todos los paywalls y productos después de identificar al usuario, ya que los datos del nuevo usuario pueden ser diferentes. ::: ### Cerrar sesión e iniciar sesión \{#logging-out-and-logging-in\} Puedes cerrar la sesión del usuario en cualquier momento llamando al método `.logout()`: ```kotlin showLineNumbers Adapty.logout().onSuccess { // successful logout }.onError { error -> // handle the error } ``` Después puedes iniciar sesión con el método `.identify()`. ## Asignar `appAccountToken` (iOS) \{#assign-appaccounttoken-ios\} [`iosAppAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)) es un **UUID** que te permite vincular las transacciones del App Store con la identidad interna de tus usuarios. StoreKit asocia este token con cada transacción, de modo que tu backend puede relacionar los datos del App Store con tus usuarios. Usa un UUID estable generado por usuario y reutilízalo para la misma cuenta en todos los dispositivos. Esto garantiza que las compras y las notificaciones del App Store queden correctamente vinculadas. Puedes establecer el token de dos formas: durante la activación del SDK o al identificar al usuario. :::important Siempre debes pasar `iosAppAccountToken` junto con `customerUserId`. Si solo pasas el token, no se incluirá en la transacción. ::: ```kotlin showLineNumbers // Durante la configuración: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ) .build() ).onSuccess { // activación exitosa }.onError { error -> // manejar el error } // O al identificar usuarios Adapty.identify( customerUserId = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ).onSuccess { // identificación exitosa }.onError { error -> // manejar el error } ``` ## Establecer IDs de cuenta ofuscados (Android) \{#set-obfuscated-account-ids-android\} Google Play requiere IDs de cuenta ofuscados en ciertos casos de uso para mejorar la privacidad y seguridad del usuario. Estos IDs ayudan a Google Play a identificar las compras manteniendo el anonimato de la información del usuario, algo especialmente importante para la prevención de fraudes y los análisis. Es posible que necesites configurar estos IDs si tu aplicación maneja datos sensibles de usuarios o si debes cumplir con regulaciones de privacidad específicas. Los IDs ofuscados permiten a Google Play rastrear las compras sin exponer los identificadores reales de los usuarios. :::important Siempre debes pasar `androidObfuscatedAccountId` junto con `customerUserId`. Si solo pasas el ID de cuenta ofuscado, no se incluirá en la transacción. ::: ```kotlin showLineNumbers // Durante la configuración: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ) .build() ).onSuccess { // activación correcta }.onError { error -> // gestionar el error } // O al identificar usuarios Adapty.identify( customerUserId = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ).onSuccess { // identificación correcta }.onError { error -> // gestionar el error } ``` ## Detectar usuarios en varios dispositivos \{#detect-users-across-devices\} --- no_index: true --- Cuando el SDK se activa, lee automáticamente los derechos existentes del usuario desde StoreKit (iOS) o Google Play Billing (Android) y los sincroniza con el backend de Adapty. Una suscripción activa aparece en el perfil de Adapty sin que la app llame a `restorePurchases`. Lo que **no** ocurre automáticamente es reconocer que un perfil en un dispositivo nuevo pertenece al mismo usuario que el perfil en el dispositivo original. Adapty relaciona perfiles por Customer User ID, así que la continuidad de identidad depende de lo que uses como CUID. **Lo que Adapty puede detectar entre dispositivos** | Tu configuración | Lo que Adapty detecta | Lo que debes hacer | | --- | --- | --- | | Customer User ID = `device_id` (sin login en la app) | El nuevo dispositivo obtiene un CUID diferente y, por tanto, un perfil diferente. La suscripción se sincroniza con el nuevo perfil mediante un evento **Access level updated**, pero `subscription_started` no se dispara — el nuevo perfil se trata como heredero de la compra original. Los análisis basados en `subscription_started` contarán de menos a los usuarios que vuelven. | Usa un ID de cuenta estable como Customer User ID para que un usuario que regresa coincida con el perfil existente en todos los dispositivos. | | Customer User ID = ID de cuenta estable (login en cada dispositivo) | El SDK sincroniza automáticamente la suscripción en `activate()`, e `identify()` relaciona el perfil existente por CUID. | No se necesita configuración adicional — tanto la identidad como la suscripción se resuelven automáticamente. | | Heredero de Apple Family Sharing | El miembro de la familia recibe la suscripción solo a través de un evento **Access level updated** — `subscription_started` no se dispara. | Escucha el evento **Access level updated**. Consulta [Apple Family Sharing](apple-family-sharing) para ver la matriz de eventos completa. | | Misma cuenta de Apple/Google, distintos usuarios dentro de la app | El primer perfil que registra la compra se convierte en el principal. Los perfiles posteriores ven la suscripción a través de una cadena de herederos, con un evento **Access level updated**. | Exige login y elige un [modo de compartición](sharing-paid-access-between-user-accounts) que se adapte a tu modelo. | **Restaurar compras en un dispositivo nuevo** Muestra un botón "Restaurar compras" iniciado por el usuario en tu paywall. Apple App Review (directriz 3.1.1) lo exige, y actúa como alternativa cuando la sincronización automática no cubre algún caso límite. El botón debe llamar a `restorePurchases` en tu SDK. No es necesario llamar a `restorePurchases` de forma programática al primer inicio para el uso normal — el SDK ya ejecuta el equivalente en `activate()`. Reserva las llamadas programáticas para forzar una verificación de recibo actualizada, por ejemplo al depurar un acceso que falta después de que `activate()` haya completado. --- # File: kmp-setting-user-attributes --- --- title: "Establecer atributos de usuario en el SDK de Kotlin Multiplatform" description: "Aprende cómo establecer atributos de usuario en Adapty para mejorar la segmentación de audiencias." --- Puedes establecer atributos opcionales como el correo electrónico, el número de teléfono, etc., en el usuario de tu aplicación. Luego puedes usar estos atributos para crear [segmentos](segments) de usuarios o simplemente verlos en el CRM. ### Establecer atributos de usuario \{#setting-user-attributes\} Para establecer atributos de usuario, llama al método `.updateProfile()`: ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.FEMALE) .withBirthday(AdaptyProfile.Date(1970, 1, 3)) Adapty.updateProfile(builder.build()) .onSuccess { // profile updated successfully } .onError { error -> // handle the error } ``` Ten en cuenta que los atributos que hayas establecido previamente con el método `updateProfile` no se restablecerán. :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: ### Lista de claves permitidas \{#the-allowed-keys-list\} Las claves permitidas `phoneNumber
firstName
lastName
| String | | gender | Enum, los valores permitidos son: `AdaptyProfile.Gender.FEMALE`, `AdaptyProfile.Gender.MALE`, `AdaptyProfile.Gender.OTHER` | | birthday | Date | ### Atributos personalizados de usuario \{#custom-user-attributes\} Puedes definir tus propios atributos personalizados. Estos suelen estar relacionados con el uso de tu aplicación. Por ejemplo, en aplicaciones de fitness podrían ser el número de ejercicios por semana; en aplicaciones de aprendizaje de idiomas, el nivel de conocimiento del usuario, etc. Puedes usarlos en segmentos para crear paywalls y ofertas dirigidas, y también en análisis para determinar qué métricas de producto influyen más en los ingresos. ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withCustomAttribute("key1", "value1") ``` Para eliminar una clave existente, usa el método `.withRemovedCustomAttribute()`: ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withRemovedCustomAttribute("key2") ``` En ocasiones necesitas saber qué atributos personalizados ya se han establecido anteriormente. Para ello, utiliza el campo `customAttributes` del objeto `AdaptyProfile`. :::warning Ten en cuenta que el valor de `customAttributes` puede estar desactualizado, ya que los atributos de usuario pueden enviarse desde distintos dispositivos en cualquier momento, por lo que los atributos en el servidor pueden haber cambiado desde la última sincronización. ::: ### Límites \{#limits\} - Hasta 30 atributos personalizados por usuario - Los nombres de clave tienen un máximo de 30 caracteres. El nombre de la clave puede incluir caracteres alfanuméricos y cualquiera de los siguientes: `_` `-` `.` - El valor puede ser una cadena de texto o un número flotante con un máximo de 50 caracteres. --- # File: kmp-listen-subscription-changes --- --- title: "Verificar el estado de la suscripción en el SDK de Kotlin Multiplatform" description: "Rastrea y gestiona el estado de la suscripción de usuarios en Adapty para mejorar la retención de clientes en tu app de Kotlin Multiplatform." --- Con Adapty, hacer seguimiento del estado de la suscripción es muy sencillo. No tienes que insertar manualmente IDs de productos en tu código. En su lugar, puedes confirmar fácilmente el estado de la suscripción de un usuario comprobando si tiene un [nivel de acceso](access-level) activo. Antes de empezar a verificar el estado de la suscripción, configura las [notificaciones de desarrollador en tiempo real (RTDN)](enable-real-time-developer-notifications-rtdn). ## Nivel de acceso y el objeto AdaptyProfile \{#access-level-and-the-adaptyprofile-object\} Los niveles de acceso son propiedades del objeto [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/). Te recomendamos obtener el perfil cuando tu app se inicie, por ejemplo al [identificar un usuario](android-identifying-users#setting-customer-user-id-on-configuration), y actualizarlo cada vez que se produzcan cambios. Así podrás usar el objeto de perfil sin tener que solicitarlo repetidamente. Para recibir notificaciones sobre actualizaciones del perfil, escucha los cambios tal como se describe en la sección [Escuchar actualizaciones del perfil, incluidos los niveles de acceso](android-listen-subscription-changes) a continuación. :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: ## Obtener el nivel de acceso desde el servidor \{#retrieving-the-access-level-from-the-server\} Para obtener el nivel de acceso desde el servidor, usa el método `.getProfile()`: ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> // check the access }.onError { error -> // handle the error } ``` Parámetros de respuesta: | Parámetro | Descripción | | --------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Profile |Un objeto [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/). En general, solo tienes que comprobar el estado del nivel de acceso del perfil para determinar si el usuario tiene acceso premium a la app.
El método `.getProfile` proporciona el resultado más actualizado, ya que siempre intenta consultar la API. Si por alguna razón (por ejemplo, sin conexión a internet), el SDK de Adapty no puede obtener información del servidor, se devolverán los datos de la caché. También es importante tener en cuenta que el SDK de Adapty actualiza la caché de `AdaptyProfile` periódicamente para mantener esta información lo más actualizada posible.
| El método `.getProfile()` te proporciona el perfil de usuario desde el que puedes obtener el estado del nivel de acceso. Puedes tener varios niveles de acceso por app. Por ejemplo, si tienes una app de noticias y vendes suscripciones a distintos temas de forma independiente, puedes crear niveles de acceso "sports" y "science". Pero la mayoría de las veces solo necesitarás un nivel de acceso; en ese caso, puedes usar simplemente el nivel de acceso predeterminado "premium". A continuación se muestra un ejemplo para comprobar el nivel de acceso predeterminado "premium": ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> if (profile.accessLevels["premium"]?.isActive == true) { // grant access to premium features } }.onError { error -> // handle the error } ``` ### Escuchar actualizaciones del estado de la suscripción \{#listening-for-subscription-status-updates\} Cada vez que cambia la suscripción de un usuario, Adapty lanza un evento. Para recibir mensajes de Adapty, necesitas realizar una configuración adicional: ```kotlin showLineNumbers Adapty.setOnProfileUpdatedListener { profile -> // handle any changes to subscription state } ``` Adapty también lanza un evento al inicio de la aplicación. En ese caso, se pasará el estado de la suscripción almacenado en caché. ### Caché del estado de la suscripción \{#subscription-status-cache\} La caché implementada en el SDK de Adapty almacena el estado de la suscripción del perfil. Esto significa que, aunque el servidor no esté disponible, se puede acceder a los datos en caché para obtener información sobre el estado de la suscripción del perfil. Sin embargo, es importante tener en cuenta que no es posible solicitar datos directamente desde la caché. El SDK consulta periódicamente el servidor cada minuto para comprobar si hay actualizaciones o cambios relacionados con el perfil. Si hay alguna modificación, como nuevas transacciones u otras actualizaciones, se enviarán a los datos en caché para mantenerlos sincronizados con el servidor. --- # File: kmp-deal-with-att --- --- title: "Gestionar ATT en el SDK de Kotlin Multiplatform" description: "Comienza con Adapty en Kotlin Multiplatform para simplificar la configuración y gestión de suscripciones." --- Si tu aplicación usa el framework AppTrackingTransparency y muestra al usuario una solicitud de autorización de seguimiento, debes enviar el [estado de autorización](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) a Adapty. ```kotlin showLineNumbers val profileParameters = AdaptyProfileParameters.Builder() .withAttStatus(3) // 3 = ATTrackingManagerAuthorizationStatusAuthorized .build() Adapty.updateProfile(profileParameters) .onSuccess { // ATT status updated successfully } .onError { error -> // handle AdaptyError } ``` :::warning Te recomendamos encarecidamente que envíes este valor lo antes posible cuando cambie; solo así los datos se transmitirán a tiempo a las integraciones que hayas configurado. ::: --- # File: kids-mode-kmp --- --- title: "Modo para Niños en el SDK de Kotlin Multiplatform" description: "Activa fácilmente el Modo para Niños para cumplir con las políticas de Google. Sin GAID ni datos publicitarios recopilados en el SDK de Kotlin Multiplatform." --- Si tu aplicación de Kotlin Multiplatform está destinada a niños, debes seguir las políticas de [Google](https://support.google.com/googleplay/android-developer/answer/9893335). Si usas el SDK de Adapty, unos pocos pasos sencillos te ayudarán a configurarlo para cumplir con estas políticas y superar las revisiones de la app store. ## ¿Qué se requiere? \{#whats-required\} Necesitas configurar el SDK de Adapty para deshabilitar la recopilación de: - [IDFA (Identifier for Advertisers)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [Dirección IP](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Además, te recomendamos usar el ID de usuario del cliente con cuidado. Un ID de usuario con el formato `opcional
por defecto: `en`
| El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En ese caso, puede que los usuarios no reciban los datos más recientes, pero tendrán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza con regularidad, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización periódica descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings y asegurar la fiabilidad incluso cuando la conexión a internet es limitada.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede agotar el tiempo de espera un poco después de lo especificado en `loadTimeout`, ya que la operación puede estar compuesta de distintas solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Un objeto [`AdaptyOnboarding`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-onboarding/) con: el identificador y la configuración del onboarding, el Remote Config y otras propiedades. | ## Acelerar la obtención del onboarding con el onboarding de audiencia predeterminada \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Normalmente, los onboardings se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, si tienes muchas audiencias y onboardings y tus usuarios tienen una conexión a internet débil, la obtención de un onboarding puede tardar más de lo deseado. En esas situaciones, puede que quieras mostrar un onboarding predeterminado para garantizar una experiencia fluida en lugar de no mostrar ninguno. Para esto, puedes usar el método `getOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, tal como se detalla en la sección [Obtener el onboarding](#fetch-onboarding) anterior. :::warning Considera usar `getOnboarding` en lugar de `getOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: Puede generar problemas al mantener varias versiones de la app, lo que exige diseños retrocompatibles o asumir que versiones más antiguas podrían mostrarse incorrectamente. - **Sin personalización**: Solo muestra contenido para la audiencia "All Users", eliminando la segmentación por país, atribución o atributos personalizados. Si la mayor velocidad de obtención compensa estos inconvenientes en tu caso de uso, utiliza `getOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getOnboarding` tal como se describe [arriba](#fetch-onboarding). ::: ```kotlin showLineNumbers Adapty.getOnboardingForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` Parámetros: | Parámetro | Presencia | Descripción | |---------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
| El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En ese caso, puede que los usuarios no reciban los datos más recientes, pero tendrán tiempos de carga más rápidos independientemente de la calidad de su conexión. La caché se actualiza con regularidad, por lo que es seguro usarla durante la sesión para evitar peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización periódica descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings y asegurar la fiabilidad incluso cuando la conexión a internet es limitada.
| --- # File: kmp-present-onboardings --- --- title: "Presentar onboardings en Kotlin Multiplatform SDK" description: "Aprende a presentar onboardings de forma efectiva para impulsar más conversiones." --- Si has personalizado un onboarding con el builder, no necesitas preocuparte por renderizarlo en el código de tu app Kotlin Multiplatform para mostrárselo al usuario. Ese onboarding incluye tanto lo que debe mostrarse como la forma en que debe hacerlo. Antes de empezar, asegúrate de que: 1. Tienes instalado [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) 3.16.1 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). El SDK de Adapty para Kotlin Multiplatform ofrece dos formas de presentar onboardings: - **Con Compose Multiplatform** - **Sin Compose Multiplatform** ## Con Compose Multiplatform \{#with-compose-multiplatform\} Para mostrar un onboarding, usa el método `view.present()` sobre el `view` creado por el método `createOnboardingView`. Cada `view` solo puede usarse una vez. Si necesitas mostrar el onboarding de nuevo, llama a `createOnboardingView` otra vez para crear una nueva instancia de `view`. :::warning Reutilizar el mismo `view` sin recrearlo puede producir un error. ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createOnboardingView(onboarding = onboarding).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### Configurar el estilo de presentación en iOS \{#configure-ios-presentation-style\} Configura cómo se presenta el onboarding en iOS pasando el parámetro `iosPresentationStyle` al método `present()`. El parámetro acepta los valores `AdaptyUIIOSPresentationStyle.FULLSCREEN` (predeterminado) o `AdaptyUIIOSPresentationStyle.PAGESHEET`. ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createOnboardingView(onboarding = onboarding).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ### Personalizar cómo se abren los enlaces en los onboardings \{#customize-how-links-open-in-onboardings\} Por defecto, los enlaces de los onboardings se abren en un navegador in-app. Esto ofrece una experiencia fluida al mostrar las páginas web dentro de tu aplicación, sin que el usuario tenga que cambiar de app. Si prefieres que los enlaces se abran en un navegador externo, puedes personalizar este comportamiento estableciendo el parámetro `externalUrlsPresentation` en `AdaptyWebPresentation.EXTERNAL_BROWSER`: ```kotlin showLineNumbers viewModelScope.launch { AdaptyUI.createOnboardingView( onboarding = onboarding, externalUrlsPresentation = AdaptyWebPresentation.EXTERNAL_BROWSER // default – IN_APP_BROWSER ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ## Sin Compose Multiplatform \{#without-compose-multiplatform\} :::note `createNativeOnboardingView` forma parte del módulo principal `io.adapty:adapty-kmp`. Si tu proyecto no usa Compose Multiplatform, no necesitas la dependencia `io.adapty:adapty-kmp-ui`. ::: Para integrar un onboarding sin Compose Multiplatform, llama a `createNativeOnboardingView`. Devuelve un `AdaptyNativeOnboardingView` que añades a tu layout:
Por ejemplo, si un usuario pulsa un botón personalizado como **Login** o **Allow notifications**, se activará el método delegado `onCustomAction` con el ID de acción definido en el builder. Puedes crear tus propios IDs, como "allowNotifications".
```kotlin
class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver {
override fun onboardingViewOnCustomAction(
view: AdaptyUIOnboardingView,
meta: AdaptyUIOnboardingMeta,
actionId: String
) {
when (actionId) {
"openPaywall" -> {
// Display paywall from onboarding
// You would typically fetch and present a new paywall here
mainUiScope.launch {
// Example: Get paywall by placement ID
// val paywallResult = Adapty.getPaywall("your_placement_id")
// paywallResult.onSuccess { paywall ->
// val paywallViewResult = AdaptyUI.createPaywallView(paywall)
// paywallViewResult.onSuccess { paywallView ->
// paywallView.present()
// }
// }
}
}
"allowNotifications" -> {
// Handle notification permissions
}
else -> {
// Handle other custom actions
}
}
}
}
// Set up the observer
AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver())
```
2. Haz clic en el nombre del grupo de suscripción. Verás tus productos listados en la sección **Subscriptions**.
3. Asegúrate de que el producto que estás probando esté marcado como **Ready to Submit**. Si no lo está, sigue las instrucciones de la página [Producto en App Store](app-store-products).
4. Compara el ID del producto en la tabla con el que aparece en la pestaña [**Products**](https://app.adapty.io/products) del Adapty Dashboard. Si los IDs no coinciden, copia el ID del producto de la tabla y [crea un producto](create-product) con ese ID en el Adapty Dashboard.
## Paso 3. Comprueba la disponibilidad del producto \{#step-4-check-product-availability\}
1. Vuelve a **App Store Connect** y abre la misma sección **Subscriptions**.
2. Haz clic en el nombre del grupo de suscripción para ver tus productos.
3. Selecciona el producto que estás probando.
4. Desplázate hasta la sección **Availability** y comprueba que todos los países y regiones requeridos estén listados.
## Paso 4. Comprueba los precios del producto \{#step-5-check-product-prices\}
1. De nuevo, ve a la sección **Monetization** → **Subscriptions** en **App Store Connect**.
2. Haz clic en el nombre del grupo de suscripción.
3. Selecciona el producto que estás probando.
4. Desplázate hacia abajo hasta **Subscription Pricing** y despliega la sección **Current Pricing for New Subscribers**.
5. Asegúrate de que todos los precios requeridos estén listados.
## Paso 5. Comprueba que el estado de pago de la app, la cuenta bancaria y los formularios fiscales estén activos \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. En la página de inicio de [**App Store Connect**](https://appstoreconnect.apple.com/), haz clic en **Business**.
2. Selecciona el nombre de tu empresa.
3. Desplázate hacia abajo y comprueba que tu **Paid Apps Agreement**, **Bank Account** y **Tax forms** aparezcan como **Active**.
Siguiendo estos pasos deberías poder resolver la advertencia `InvalidProductIdentifiers` y hacer que tus productos estén disponibles en el store.
## Paso 6. Vuelve a crear el producto si está bloqueado \{#step-6-recreate-the-product-if-its-stuck\}
Es posible que los pasos 1–5 pasen correctamente —estado `Approved`, Bundle ID coincidente, API key válida— y el SDK siga devolviendo `1000 noProductIDsFound`. En ese caso, puede que el producto esté bloqueado en el registro de Apple. El registro de productos de Apple puede entrar en un estado en el que el producto existe en la interfaz de App Store Connect pero no está expuesto a la ruta de búsqueda de StoreKit.
Elimina el producto en App Store Connect y vuelve a crearlo con el mismo ID de producto. Espera hasta 24 horas tras la recreación para que los cambios se propaguen.
---
# File: cantMakePayments-kmp
---
---
title: "Solución para el error Code-1003 cantMakePayment en el SDK de Kotlin Multiplatform"
description: "Resuelve el error al realizar pagos cuando gestionas suscripciones en Adapty."
---
El error 1003, `cantMakePayments`, indica que no es posible realizar compras in-app en este dispositivo.
Si encuentras el error `cantMakePayments`, normalmente se debe a una de estas razones:
- Restricciones del dispositivo: El error no está relacionado con Adapty. Consulta las soluciones más abajo.
- Configuración del modo Observer: El método `makePurchase` y el modo Observer no pueden usarse al mismo tiempo. Consulta la sección más abajo.
## Problema: Restricciones del dispositivo \{#issue-device-restrictions\}
| Problema | Solución |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Restricciones de Screen Time | Desactiva las restricciones de compras in-app en [Screen Time](https://support.apple.com/en-us/102470) |
| Cuenta suspendida | Contacta con el soporte de Apple para resolver problemas con la cuenta |
| Restricciones regionales | Usa una cuenta de App Store de una región compatible |
## Problema: Usar el modo Observer y makePurchase a la vez \{#issue-using-both-observer-mode-and-makepurchase\}
Si usas `makePurchases` para gestionar las compras, no necesitas el modo Observer. El [modo Observer](observer-vs-full-mode) solo es necesario si implementas la lógica de compra tú mismo.
Por lo tanto, si usas `makePurchase`, puedes eliminar sin problema la activación del modo Observer del código de inicialización del SDK.
---
# File: kmp-sdk-migration-guides
---
---
title: "Kotlin Multiplatform SDK Migration Guides"
description: "Migration guides for Adapty Kotlin Multiplatform SDK versions."
---
This page contains all migration guides for Adapty Kotlin Multiplatform SDK. Choose the version you want to migrate to for detailed instructions:
- **[Migrate to v. 3.15](migration-to-kmp-315)**
---
# File: migration-to-kmp-315
---
---
title: "Guía de migración al SDK de Adapty Kotlin Multiplatform 3.15.0"
description: "Pasos de migración para el SDK de Adapty Kotlin Multiplatform 3.15.0"
---
El SDK de Adapty Kotlin Multiplatform 3.15.0 es una versión mayor que trae nuevas funcionalidades y mejoras que, sin embargo, pueden requerir algunos pasos de migración por tu parte.
1. Actualiza los nombres de la clase observer y sus métodos.
2. Actualiza el nombre del método para los paywalls de respaldo.
3. Actualiza el nombre de la clase de vista en los métodos de gestión de eventos.
## Actualiza los nombres de la clase observer y sus métodos \{#update-observer-class-and-method-names\}
La clase observer y su método de registro han sido renombrados:
```diff
- import com.adapty.kmp.AdaptyUIObserver
+ import com.adapty.kmp.AdaptyUIPaywallsEventsObserver
- import com.adapty.kmp.models.AdaptyUIView
+ import com.adapty.kmp.models.AdaptyUIPaywallView
- class MyAdaptyUIObserver : AdaptyUIObserver {
- override fun paywallViewDidPerformAction(view: AdaptyUIView, action: AdaptyUIAction) {
+ class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver {
+ override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) {
// handle actions
}
}
// Set up the observer
- AdaptyUI.setObserver(MyAdaptyUIObserver())
+ AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver())
```
## Actualiza el nombre del método para los paywalls de respaldo \{#update-fallback-paywalls-method-name\}
El nombre del método para configurar los paywalls de respaldo ha cambiado:
```diff showLineNumbers
- Adapty.setFallbackPaywalls(assetId = "fallback.json")
+ Adapty.setFallback(assetId = "fallback.json")
.onSuccess {
// Fallback paywalls loaded successfully
}
.onError { error ->
// Handle the error
}
```
## Actualiza el nombre de la clase de vista en los métodos de gestión de eventos \{#update-view-class-name-in-event-handling-methods\}
Todos los métodos de gestión de eventos usan ahora la nueva clase `AdaptyUIPaywallView` en lugar de `AdaptyUIView`:
```diff
- override fun paywallViewDidAppear(view: AdaptyUIView) {
+ override fun paywallViewDidAppear(view: AdaptyUIPaywallView) {
// Handle paywall appearance
}
- override fun paywallViewDidDisappear(view: AdaptyUIView) {
+ override fun paywallViewDidDisappear(view: AdaptyUIPaywallView) {
// Handle paywall disappearance
}
- override fun paywallViewDidSelectProduct(view: AdaptyUIPaywallView, productId: String) {
+ override fun paywallViewDidSelectProduct(view: AdaptyUIView, productId: String) {
// Handle product selection
}
- override fun paywallViewDidStartPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct) {
+ override fun paywallViewDidStartPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct) {
// Handle purchase start
}
- override fun paywallViewDidFinishPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) {
+ override fun paywallViewDidFinishPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) {
// Handle purchase result
}
- override fun paywallViewDidFailPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, error: AdaptyError) {
+ override fun paywallViewDidFailPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, error: AdaptyError) {
// Add your purchase failure handling logic here
}
- override fun paywallViewDidFinishRestore(view: AdaptyUIView, profile: AdaptyProfile) {
+ override fun paywallViewDidFinishRestore(view: AdaptyUIPaywallView, profile: AdaptyProfile) {
// Add your successful restore handling logic here
}
- override fun paywallViewDidFailRestore(view: AdaptyUIView, error: AdaptyError) {
+ override fun paywallViewDidFailRestore(view: AdaptyUIPaywallView, error: AdaptyError) {
// Add your restore failure handling logic here
}
- override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIView, product: AdaptyPaywallProduct?, error: AdaptyError?) {
+ override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct?, error: AdaptyError?) {
// Handle web payment navigation result
}
- override fun paywallViewDidFailLoadingProducts(view: AdaptyUIView, error: AdaptyError) {
+ override fun paywallViewDidFailLoadingProducts(view: AdaptyUIPaywallView, error: AdaptyError) {
// Add your product loading failure handling logic here
}
- override fun paywallViewDidFailRendering(view: AdaptyUIView, error: AdaptyError) {
+ override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) {
// Handle rendering error
}
```
---
# End of Documentation
_Generated on: 2026-05-15T20:13:57.595Z_
_Successfully processed: 44/44 files_
# REACT-NATIVE - Adapty Documentation (Full Content)
This file contains the complete content of all documentation pages for this platform.
Locale: es
Generated on: 2026-05-15T20:13:57.596Z
Total files: 40
---
# File: sdk-installation-react-native-expo
---
---
title: "Instalar y configurar el SDK de Adapty para React Native en un proyecto Expo"
description: "Guía paso a paso para instalar el SDK de Adapty para React Native en un proyecto Expo para apps con suscripciones."
---
:::important
Esta guía cubre la instalación y configuración del SDK de Adapty para React Native **en un proyecto Expo**.
Si usas **React Native puro (sin Expo)**, sigue la [guía de instalación para React Native](sdk-installation-react-native-pure).
:::
El SDK de Adapty incluye dos módulos clave para una integración fluida en tu app de React Native:
- **Core Adapty**: Este módulo es necesario para que Adapty funcione correctamente en tu app.
- **AdaptyUI**: Este módulo es necesario si usas el [Adapty Paywall Builder](adapty-paywall-builder), una herramienta visual sin código para crear paywalls multiplataforma fácilmente. AdaptyUI se activa automáticamente junto con el módulo principal.
Si quieres un tutorial completo sobre cómo implementar compras in-app en tu app de React Native, consulta [este artículo](https://adapty.io/blog/react-native-in-app-purchases-tutorial/).
:::tip
¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app Expo? Echa un vistazo a nuestras apps de ejemplo:
- [Ejemplo con Expo dev build](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) para funcionalidad completa con compras reales y Paywall Builder
- [Ejemplo con Expo Go y Web](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) para pruebas con modo mock
:::
Para un recorrido completo de la implementación, también puedes ver el vídeo:
### Durante el inicio de sesión/registro \{#during-loginsignup\}
Si identificas a los usuarios después del inicio de la app (por ejemplo, cuando inician sesión o se registran), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario antes**, Adapty pasará a trabajar con el perfil asociado a ese customer user ID.
:::important
Los customer user IDs deben ser únicos para cada usuario. Si hardcodeas el valor del parámetro, todos los usuarios se considerarán como uno solo.
:::
Siempre usa `await` con `identify` antes de llamar a otros métodos del SDK. Las llamadas concurrentes generan `#3006 profileWasChanged` o aterrizan en el perfil anónimo. Consulta [Orden de llamadas en el SDK de React Native](react-native-sdk-call-order).
```typescript showLineNumbers
try {
await adapty.identify("YOUR_USER_ID"); // Unique for each user
// successfully identified
} catch (error) {
// handle the error
}
```
### Durante la activación del SDK \{#during-the-sdk-activation\}
Si ya conoces el customer user ID cuando activas el SDK, puedes enviarlo en el método `activate` en lugar de llamar a `identify` por separado.
Si conoces un customer user ID pero solo lo configuras después de la activación, eso significa que, al activarse, Adapty creará un nuevo perfil anónimo y solo pasará al existente cuando llames a `identify`.
Puedes pasar un customer user ID existente (uno que ya hayas usado antes) o uno nuevo. Si pasas uno nuevo, el perfil creado al activarse se vinculará automáticamente a ese customer user ID.
:::note
Por defecto, la creación de perfiles anónimos no afecta a los dashboards de análisis, porque las instalaciones se cuentan por IDs de dispositivo.
Un ID de dispositivo representa una única instalación de la app desde el store en un dispositivo y solo se regenera cuando la app se reinstala.
No depende de si es la primera instalación o una repetida, ni de si se usa un customer user ID existente.
Crear un perfil (al activar el SDK o al cerrar sesión), iniciar sesión o actualizar la app sin reinstalarla no genera eventos de instalación adicionales.
Si quieres contar las instalaciones por usuarios únicos en lugar de por dispositivos, ve a **App settings** y configura [**Installs definition for analytics**](general#4-installs-definition-for-analytics).
:::
```typescript showLineNumbers
adapty.activate("PUBLIC_SDK_KEY", {
customerUserId: "YOUR_USER_ID" // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one.
});
```
### Cerrar sesión de usuarios \{#log-users-out\}
Si tienes un botón para cerrar la sesión de los usuarios, usa el método `logout`.
:::important
Cerrar la sesión crea un nuevo perfil anónimo para el usuario.
:::
```typescript showLineNumbers
try {
await adapty.logout();
// successful logout
} catch (error) {
// handle the error
}
```
:::info
Para volver a iniciar sesión en la app, usa el método `identify`.
:::
### Permitir compras sin inicio de sesión \{#allow-purchases-without-login\}
Si tus usuarios pueden realizar compras tanto antes como después de iniciar sesión en tu app, debes asegurarte de que mantengan el acceso después de iniciar sesión:
1. Cuando un usuario sin sesión iniciada realiza una compra, Adapty la vincula a su ID de perfil anónimo.
2. Cuando el usuario inicia sesión en su cuenta, Adapty pasa a trabajar con su perfil identificado.
- Si es un customer user ID nuevo (por ejemplo, la compra se realizó antes del registro), Adapty asigna el customer user ID al perfil actual, por lo que se mantiene todo el historial de compras.
- Si es un customer user ID existente (el customer user ID ya está vinculado a un perfil), necesitas obtener el nivel de acceso actual después del cambio de perfil. Puedes llamar a [`getProfile`](react-native-check-subscription-status) justo después de la identificación, o [escuchar las actualizaciones del perfil](react-native-check-subscription-status) para que los datos se sincronicen automáticamente.
## Próximos pasos \{#next-steps\}
¡Enhorabuena! Has implementado la lógica de pago in-app en tu app. ¡Te deseamos todo lo mejor con la monetización de tu app!
Para sacar aún más partido a Adapty, puedes explorar estos temas:
- [**Pruebas**](troubleshooting-test-purchases): Asegúrate de que todo funciona como se espera
- [**Onboardings**](react-native-onboardings): Engancha a los usuarios con onboardings y aumenta la retención
- [**Integraciones**](configuration): Integra con servicios de atribución de marketing y análisis con una sola línea de código
- [**Establecer atributos de perfil personalizados**](react-native-setting-user-attributes): Añade atributos personalizados a los perfiles de usuario y crea segmentos para lanzar pruebas A/B o mostrar diferentes paywalls a distintos usuarios
---
# File: adapty-cursor-react-native
---
---
title: "Integra Adapty en tu app de React Native con ayuda de IA"
description: "Una guía paso a paso para integrar Adapty en tu app de React Native usando Cursor, Context7, ChatGPT, Claude u otras herramientas de IA."
---
Esta página explica dos formas de integrar Adapty en tu app de React Native. Usa la skill de integración del SDK que encontrarás a continuación para un flujo automatizado de extremo a extremo, o sigue el tutorial manual más abajo.
## Usa la skill de integración del SDK (beta) \{#use-the-sdk-integration-skill-beta\}
La [skill adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza la integración de principio a fin: configuración del dashboard, instalación del SDK, paywall y verificación por etapas. El tutorial manual que aparece más abajo es la alternativa si tu herramienta no es compatible con el formato Claude Skills.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
### Instalación \{#install\}
Elige el formato según tu herramienta. La lista completa está en el [README de la skill](https://github.com/adaptyteam/adapty-sdk-integration-skill).
- **Claude Code**: Ejecuta `claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill` y luego `claude plugin install adapty-sdk-integration@adapty` desde tu terminal.
- **GitHub Copilot CLI**: Ejecuta `gh skill install adaptyteam/adapty-sdk-integration-skill`.
- **Gemini CLI**: Ejecuta `gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill`.
- **OpenAI Codex u otra herramienta**: Clona el repositorio y copia `plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` en el directorio de skills de tu herramienta.
### Ejecución \{#run\}
En tu proyecto, ejecuta `/adapty-sdk-integration`. La skill detecta tu plataforma y hace algunas preguntas de configuración. Luego guía paso a paso por la configuración del dashboard, la instalación del SDK, el paywall y la verificación — obteniendo la documentación de Adapty relevante en cada etapa.
:::note
La skill está en beta. Si se bloquea o se comporta de forma inesperada, el tutorial manual que aparece a continuación cubre cada etapa paso a paso.
:::
## Antes de empezar: configuración del dashboard \{#before-you-start-dashboard-setup\}
Adapty requiere cierta configuración en el dashboard antes de escribir código con el SDK. Puedes hacerlo con una skill interactiva de LLM o manualmente a través del Dashboard.
### Enfoque con skill (recomendado) \{#skill-approach-recommended\}
La skill Adapty CLI permite que tu LLM configure tu app, productos, niveles de acceso, paywalls y placements directamente, sin necesidad de abrir el Dashboard en cada paso. Solo tienes que [conectar tus stores](integrate-payments) en el Dashboard.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Una vez añadida la skill, ejecuta `/adapty-cli` en tu agente. Te guiará por cada paso, incluyendo cuándo abrir el Dashboard para conectar tus stores.
### Enfoque manual por el Dashboard \{#dashboard-approach\}
Si prefieres configurarlo todo manualmente, esto es lo que necesitas antes de escribir código. Tu LLM no puede consultar los valores del dashboard por ti — tendrás que proporcionarlos tú.
1. **Conecta tus stores**: En el Adapty Dashboard, ve a **App settings → General**. Conecta tanto App Store como Google Play si tu app está disponible en ambas plataformas. Esto es necesario para que las compras funcionen.
[Conectar stores](integrate-payments)
2. **Copia tu clave SDK pública**: En el Adapty Dashboard, ve a **App settings → General** y busca la sección **API keys**. En el código, esta es la cadena que pasas a `adapty.activate("YOUR_PUBLIC_SDK_KEY")`.
3. **Crea al menos un producto**: En el Adapty Dashboard, ve a la página **Products**. No haces referencia a los productos directamente en el código — Adapty los entrega a través de paywalls.
[Añadir productos](quickstart-products)
4. **Crea un paywall y un placement**: En el Adapty Dashboard, crea un paywall en la página **Paywalls** y asígnalo a un placement en la página **Placements**. En el código, el ID del placement es la cadena que pasas a `adapty.getPaywall("YOUR_PLACEMENT_ID")`.
[Crear paywall](quickstart-paywalls)
5. **Configura los niveles de acceso**: En el Adapty Dashboard, configúralos por producto en la página **Products**. En el código, la cadena que se comprueba en `profile.accessLevels['premium']?.isActive`. El nivel de acceso `premium` predeterminado funciona para la mayoría de las apps. Si los usuarios de pago tienen acceso a funciones distintas según el producto (por ejemplo, un plan `basic` frente a un plan `pro`), [crea niveles de acceso adicionales](assigning-access-level-to-a-product) antes de empezar a programar.
:::tip
Una vez que tengas los cinco, estás listo para escribir código. Dile a tu LLM: "Mi clave SDK pública es X, mi ID de placement es Y" para que pueda generar el código de inicialización y de obtención de paywalls correcto.
:::
### Configurar cuando estés listo \{#set-up-when-ready\}
Esto no es necesario para empezar a programar, pero lo querrás a medida que tu integración madure:
- **Pruebas A/B**: Configúralas en la página **Placements**. No se necesita ningún cambio de código.
[Pruebas A/B](ab-tests)
- **Paywalls y placements adicionales**: Añade más llamadas a `getPaywall` con distintos IDs de placement.
- **Integraciones de analítica**: Configúralas en la página **Integrations**. La configuración varía según la integración. Consulta [integraciones de analítica](analytics-integration) e [integraciones de atribución](attribution-integration).
## Dale documentación de Adapty a tu LLM \{#feed-adapty-docs-to-your-llm\}
### Usa Context7 (recomendado) \{#use-context7-recommended\}
[Context7](https://context7.com) es un servidor MCP que da a tu LLM acceso directo a la documentación actualizada de Adapty. Tu LLM obtiene la documentación correcta automáticamente según lo que preguntes — sin necesidad de pegar URLs manualmente.
Context7 funciona con **Cursor**, **Claude Code**, **Windsurf** y otras herramientas compatibles con MCP. Para configurarlo, ejecuta:
```
npx ctx7 setup
```
Esto detecta tu editor y configura el servidor Context7. Para la configuración manual, consulta el [repositorio de Context7 en GitHub](https://github.com/upstash/context7).
Una vez configurado, haz referencia a la biblioteca de Adapty en tus prompts:
```
Use the adaptyteam/adapty-docs library to look up how to install the React Native SDK
```
:::warning
Aunque Context7 elimina la necesidad de pegar enlaces a la documentación manualmente, el orden de implementación es importante. Sigue el [tutorial de implementación](#implementation-walkthrough) que aparece a continuación paso a paso para asegurarte de que todo funciona.
:::
### Usa documentación en texto plano \{#use-plain-text-docs\}
Puedes acceder a cualquier documento de Adapty como Markdown en texto plano. Añade `.md` al final de su URL o haz clic en **Copy for LLM** debajo del título del artículo. Por ejemplo: [adapty-cursor-react-native.md](https://adapty.io/docs/es/adapty-cursor-react-native.md).
Cada etapa del [tutorial de implementación](#implementation-walkthrough) que aparece a continuación incluye un bloque "Envía esto a tu LLM" con enlaces `.md` para pegar.
Para obtener más documentación a la vez, consulta los [archivos de índice y subconjuntos específicos por plataforma](#plain-text-doc-index-files) que aparecen más abajo.
## Tutorial de implementación \{#implementation-walkthrough\}
El resto de esta guía recorre la integración de Adapty en el orden de implementación. Cada etapa incluye la documentación que debes enviar a tu LLM, lo que deberías ver al terminar y los problemas más frecuentes.
### Planifica tu integración \{#plan-your-integration\}
Antes de escribir código, pide a tu LLM que analice tu proyecto y cree un plan de implementación. Si tu herramienta de IA dispone de un modo de planificación (como el de Cursor o Claude Code), úsalo para que el LLM pueda leer tanto la estructura de tu proyecto como la documentación de Adapty antes de escribir código.
Dile a tu LLM qué enfoque usas para las compras — esto afecta a las guías que debe seguir:
- [**Adapty Paywall Builder**](adapty-paywall-builder): Creas los paywalls en el editor no-code de Adapty y el SDK los renderiza automáticamente.
- [**Paywalls creados manualmente**](react-native-making-purchases): Construyes tu propia interfaz de paywall en código, pero sigues usando Adapty para obtener productos y gestionar compras.
- [**Modo Observer**](observer-vs-full-mode): Mantienes tu infraestructura de compras existente y usas Adapty solo para analítica e integraciones.
¿No sabes cuál elegir? Lee la [tabla de comparación en la guía de inicio rápido](react-native-quickstart-paywalls).
### Instala y configura el SDK \{#install-and-configure-the-sdk\}
Añade la dependencia del SDK de Adapty usando npm (o yarn) y actívalo con tu clave SDK pública. Esta es la base — nada más funciona sin esto.
Tenemos guías de instalación separadas para proyectos Expo y React Native puro — elige la que corresponda a tu configuración.
**Guías:**
- [Instalar con Expo](sdk-installation-react-native-expo)
- [Instalar con React Native puro](sdk-installation-react-native-pure)
Envía esto a tu LLM (elige la que corresponda a tu configuración, o envía ambas):
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/es/sdk-installation-react-native-expo.md
- https://adapty.io/docs/es/sdk-installation-react-native-pure.md
```
:::tip[Punto de verificación]
- **Resultado esperado:** La app compila y se ejecuta en iOS y Android. Los logs del bundler Metro muestran el log de activación de Adapty.
- **Problema frecuente:** "Public API key is missing" → comprueba que reemplazaste el marcador de posición con tu clave real de App settings.
:::
### Muestra paywalls y gestiona compras \{#show-paywalls-and-handle-purchases\}
Obtén un paywall por ID de placement, muéstralo y gestiona los eventos de compra. Las guías que necesitas dependen de cómo gestionas las compras.
Prueba cada compra en el sandbox a medida que avanzas — no esperes hasta el final. Consulta [Probar compras en sandbox](test-purchases-in-sandbox) para las instrucciones de configuración.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En ese caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché de actualización regular descrita anteriormente y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que la CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeoutMs** | por defecto: 5 seg |Este valor limita el tiempo de espera de este método. Si se alcanza el límite, se devolverán los datos en caché o el fallback local.
Ten en cuenta que en casos excepcionales este método puede agotar el tiempo de espera un poco después de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
Para Android: puedes crear `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` es de `import com.adapty.utils.seconds`), o `TimeInterval.seconds(5)`. Para no establecer ningún límite, usa `TimeInterval.INFINITE`.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | Un objeto [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) con una lista de IDs de productos, el identificador del paywall, Remote Config y varias otras propiedades. | ## Obtener la configuración de vista del paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el toggle **Show on device** en el Paywall Builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperar. ::: Después de obtener el paywall, comprueba si incluye una `ViewConfiguration`, lo que indica que fue creado con Paywall Builder. Esto te orientará sobre cómo mostrar el paywall. Si la `ViewConfiguration` está presente, trátalo como un paywall de Paywall Builder; si no, [manéjalo como un paywall de Remote Config](present-remote-config-paywalls-react-native). En el SDK de React Native, llama directamente al método `createPaywallView` sin necesidad de obtener la configuración de vista manualmente primero. :::warning El resultado del método `createPaywallView` solo puede usarse una vez. Si necesitas usarlo de nuevo, llama al método `createPaywallView` nuevamente. Llamarlo dos veces sin recrearlo puede provocar el error `AdaptyUIError.viewAlreadyPresented`. ::: ```typescript showLineNumbers // for the Adapty SDK < 3.14 – import {createPaywallView} from 'react-native-adapty/dist/ui'; if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { //use your custom logic } ``` Parámetros: | Parámetro | Presencia | Descripción | | :------------------- | :------- | :----------------------------------------------------------- | | **paywall** | obligatorio | Un objeto `AdaptyPaywall` para obtener un controlador del paywall deseado. | | **customTags** | opcional | Define un diccionario de etiquetas personalizadas y sus valores resueltos. Las etiquetas personalizadas funcionan como marcadores de posición en el contenido del paywall, reemplazados dinámicamente con cadenas específicas para contenido personalizado. Consulta el tema [Etiquetas personalizadas en el Paywall Builder](custom-tags-in-paywall-builder) para más detalles. | | **prefetchProducts** | opcional | Actívalo para optimizar el tiempo de visualización de los productos en pantalla. Cuando es `true`, AdaptyUI obtendrá automáticamente los productos necesarios. Por defecto: `false`. | :::note Si usas varios idiomas, aprende cómo añadir una [localización de Paywall Builder](add-paywall-locale-in-adapty-paywall-builder) y cómo usar los códigos de idioma correctamente [aquí](react-native-localizations-and-locale-codes). ::: Una vez que tengas la vista, [presenta el paywall](react-native-present-paywalls). ## Obtener un paywall para la audiencia predeterminada para cargarlo más rápido \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Por lo general, los paywalls se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, en casos en los que tienes numerosas audiencias y paywalls y tus usuarios tienen una conexión a internet débil, obtener un paywall puede tardar más de lo deseable. En esas situaciones, puede que quieras mostrar un paywall predeterminado para garantizar una experiencia de usuario fluida en lugar de no mostrar ninguno. Para abordar esto, puedes usar el método `getPaywallForDefaultAudience`, que obtiene el paywall del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el paywall con el método `getPaywall`, como se detalla en la sección [Obtener el paywall](#fetch-paywall-designed-with-paywall-builder) anterior. :::warning Por qué recomendamos usar `getPaywall` El método `getPaywallForDefaultAudience` tiene algunos inconvenientes importantes: - **Posibles problemas de compatibilidad con versiones anteriores**: si necesitas mostrar diferentes paywalls para distintas versiones de la app (actual y futuras), puedes encontrarte con dificultades. Tendrás que diseñar paywalls compatibles con la versión actual (legacy) o aceptar que los usuarios con esa versión puedan encontrar problemas con paywalls que no se renderizan. - **Pérdida de segmentación**: todos los usuarios verán el mismo paywall diseñado para la audiencia **All Users**, lo que significa que pierdes la segmentación personalizada (incluida la basada en países, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a aceptar estos inconvenientes para beneficiarte de una carga más rápida de paywalls, usa el método `getPaywallForDefaultAudience` de la siguiente manera. De lo contrario, usa `getPaywall` descrito [arriba](#fetch-paywall-designed-with-paywall-builder). ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywallForDefaultAudience(id, locale); // the requested paywall } catch (error) { // handle the error } ``` :::note El método `getPaywallForDefaultAudience` está disponible a partir de la versión 2.11.2 del SDK de React Native. ::: | Parámetro | Presencia | Descripción | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements). Es el valor que especificaste al crear un placement en tu Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](react-native-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver datos en caché si existen. En ese caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
| ## Personalizar recursos \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los recursos personalizados. Las imágenes y vídeos destacados tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de recursos personalizados, apuntas a estos elementos por sus IDs y personalizas su comportamiento. Para otras imágenes y vídeos, debes [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta función, actualiza el SDK de React Native de Adapty a la versión 3.8.0 o superior. ::: Aquí tienes un ejemplo de cómo puedes proporcionar recursos personalizados mediante un diccionario sencillo: ```javascript const customAssets: Record
## El número de vistas del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El recuento de vistas del paywall muestra el doble del número esperado.
**Causa**: Es posible que estés llamando a `logShowPaywall` en tu código, lo que duplica el recuento de vistas si usas el Paywall Builder. Para los paywalls diseñados con el Paywall Builder, las analíticas se registran automáticamente, por lo que no es necesario usar este método.
**Solución**: Asegúrate de no llamar a `logShowPaywall` en tu código si estás usando el Paywall Builder.
## Otros problemas \{#other-issues\}
**Problema**: Estás experimentando otros problemas relacionados con el Paywall Builder que no se tratan arriba.
**Solución**: Migra el SDK a la última versión siguiendo las [guías de migración](react-native-sdk-migration-guides) si es necesario. Muchos problemas se resuelven en versiones más recientes del SDK.
---
# File: react-native-quickstart-manual
---
---
title: "Habilitar compras en tu paywall personalizado en el SDK de React Native"
description: "Integra el SDK de Adapty en tus paywalls personalizados de React Native para habilitar compras in-app."
---
Esta guía describe cómo integrar Adapty en tus paywalls personalizados. Mantén el control total sobre la implementación del paywall, mientras el SDK de Adapty obtiene los productos, gestiona las nuevas compras y restaura las anteriores.
:::important
**Esta guía es para desarrolladores que implementan paywalls personalizados.** Si quieres la forma más sencilla de habilitar compras, usa el [Paywall Builder de Adapty](react-native-quickstart-paywalls). Con el Paywall Builder, creas paywalls en un editor visual sin código, Adapty gestiona toda la lógica de compras automáticamente y puedes probar distintos diseños sin volver a publicar tu app.
:::
## Antes de empezar \{#before-you-start\}
### Configura los productos \{#set-up-products\}
Para habilitar las compras in-app, necesitas entender tres conceptos clave:
- [**Productos**](product) – cualquier cosa que los usuarios pueden comprar (suscripciones, consumibles, acceso de por vida)
- [**Paywalls**](paywalls) – configuraciones que definen qué productos ofrecer. En Adapty, los paywalls son la única forma de recuperar productos, pero este diseño te permite modificar productos, precios y ofertas sin tocar el código de tu app.
- [**Placements**](placements) – dónde y cuándo muestras los paywalls en tu app (como `main`, `onboarding`, `settings`). Configuras los paywalls para los placements en el dashboard y luego los solicitas por ID de placement en tu código. Esto facilita ejecutar pruebas A/B y mostrar diferentes paywalls a distintos usuarios.
Asegúrate de entender estos conceptos aunque trabajes con tu paywall personalizado. Básicamente, son tu manera de gestionar los productos que vendes en tu app.
Para implementar tu paywall personalizado, necesitarás crear un **paywall** y añadirlo a un **placement**. Esta configuración te permite recuperar tus productos. Para entender qué debes hacer en el dashboard, sigue la guía de inicio rápido [aquí](quickstart).
### Gestión de usuarios \{#manage-users\}
Puedes trabajar con o sin autenticación de backend de tu parte.
Sin embargo, el SDK de Adapty gestiona los usuarios anónimos e identificados de forma diferente. Lee la [guía de inicio rápido de identificación](react-native-quickstart-identify) para entender los detalles y asegurarte de que estás trabajando con los usuarios correctamente.
## Paso 1. Obtén los productos \{#step-1-get-products\}
Para recuperar los productos de tu paywall personalizado, necesitas:
1. Obtener el objeto `paywall` pasando el ID del [placement](placements) al método `getPaywall`.
2. Obtener el array de productos para ese paywall usando el método `getPaywallProducts`.
```typescript showLineNumbers
async function loadPaywall() {
try {
const paywall: AdaptyPaywall = await adapty.getPaywall('YOUR_PLACEMENT_ID');
const products: AdaptyPaywallProduct[] = await adapty.getPaywallProducts(paywall);
// Use products to build your custom paywall UI
} catch (error) {
// Handle the error
}
}
```
## Paso 2. Acepta las compras \{#step-2-accept-purchases\}
Cuando un usuario pulsa en un producto de tu paywall personalizado, llama al método `makePurchase` con el producto seleccionado. Esto gestionará el flujo de compra y devolverá el perfil actualizado.
```typescript showLineNumbers
async function purchaseProduct(product: AdaptyPaywallProduct) {
try {
const purchaseResult: AdaptyPurchaseResult = await adapty.makePurchase(product);
switch (purchaseResult.type) {
case 'success':
// Purchase successful, profile updated
break;
case 'user_cancelled':
// User canceled the purchase
break;
case 'pending':
// Purchase is pending (e.g., user will pay offline with cash)
break;
}
} catch (error) {
// Handle the error
}
}
```
## Paso 3. Restaura las compras \{#step-3-restore-purchases\}
Los stores de aplicaciones exigen que todas las apps con suscripciones ofrezcan una forma de que los usuarios puedan restaurar sus compras.
Llama al método `restorePurchases` cuando el usuario pulse el botón de restaurar. Esto sincronizará su historial de compras con Adapty y devolverá el perfil actualizado.
```typescript showLineNumbers
async function restorePurchases() {
try {
const profile: AdaptyProfile = await adapty.restorePurchases();
// Restore successful, profile updated
} catch (error) {
// Handle the error
}
}
```
## Próximos pasos \{#next-steps\}
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](react-native-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](react-native-use-fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN sea inaccesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeoutMs** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
| ¡No pongas los IDs de productos en el código! Dado que los paywalls se configuran de forma remota, los productos disponibles, el número de productos y las ofertas especiales (como períodos de prueba gratuitos) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, tu app debería mostrar esos 2 productos. Sin embargo, si más adelante obtienes 3 productos, tu app debería mostrar los 3 sin necesidad de cambios en el código. Lo único que debes incluir en el código es el ID del placement. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) con: una lista de IDs de productos, el identificador del paywall, Remote Config y varias otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tienes el paywall, puedes consultar el array de productos que le corresponde: ```typescript showLineNumbers try { // ...paywall const products = await adapty.getPaywallProducts(paywall); // la lista de productos solicitada } catch (error) { // gestionar el error } ``` Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | Lista de objetos [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) con: identificador del producto, nombre del producto, precio, moneda, duración de la suscripción y varias otras propiedades. | Al implementar tu propio diseño de paywall, probablemente necesitarás acceder a estas propiedades del objeto [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct). A continuación se muestran las propiedades más utilizadas, pero consulta el documento enlazado para obtener detalles completos sobre todas las propiedades disponibles. | Propiedad | Descripción | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Título** | Para mostrar el título del producto, usa `product.localizedTitle`. Ten en cuenta que la localización se basa en el país de la store seleccionado por el usuario, no en el idioma del dispositivo. | | **Precio** | Para mostrar una versión localizada del precio, usa `product.price?.localizedString`. Esta localización se basa en la configuración regional del dispositivo. También puedes acceder al precio como número usando `product.price?.amount`. El valor se proporcionará en la moneda local. Para obtener el símbolo de moneda asociado, usa `product.price?.currencySymbol`. | | **Período de suscripción** | Para mostrar el período (p. ej. semana, mes, año, etc.), usa `product.subscription?.localizedSubscriptionPeriod`. Esta localización se basa en la configuración regional del dispositivo. Para obtener el período de suscripción de forma programática, usa `product.subscription?.subscriptionPeriod`. Desde ahí puedes acceder a la propiedad `unit` para obtener la duración (es decir, 'day', 'week', 'month', 'year' o 'unknown'). El valor `numberOfUnits` te dará el número de unidades del período. Por ejemplo, para una suscripción trimestral, verías `'month'` en la propiedad unit y `3` en la propiedad numberOfUnits. | | **Oferta introductoria** | Para mostrar una insignia u otro indicador de que una suscripción contiene una oferta introductoria, consulta la propiedad `product.subscription?.offer?.phases`. Esta es una lista que puede contener hasta dos fases de descuento: la fase de prueba gratuita y la fase de precio introductorio. Dentro de cada objeto de fase se encuentran las siguientes propiedades útiles:opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](react-native-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de error. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, puede que los usuarios no obtengan los datos más recientes, pero experimentarán tiempos de carga más rápidos, sin importar la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra al desinstalarla o mediante una limpieza manual.
| --- # File: present-remote-config-paywalls-react-native --- --- title: "Renderizar paywall con Remote Config en React Native SDK" description: "Descubre cómo presentar paywalls con Remote Config en Adapty React Native SDK para personalizar la experiencia del usuario." --- Si has personalizado un paywall usando Remote Config, tendrás que implementar el renderizado en el código de tu app para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú decides qué incluir y cómo se ve tu paywall. Proporcionamos un método para obtener la configuración remota, dándote autonomía para mostrar tu paywall personalizado configurado mediante Remote Config. ## Obtener el Remote Config del paywall y mostrarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores que necesites. ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: "YOUR_PLACEMENT_ID" }); const headerText = paywall.remoteConfig?.data?.["header_text"]; } catch (error) { // handle the error } ``` En este punto, una vez que hayas recibido todos los valores necesarios, es momento de renderizarlos y ensamblarlos en una página visualmente atractiva. Asegúrate de que el diseño se adapte a distintas pantallas y orientaciones de móvil, ofreciendo una experiencia fluida y cómoda en diferentes dispositivos. :::warning Asegúrate de [registrar el evento de visualización del paywall](present-remote-config-paywalls-react-native#track-paywall-view-events) como se describe a continuación, para que Adapty Analytics pueda recopilar información para los embudos y las pruebas A/B. ::: Una vez que hayas terminado de mostrar el paywall, continúa configurando el flujo de compra. Cuando el usuario realice una compra, simplemente llama a `.makePurchase()` con el producto de tu paywall. Para más detalles sobre el método `.makePurchase()`, consulta [Realizar compras](react-native-making-purchases). Recomendamos [crear un paywall de respaldo llamado fallback paywall](react-native-use-fallback-paywalls). Este respaldo se mostrará al usuario cuando no haya conexión a internet ni caché disponible, garantizando una experiencia fluida incluso en esas situaciones. ## Registrar eventos de visualización del paywall \{#track-paywall-view-events\} Adapty te ayuda a medir el rendimiento de tus paywalls. Aunque los datos de compras se recopilan automáticamente, registrar las visualizaciones del paywall requiere tu intervención, porque solo tú sabes cuándo un usuario ve un paywall. Para registrar un evento de visualización del paywall, simplemente llama a `.logShowPaywall(paywall)`, y quedará reflejado en las métricas de tu paywall en embudos y pruebas A/B. :::important No es necesario llamar a `.logShowPaywall(paywall)` si estás mostrando paywalls creados con el [Paywall Builder](adapty-paywall-builder). ::: ```typescript showLineNumbers await adapty.logShowPaywall(paywall); ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :------- |:--------------------------------------------------------------------------------------------| | **paywall** | obligatorio | Un objeto [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall). | --- # File: react-native-making-purchases --- --- title: "Realizar compras in-app en React Native SDK" description: "Guía sobre cómo gestionar compras in-app y suscripciones usando Adapty." --- Mostrar paywalls en tu app móvil es un paso esencial para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, con solo mostrar esos paywalls es suficiente para gestionar las compras únicamente si usas el [Paywall Builder](adapty-paywall-builder) para personalizar tus paywalls. Si no usas el Paywall Builder, debes utilizar un método independiente llamado `.makePurchase()` para completar una compra y desbloquear el contenido deseado. Este método es la puerta de entrada para que los usuarios interactúen con los paywalls y realicen sus transacciones. Si tu paywall tiene una oferta promocional activa para el producto que un usuario intenta comprar, Adapty la aplicará automáticamente en el momento de la compra. :::warning Ten en cuenta que la oferta introductoria solo se aplicará automáticamente si usas los paywalls configurados con el Paywall Builder. En otros casos, deberás [verificar la elegibilidad del usuario para una oferta introductoria en iOS](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios). Saltarte este paso puede hacer que tu app sea rechazada durante la revisión. Además, podría suponer cobrar el precio completo a usuarios que tienen derecho a una oferta introductoria. ::: Asegúrate de haber [realizado la configuración inicial](quickstart) sin saltarte ningún paso. Sin ella, no podemos validar las compras. ## Realizar una compra \{#make-purchase\} :::note **¿Usas el [Paywall Builder](adapty-paywall-builder)?** Las compras se procesan automáticamente: puedes saltarte este paso. **¿Buscas una guía paso a paso?** Consulta la [guía de inicio rápido](react-native-implement-paywalls-manually) para instrucciones de implementación completas con todo el contexto. ::: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :-------- |:-------------------------------------------------------------------------------------------------------------------------------| | **Product** | requerido | Un objeto [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) obtenido del paywall. | Parámetros de la respuesta: | Parámetro | Descripción | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |Si la solicitud fue exitosa, la respuesta contiene este objeto. Un objeto [AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile) proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas de un usuario dentro de la app.
Comprueba el estado del nivel de acceso para verificar si el usuario tiene el acceso necesario a la app.
| :::warning **Nota:** si todavía usas la versión de StoreKit de Apple inferior a v2.0 y la versión del SDK de Adapty inferior a v.2.9.0, debes proporcionar el [secreto compartido de App Store de Apple](app-store-connection-configuration#step-5-enter-app-store-shared-secret) en su lugar. Apple ha declarado este método como obsoleto. ::: ## Cambiar la suscripción al realizar una compra \{#change-subscription-when-making-a-purchase\} Cuando un usuario elige una nueva suscripción en lugar de renovar la actual, el funcionamiento depende del store: - En App Store, la suscripción se actualiza automáticamente dentro del grupo de suscripciones. Si un usuario compra una suscripción de un grupo mientras ya tiene una de otro, ambas suscripciones estarán activas al mismo tiempo. - En Google Play, la suscripción no se actualiza automáticamente. Tendrás que gestionar el cambio en el código de tu app móvil como se describe a continuación. Para reemplazar la suscripción por otra en Android, llama al método `.makePurchase()` con el parámetro adicional: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product, params); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` Parámetro adicional de la solicitud: | Parámetro | Presencia | Descripción | | :--------- | :-------- | :----------------------------------------------------------- | | **params** | requerido | un objeto de tipo [`MakePurchaseParamsInput`](https://react-native.adapty.io/types/makepurchaseparamsinput). | :::info **Versión 3.8.2+**: La estructura `MakePurchaseParamsInput` ha sido actualizada. `oldSubVendorProductId` y `prorationMode` ahora están anidados bajo `subscriptionUpdateParams`, e `isOfferPersonalized` se ha movido al nivel superior. Ejemplo: ```javascript makePurchase(product, { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } }); ``` ::: Puedes leer más sobre suscripciones y modos de reemplazo en la documentación de Google para desarrolladores: - [Acerca de los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Recomendaciones de Google para los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Modo de reemplazo [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Nota: este método solo está disponible para actualizaciones de suscripción. No se admiten degradaciones. - Modo de reemplazo [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Nota: el cambio real de suscripción solo ocurrirá cuando finalice el período de facturación de la suscripción actual. ## Canjear códigos de oferta en iOS \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';Un objeto [`AdaptyProfile`](https://react-native.adapty.io/interfaces/adaptyprofile). Este modelo contiene información sobre niveles de acceso, suscripciones y compras únicas.
Comprueba el **estado del nivel de acceso** para determinar si el usuario tiene acceso a la app.
| :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: --- # File: implement-observer-mode-react-native --- --- title: "Implementar el modo Observer en React Native SDK" description: "Implementa el modo Observer en Adapty para rastrear eventos de suscripción de usuarios en React Native SDK." --- Si ya tienes tu propia infraestructura de compras y no estás listo para migrar completamente a Adapty, puedes explorar el [modo Observer](observer-vs-full-mode). En su forma básica, el modo Observer ofrece analíticas avanzadas e integración fluida con sistemas de atribución y analíticas. Si esto cubre tus necesidades, solo tienes que: 1. Activarlo al configurar el SDK de Adapty estableciendo el parámetro `observerMode` en `true`. Sigue las instrucciones de configuración para [React Native](sdk-installation-reactnative). 2. [Reportar transacciones](report-transactions-observer-mode-react-native) desde tu infraestructura de compras existente a Adapty. ### Configuración del modo Observer \{#observer-mode-setup\} Activa el modo Observer si gestionas las compras y el estado de la suscripción tú mismo y usas Adapty solo para enviar eventos de suscripción y analíticas. :::important Cuando se ejecuta en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlas tú mismo. ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { observerMode: true, // Enable observer mode }); ``` Parámetros: | Parámetro | Descripción | | --------------------------- | ------------------------------------------------------------ | | observerMode | Un valor booleano que controla el [modo Observer](observer-vs-full-mode). El valor por defecto es `false`. | ## Usar los paywalls de Adapty en el modo Observer \{#using-adapty-paywalls-in-observer-mode\} Si también quieres usar los paywalls y las funciones de pruebas A/B de Adapty, puedes hacerlo, pero requiere una configuración adicional en el modo Observer. Esto es lo que necesitas hacer además de los pasos anteriores: 1. Muestra los paywalls de la forma habitual para los [paywalls de Remote Config](present-remote-config-paywalls-react-native). 3. [Asocia los paywalls](report-transactions-observer-mode-react-native) con las transacciones de compra. --- # File: report-transactions-observer-mode-react-native --- --- title: "Reportar transacciones en Observer Mode en el SDK de React Native" description: "Reporta transacciones de compra en el Observer Mode de Adapty para obtener información sobre usuarios y seguimiento de ingresos en el SDK de React Native." ---Para iOS, StoreKit 1: un objeto [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction).
Para iOS, StoreKit 2: objeto [Transaction](https://developer.apple.com/documentation/storekit/transaction).
Para Android: identificador de cadena (purchase.getOrderId de la compra, donde la compra es una instancia de la clase [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) de la biblioteca de facturación.
| | variationId | obligatorio | El identificador de cadena de la variante. Puedes obtenerlo usando la propiedad `variationId` del objeto [AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall). |phoneNumber
firstName
lastName
| String | | gender | Enum, los valores permitidos son: `female`, `male`, `other` | | birthday | Date | ### Atributos de usuario personalizados \{#custom-user-attributes\} Puedes definir tus propios atributos personalizados. Estos suelen estar relacionados con el uso de tu app. Por ejemplo, en aplicaciones de fitness pueden ser el número de ejercicios por semana; en apps de aprendizaje de idiomas, el nivel de conocimiento del usuario, etc. Puedes usarlos en segmentos para crear paywalls y ofertas dirigidas, y también en analíticas para determinar qué métricas de producto influyen más en los ingresos. ```typescript showLineNumbers try { await adapty.updateProfile({ codableCustomAttributes: { key_1: 'value_1', key_2: 2, }, }); } catch (error) { // handle `AdaptyError` } ``` Para eliminar una clave existente, usa el método `.withRemoved(customAttributeForKey:)`: ```typescript showLineNumbers try { // to remove a key, pass null as its value await adapty.updateProfile({ codableCustomAttributes: { key_1: null, key_2: null, }, }); } catch (error) { // handle `AdaptyError` } ``` A veces necesitas saber qué atributos personalizados ya están configurados. Para ello, usa el campo `customAttributes` del objeto `AdaptyProfile`. :::warning Ten en cuenta que el valor de `customAttributes` puede estar desactualizado, ya que los atributos de usuario pueden enviarse desde distintos dispositivos en cualquier momento, por lo que los atributos en el servidor podrían haber cambiado después de la última sincronización. ::: ### Límites \{#limits\} - Hasta 30 atributos personalizados por usuario - Los nombres de clave pueden tener hasta 30 caracteres. El nombre de la clave puede incluir caracteres alfanuméricos y cualquiera de los siguientes: `_` `-` `.` - El valor puede ser una cadena de texto o un número flotante con un máximo de 50 caracteres. --- # File: react-native-listen-subscription-changes --- --- title: "Comprobar el estado de suscripción en el SDK de React Native" description: "Haz seguimiento y gestión del estado de suscripción del usuario en Adapty para mejorar la retención de clientes en tu app de React Native." --- Con Adapty, hacer seguimiento del estado de suscripción es muy sencillo. No tienes que insertar manualmente los IDs de producto en tu código. En su lugar, puedes comprobar fácilmente el estado de suscripción de un usuario verificando si tiene un [nivel de acceso](access-level) activo.Un objeto [AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile). Por lo general, solo necesitas comprobar el estado del nivel de acceso del perfil para determinar si el usuario tiene acceso premium a la app.
El método `.getProfile` devuelve el resultado más actualizado, ya que siempre intenta consultar la API. Si por algún motivo (por ejemplo, sin conexión a internet) el SDK de Adapty no puede recuperar información del servidor, se devolverán los datos de la caché. También es importante tener en cuenta que el SDK de Adapty actualiza la caché de `AdaptyProfile` de forma periódica para mantener esta información lo más actualizada posible.
| El método `.getProfile()` te proporciona el perfil de usuario desde el que puedes obtener el estado del nivel de acceso. Puedes tener múltiples niveles de acceso por app. Por ejemplo, si tienes una app de noticias y vendes suscripciones a diferentes temáticas de forma independiente, puedes crear niveles de acceso "sports" y "science". Pero la mayoría de las veces solo necesitarás un nivel de acceso; en ese caso, puedes usar simplemente el nivel de acceso predeterminado "premium". Aquí tienes un ejemplo para comprobar el nivel de acceso "premium" predeterminado: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); const isActive = profile.accessLevels?.["premium"]?.isActive; if (isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` ### Escuchar actualizaciones del estado de suscripción \{#listening-for-subscription-status-updates\} Cada vez que cambia la suscripción del usuario, Adapty lanza un evento. Para recibir mensajes de Adapty, necesitas realizar algunas configuraciones adicionales: ```typescript showLineNumbers // Create an "onLatestProfileLoad" event listener adapty.addEventListener('onLatestProfileLoad', profile => { // handle any changes to subscription state }); ``` Adapty también lanza un evento al iniciar la aplicación. En ese caso, se pasará el estado de suscripción almacenado en caché. ### Caché del estado de suscripción \{#subscription-status-cache\} La caché implementada en el SDK de Adapty almacena el estado de suscripción del perfil. Esto significa que, aunque el servidor no esté disponible, se puede acceder a los datos en caché para obtener información sobre el estado de suscripción del perfil. No obstante, hay que tener en cuenta que no es posible solicitar datos directamente desde la caché. El SDK consulta el servidor periódicamente cada minuto para comprobar si hay actualizaciones o cambios relacionados con el perfil. Si hay alguna modificación, como nuevas transacciones u otras actualizaciones, se enviarán a los datos en caché para mantenerlos sincronizados con el servidor. --- # File: react-native-deal-with-att --- --- title: "Gestionar ATT en el SDK de React Native" description: "Empieza con Adapty en React Native para simplificar la configuración y gestión de suscripciones." --- Si tu aplicación utiliza el framework AppTrackingTransparency y muestra al usuario una solicitud de autorización de seguimiento de la app, debes enviar el [estado de autorización](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) a Adapty. ```typescript showLineNumbers try { await adapty.updateProfile({ // you can also pass a string value (validated via tsc) if you prefer appTrackingTransparencyStatus: AppTrackingTransparencyStatus.Authorized, }); } catch (error) { // handle `AdaptyError` } ``` :::warning Te recomendamos encarecidamente que envíes este valor lo antes posible cuando cambie; solo así los datos se enviarán a tiempo a las integraciones que hayas configurado. ::: --- # File: kids-mode-react-native --- --- title: "Modo Niños en React Native SDK" description: "Activa fácilmente el Modo Niños para cumplir con las políticas de Apple y Google. Sin recopilación de IDFA, GAID ni datos publicitarios en el SDK de React Native." --- Si tu aplicación React Native está dirigida a niños, debes cumplir las políticas de [Apple](https://developer.apple.com/kids/) y [Google](https://support.google.com/googleplay/android-developer/answer/9893335). Si usas el SDK de Adapty, unos pocos pasos sencillos te permitirán configurarlo para cumplir con estas políticas y superar las revisiones de la tienda. ## ¿Qué se requiere? \{#whats-required\} Necesitas configurar el SDK de Adapty para deshabilitar la recopilación de: - [IDFA (Identifier for Advertisers)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [Dirección IP](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Además, te recomendamos utilizar el ID de usuario del cliente con cuidado. Un ID de usuario con el formato `opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizations and locale codes](localizations-and-locale-codes) para más información sobre los códigos de localización y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexión inestable a internet, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN sea inaccesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeoutMs** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo de espera, se devolverán los datos en caché o el fallback local.
Ten en cuenta que, en casos excepcionales, este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Un objeto [`AdaptyOnboarding`](https://react-native.adapty.io/interfaces/adaptyonboarding) con: el identificador y la configuración del onboarding, Remote Config y otras propiedades. | ## Acelera la obtención del onboarding con el onboarding de audiencia predeterminada \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Normalmente, los onboardings se obtienen casi al instante, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, en casos donde tienes numerosas audiencias y onboardings, y tus usuarios tienen una conexión a internet débil, obtener un onboarding puede tardar más de lo deseado. En esas situaciones, puede que quieras mostrar un onboarding predeterminado para garantizar una experiencia de usuario fluida en lugar de no mostrar ningún onboarding. Para abordar esto, puedes usar el método `getOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, como se detalla en la sección [Obtener el onboarding](#fetch-onboarding) anterior. :::warning Considera usar `getOnboarding` en lugar de `getOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: Puede generar problemas al dar soporte a varias versiones de la app, lo que requiere diseños retrocompatibles o aceptar que las versiones más antiguas podrían mostrarse incorrectamente. - **Sin personalización**: Solo muestra contenido para la audiencia "All Users", eliminando la segmentación basada en país, atribución o atributos personalizados. Si una obtención más rápida compensa estos inconvenientes para tu caso de uso, utiliza `getOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `getOnboarding` como se describe [arriba](#fetch-onboarding). ::: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const onboarding = await adapty.getOnboardingForDefaultAudience(placementId, locale); // the requested onboarding } catch (error) { // handle the error } ``` Parámetros: | Parámetro | Presencia | Descripción | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | requerido | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma y la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizations and locale codes](localizations-and-locale-codes) para más información sobre los códigos de localización y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexión inestable a internet, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo inestable que sea su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante una limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché de actualización regular descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN sea inaccesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: react-native-present-onboardings --- --- title: "Presentar onboardings en React Native SDK" description: "Descubre cómo presentar onboardings en React Native para aumentar las conversiones y los ingresos." --- Si has personalizado un onboarding con el builder, no tienes que preocuparte por renderizarlo en el código de tu app para mostrárselo al usuario. Ese onboarding ya contiene tanto lo que debe mostrarse como la forma en que debe hacerlo. Antes de empezar, asegúrate de que: 1. Tienes instalado [Adapty React Native SDK](sdk-installation-reactnative) 3.8.0 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). El SDK de Adapty para React Native ofrece dos formas de presentar onboardings: - **Componente React**: Un componente embebido que te permite integrarlo en la arquitectura y el sistema de navegación de tu app. - **Presentación modal** ## Componente React \{#react-component\} Para insertar un onboarding dentro de tu árbol de componentes existente, usa el componente `AdaptyOnboardingView` directamente en la jerarquía de componentes de React Native. El componente embebido te permite integrarlo en la arquitectura y el sistema de navegación de tu app. :::note En Android, recomendamos una configuración adicional para `AdaptyOnboardingView` con el fin de evitar un artefacto visual en el renderizado. Consulta [La UI del sistema se superpone al contenido del onboarding en Android](#system-ui-overlaps-onboarding-content-on-android). :::
Después, puedes usar ese ID en tu código y manejarlo como una acción personalizada. Por ejemplo, si un usuario pulsa un botón personalizado como **Login** o **Allow notifications**, el manejador de eventos se disparará con el parámetro `actionId` que coincide con el **Action ID** del builder. Puedes crear tus propios IDs, como "allowNotifications".
:::important
Ten en cuenta que debes gestionar qué ocurre cuando el usuario cierra el onboarding. Por ejemplo, necesitas dejar de mostrar el propio onboarding.
:::
2. Haz clic en el nombre del grupo de suscripción. Verás tus productos listados en la sección **Subscriptions**.
3. Asegúrate de que el producto que estás probando esté marcado como **Ready to Submit**.
4. Compara el ID de producto de la tabla con el que aparece en la pestaña [**Products**](https://app.adapty.io/products) del Adapty Dashboard. Si los IDs no coinciden, copia el ID del producto de la tabla y [crea un producto](create-product) con ese ID en el Adapty Dashboard.
## Paso 3. Verifica la disponibilidad del producto \{#step-4-check-product-availability\}
1. Vuelve a **App Store Connect** y abre la misma sección **Subscriptions**.
2. Haz clic en el nombre del grupo de suscripción para ver tus productos.
3. Selecciona el producto que estás probando.
4. Desplázate hasta la sección **Availability** y comprueba que todos los países y regiones necesarios aparecen en la lista.
## Paso 4. Verifica los precios del producto \{#step-5-check-product-prices\}
1. De nuevo, ve a la sección **Monetization** → **Subscriptions** en **App Store Connect**.
2. Haz clic en el nombre del grupo de suscripción.
3. Selecciona el producto que estás probando.
4. Desplázate hacia abajo hasta **Subscription Pricing** y despliega la sección **Current Pricing for New Subscribers**.
5. Asegúrate de que todos los precios necesarios aparecen en la lista.
## Paso 5. Verifica que el estado de pago de la app, la cuenta bancaria y los formularios fiscales estén activos \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. En la página de inicio de [**App Store Connect**](https://appstoreconnect.apple.com/), haz clic en **Business**.
2. Selecciona el nombre de tu empresa.
3. Desplázate hacia abajo y comprueba que tu **Paid Apps Agreement**, **Bank Account** y **Tax forms** muestran el estado **Active**.
Siguiendo estos pasos deberías poder resolver la advertencia `InvalidProductIdentifiers` y publicar tus productos en el store.
## Paso 6. Recrea el producto si está bloqueado \{#step-6-recreate-the-product-if-its-stuck\}
Los pasos 1 a 5 pueden superarse correctamente —estado `Approved`, Bundle ID coincidente, API key válida— y aun así el SDK devuelve `1000 noProductIDsFound`. En ese caso, es posible que el producto esté bloqueado en el registro de Apple. El registro de productos de Apple puede entrar ocasionalmente en un estado en el que un producto existe en la interfaz de App Store Connect pero no está expuesto en la ruta de búsqueda de StoreKit.
Elimina el producto en App Store Connect y vuelve a crearlo con el mismo ID de producto. Espera hasta 24 horas tras la recreación para que los cambios se propaguen.
---
# File: cantMakePayments-react-native
---
---
title: "Solución para el error Code-1003 cantMakePayment en el SDK de React Native"
description: "Resuelve el error de pago al gestionar suscripciones en Adapty."
---
El error 1003, `cantMakePayments`, indica que no es posible realizar compras in-app en este dispositivo.
Si encuentras el error `cantMakePayments`, normalmente se debe a una de estas razones:
- Restricciones del dispositivo: El error no está relacionado con Adapty. Consulta las soluciones más abajo.
- Configuración del modo Observer: El método `makePurchase` y el modo Observer no pueden usarse al mismo tiempo. Consulta la sección más abajo.
## Problema: Restricciones del dispositivo \{#issue-device-restrictions\}
| Problema | Solución |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Restricciones de Screen Time | Desactiva las restricciones de compras in-app en [Screen Time](https://support.apple.com/en-us/102470) |
| Cuenta suspendida | Contacta con el soporte de Apple para resolver problemas con la cuenta |
| Restricciones regionales | Usa una cuenta de App Store de una región compatible |
## Problema: Usar el modo Observer y makePurchase a la vez \{#issue-using-both-observer-mode-and-makepurchase\}
Si usas `makePurchases` para gestionar las compras, no necesitas el modo Observer. El [modo Observer](observer-vs-full-mode) solo es necesario si implementas la lógica de compra tú mismo.
Por lo tanto, si usas `makePurchase`, puedes eliminar sin problema la activación del modo Observer del código de inicialización del SDK.
---
# File: migration-react-native-314
---
---
title: "Migrar el SDK de Adapty React Native a la versión 3.14"
description: "Migra al SDK de Adapty React Native v3.14 para mejorar el rendimiento y acceder a nuevas funciones de monetización."
---
El SDK de Adapty React Native 3.14.0 es una versión mayor que introduce mejoras que requieren pasos de migración de tu parte:
- El método `registerEventHandlers` ha sido reemplazado por el método `setEventHandlers`.
- En `AdaptyOnboardingView`, los manejadores de eventos ahora se pasan como props individuales en lugar de un objeto `eventHandlers`
- Se ha introducido un nuevo estilo de importación simplificado para los componentes de UI
- El método `logShowOnboarding` ha sido eliminado
- La versión mínima de React Native se ha actualizado a 0.73.0
- El estilo de presentación predeterminado de iOS para paywalls y onboardings ha cambiado de hoja de página a pantalla completa
## Reemplaza `registerEventHandlers` por `setEventHandlers` \{#replace-registereventhandlers-with-seteventhandlers\}
El método `registerEventHandlers` utilizado para trabajar con el Paywall Builder y el Onboarding Builder de Adapty ha sido reemplazado por el método `setEventHandlers`.
Si usas el Paywall Builder y/o el Onboarding Builder de Adapty, busca `registerEventHandlers` en el código de tu app y reemplázalo por `setEventHandlers`.
Este cambio se ha introducido para que el comportamiento del método sea más claro: los manejadores ahora funcionan de uno en uno porque cada uno devuelve `true`/`false`, y tener varios manejadores para un mismo evento hacía que el comportamiento resultante fuera confuso.
Ten en cuenta que al usar componentes de React como `AdaptyOnboardingView` o `AdaptyPaywallView`, no es necesario devolver `true`/`false` desde los manejadores de eventos, ya que controlas la visibilidad del componente mediante tu propia gestión de estado. Los valores de retorno solo son necesarios para la presentación de pantallas modales donde el SDK gestiona el ciclo de vida de la vista.
:::important
Llamar a `setEventHandlers` varias veces sobreescribirá los manejadores que proporciones, reemplazando tanto los predeterminados como los establecidos previamente para esos eventos específicos.
:::
```diff showLineNumbers
- const unsubscribe = view.registerEventHandlers({
- // your event handlers
- })
const unsubscribe = view.setEventHandlers({
// your event handlers
})
```
## Actualiza las rutas de importación de los componentes de UI \{#update-import-paths-for-ui-components\}
El SDK de Adapty 3.14.0 introduce un estilo de importación simplificado para los componentes de UI. En lugar de importar desde `react-native-adapty/dist/ui`, ahora puedes importar directamente desde `react-native-adapty`.
El nuevo estilo de importación es más coherente con las prácticas estándar de React Native y hace que las declaraciones de importación sean más limpias. Si usas componentes de UI como `AdaptyPaywallView` o `AdaptyOnboardingView`, actualiza tus importaciones como se muestra a continuación:
```diff showLineNumbers
- import { AdaptyPaywallView } from 'react-native-adapty/dist/ui';
+ import { AdaptyPaywallView } from 'react-native-adapty';
- import { AdaptyOnboardingView } from 'react-native-adapty/dist/ui';
+ import { AdaptyOnboardingView } from 'react-native-adapty';
- import { createPaywallView } from 'react-native-adapty/dist/ui';
+ import { createPaywallView } from 'react-native-adapty';
- import { createOnboardingView } from 'react-native-adapty/dist/ui';
+ import { createOnboardingView } from 'react-native-adapty';
```
:::note
Por compatibilidad con versiones anteriores, el estilo de importación antiguo (`react-native-adapty/dist/ui`) sigue siendo compatible. Sin embargo, recomendamos usar el nuevo estilo de importación para mayor consistencia y claridad.
:::
## Actualiza los manejadores de eventos del onboarding en el componente de React \{#update-onboarding-event-handlers-in-the-react-component\}
Los manejadores de eventos para los onboardings se han movido fuera del objeto `eventHandlers` en `AdaptyOnboardingView`. Si estás mostrando onboardings con `AdaptyOnboardingView`, actualiza la estructura de manejo de eventos.
:::important
Ten en cuenta la forma en que recomendamos implementar los manejadores de eventos. Para evitar recrear objetos en cada renderizado, usa `useCallback` para las funciones que manejan eventos.
:::
```diff showLineNumbers
import React, { useCallback } from 'react';
- import { AdaptyOnboardingView } from 'react-native-adapty/dist/ui';
+ import { AdaptyOnboardingView } from 'react-native-adapty';
+ import type { OnboardingEventHandlers } from 'react-native-adapty';
+
+ function MyOnboarding({ onboarding }) {
+ const onAnalytics = useCallback```diff showLineNumbers - subscriptionDetails?: AdaptySubscriptionDetails; + subscription?: AdaptySubscriptionDetails; ``` 2. [AdaptySubscriptionDetails](https://react-native.adapty.io/interfaces/adaptysubscriptiondetails): - Se eliminó `promotionalOffer`. Ahora la oferta promocional se entrega dentro de la propiedad `offer` solo si está disponible. En ese caso, `offer?.identifier?.type` será `'promotional'`. - Se eliminó `introductoryOfferEligibility` (las ofertas solo se devuelven si el usuario es elegible). - Se eliminó `offerId`. El ID de la oferta ahora se almacena en `AdaptySubscriptionOffer.identifier`. - `offerTags` se movió a `AdaptySubscriptionOffer.android`.
```diff showLineNumbers - introductoryOffers?: AdaptyDiscountPhase[]; + offer?: AdaptySubscriptionOffer; ios?: { - promotionalOffer?: AdaptyDiscountPhase; subscriptionGroupIdentifier?: string; }; android?: { - offerId?: string; basePlanId: string; - introductoryOfferEligibility: OfferEligibility; - offerTags?: string[]; renewalType?: 'prepaid' | 'autorenewable'; }; } ``` 3. [AdaptyDiscountPhase](https://react-native.adapty.io/interfaces/adaptydiscountphase): - El campo `identifier` se eliminó del modelo `AdaptyDiscountPhase`. El identificador de la oferta ahora se almacena en `AdaptySubscriptionOffer.identifier`.
```diff showLineNumbers - ios?: { - readonly identifier?: string; - }; ``` ### Modelos eliminados \{#remove-models\} 1. `AttributionSource`: - Ahora se usa un string en los lugares donde antes se usaba `AttributionSource`. 2. `OfferEligibility`: - Este modelo se ha eliminado porque ya no es necesario. Ahora, una oferta solo se devuelve si el usuario es elegible. ## Elimina el método `getProductsIntroductoryOfferEligibility` \{#remove-getproductsintroductoryoffereligibility-method\} Antes del SDK de Adapty 3.3.1, los objetos de producto siempre incluían las ofertas, incluso si el usuario no era elegible. Esto requería verificar la elegibilidad manualmente antes de usar la oferta. A partir de la versión 3.3.1, el objeto de producto incluye ofertas solo si el usuario es elegible. Esto simplifica el proceso, ya que puedes asumir que el usuario es elegible si hay una oferta presente. ## Actualiza el proceso de compra \{#update-making-purchase\} En versiones anteriores, las compras canceladas y pendientes se trataban como errores y devolvían los códigos `2: 'paymentCancelled'` y `25: 'pendingPurchase'`, respectivamente. A partir de la versión 3.3.1, las compras canceladas y pendientes se consideran resultados exitosos y deben manejarse en consecuencia: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` ## Actualiza la presentación de paywalls del Paywall Builder \{#update-paywall-builder-paywall-presentation\} Para ver ejemplos actualizados, consulta la documentación [Presentar paywalls nuevos del Paywall Builder en React Native](react-native-present-paywalls). ```diff showLineNumbers - import { createPaywallView } from '@adapty/react-native-ui'; + import { createPaywallView } from 'react-native-adapty/dist/ui'; const view = await createPaywallView(paywall); view.registerEventHandlers(); // handle close press, etc try { await view.present(); } catch (error) { // handle the error } ``` ## Actualiza la implementación del temporizador definido por el desarrollador \{#update-developer-defined-timer-implementation\} Renombra el parámetro `timerInfo` a `customTimers`: ```diff showLineNumbers - let timerInfo = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } + let customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } //and then you can pass it to createPaywallView as follows: - view = await createPaywallView(paywall, { timerInfo }) + view = await createPaywallView(paywall, { customTimers }) ``` ## Modifica los eventos de compra del Paywall Builder \{#modify-paywall-builder-purchase-events\} Antes: - Las compras canceladas activaban el callback `onPurchaseCancelled`. - Las compras pendientes devolvían el código de error `25: 'pendingPurchase'`. Ahora: - Ambas se manejan mediante el callback `onPurchaseCompleted`. #### Pasos para migrar: \{#steps-to-migrate\} 1. Elimina el callback `onPurchaseCancelled`. 2. Elimina el manejo del código de error `25: 'pendingPurchase'`. 3. Actualiza el callback `onPurchaseCompleted`: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ // ... other optional callbacks onPurchaseCompleted(purchaseResult, product) { switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; // highlight-start case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; // highlight-end } // highlight-start return purchaseResult.type !== 'user_cancelled'; // highlight-end }, }); ``` ## Modifica los eventos de acción personalizada del Paywall Builder \{#modify-paywall-builder-custom-action-events\} Callbacks eliminados: - `onAction` - `onCustomEvent` Callback añadido: - Nuevo callback `onCustomAction(actionId)`. Úsalo para acciones personalizadas. ## Modifica el callback `onProductSelected` \{#modify-onproductselected-callback\} Antes, `onProductSelected` requería el objeto `product`. Ahora requiere `productId` como string. ## Elimina los parámetros de integración de terceros del método `updateProfile` \{#remove-third-party-integration-parameters-from-updateprofile-method\} Los identificadores de integración de terceros ahora se configuran con el método `setIntegrationIdentifier`. El método `updateProfile` ya no los acepta. ## Actualiza la configuración del SDK de integraciones de terceros \{#update-third-party-integration-sdk-configuration\} Para garantizar que las integraciones funcionen correctamente con el SDK de Adapty React Native 3.3.1 y versiones posteriores, actualiza las configuraciones de tu SDK para las siguientes integraciones según se describe en las secciones a continuación. Además, si usabas `AttributionSource` para obtener el identificador de atribución, cambia tu código para proporcionar el identificador requerido como string. ### Adjust \{#adjust\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Adjust](adjust#connect-your-app-to-adjust). ```diff showLineNumbers import { Adjust, AdjustConfig } from "react-native-adjust"; import { adapty } from "react-native-adapty"; var adjustConfig = new AdjustConfig(appToken, environment); // Before submiting Adjust config... adjustConfig.setAttributionCallbackListener(attribution => { // Make sure Adapty SDK is activated at this point // You may want to lock this thread awaiting of `activate` adapty.updateAttribution(attribution, "adjust"); }); // ... Adjust.create(adjustConfig); + Adjust.getAdid((adid) => { + if (adid) + adapty.setIntegrationIdentifier("adjust_device_id", adid); + }); ``` ### AirBridge \{#airbridge\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con AirBridge](airbridge#connect-your-app-to-airbridge). ```diff showLineNumbers import Airbridge from 'airbridge-react-native-sdk'; import { adapty } from 'react-native-adapty'; try { const deviceId = await Airbridge.state.deviceUUID(); - await adapty.updateProfile({ - airbridgeDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("airbridge_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` ### Amplitude \{#amplitude\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Amplitude](amplitude#sdk-configuration). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; try { - await adapty.updateProfile({ - amplitudeDeviceId: deviceId, - amplitudeUserId: userId, - }); + await adapty.setIntegrationIdentifier("amplitude_device_id", deviceId); + await adapty.setIntegrationIdentifier("amplitude_user_id", userId); } catch (error) { // handle `AdaptyError` } ``` ### AppMetrica \{#appmetrica\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con AppMetrica](appmetrica#sdk-configuration). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import AppMetrica, { DEVICE_ID_KEY, StartupParams, StartupParamsReason } from '@appmetrica/react-native-analytics'; // ... const startupParamsCallback = async ( params?: StartupParams, reason?: StartupParamsReason ) => { const deviceId = params?.deviceId if (deviceId) { try { - await adapty.updateProfile({ - appmetricaProfileId: 'YOUR_ADAPTY_CUSTOMER_USER_ID', - appmetricaDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("appmetrica_profile_id", 'YOUR_ADAPTY_CUSTOMER_USER_ID'); + await adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId); } catch (error) { // handle `AdaptyError` } } } AppMetrica.requestStartupParams(startupParamsCallback, [DEVICE_ID_KEY]) ``` ### AppsFlyer \{#appsflyer\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con AppsFlyer](appsflyer#connect-your-app-to-appsflyer). ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import appsFlyer from 'react-native-appsflyer'; appsFlyer.onInstallConversionData(installData => { try { - const networkUserId = appsFlyer.getAppsFlyerUID(); - adapty.updateAttribution(installData, AttributionSource.AppsFlyer, networkUserId); + const uid = appsFlyer.getAppsFlyerUID(); + adapty.setIntegrationIdentifier("appsflyer_id", uid); + adapty.updateAttribution(installData, "appsflyer"); } catch (error) { // handle the error } }); // ... appsFlyer.initSdk(/*...*/); ``` ### Branch \{#branch\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Branch](branch#connect-your-app-to-branch). ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import branch from 'react-native-branch'; branch.subscribe({ enComplete: ({ params, }) => { - adapty.updateAttribution(params, AttributionSource.Branch); + adapty.updateAttribution(params, "branch"); }, }); ``` ### Facebook Ads \{#facebook-ads\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Facebook Ads](facebook-ads#connect-your-app-to-facebook-ads). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { AppEventsLogger } from 'react-native-fbsdk-next'; try { const anonymousId = await AppEventsLogger.getAnonymousID(); - await adapty.updateProfile({ - facebookAnonymousId: anonymousId, - }); + await adapty.setIntegrationIdentifier("facebook_anonymous_id", anonymousId); } catch (error) { // handle `AdaptyError` } ``` ### Firebase y Google Analytics \{#firebase-and-google-analytics\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Firebase y Google Analytics](firebase-and-google-analytics). ```diff showLineNumbers import analytics from '@react-native-firebase/analytics'; import { adapty } from 'react-native-adapty'; try { const appInstanceId = await analytics().getAppInstanceId(); - await adapty.updateProfile({ - firebaseAppInstanceId: appInstanceId, - }); + await adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId); } catch (error) { // handle `AdaptyError` } ``` ### Mixpanel \{#mixpanel\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con Mixpanel](mixpanel#sdk-configuration). ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { Mixpanel } from 'mixpanel-react-native'; // ... try { - await adapty.updateProfile({ - mixpanelUserId: mixpanelUserId, - }); + await adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelUserId); } catch (error) { // handle `AdaptyError` } ``` ### OneSignal \{#onesignal\} Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [configuración del SDK para la integración con OneSignal](onesignal#sdk-configuration).
:::important
**Los siguientes pasos dependen de si ya tienes productos en el App Store y/o Google Play:**
:::
5. Haz clic en **Save & Continue** y cambia a la pestaña **App Store** o **Google Play** para rellenar los detalles del producto en la store.
### Diseñar el paywall \{#design-paywall\}
La forma más sencilla de diseñar un paywall es crearlo con el editor visual sin código de Adapty, que no requiere conocimientos de diseño ni de programación. Puedes elegir entre una amplia selección de plantillas diseñadas por profesionales o construir un paywall completamente personalizado para tu app.
:::note
Si no quieres usar el paywall builder, puedes implementar los paywalls manualmente usando [Remote Config](customize-paywall-with-remote-config) con payloads JSON personalizados. Más información sobre
Vamos a diseñar tu primer paywall. Puedes crear paywalls atractivos con facilidad:
1. Abre **Builder & Generator** en la página del paywall.
2. Haz clic en **Build no-code paywall**.
3. Elige una plantilla y confirma tu elección.
4. Añade y personaliza los elementos según necesites.
5. Haz clic en **Save**.
Para más detalles, consulta el artículo completo sobre el [Paywall builder](adapty-paywall-builder#paywall-elements).
## 2. Añadir el paywall a un placement \{#2-add-paywall-to-placement\}
Ahora necesitas crear un
## Pasos siguientes \{#next-steps\}
Tras vincular tu paywall a un placement en Adapty, el siguiente paso es mostrarlo en un dispositivo. Pasemos a [integrar el SDK de Adapty](quickstart-sdk) en tu app.
---
# File: quickstart-sdk
---
---
title: "Integra el SDK de Adapty en el código de tu app"
description: "Integra Adapty con App Store, Google Play, stores personalizadas, Stripe y Paddle."
---
Integra el SDK de Adapty en tu app para:
- Gestionar compras, validación de recibos y suscripciones sin configuración adicional
- Crear y probar paywalls sin actualizar la app
- Obtener análisis detallados de compras sin ninguna configuración: cohortes, LTV, churn y análisis de embudo incluidos
- Mantener el estado de la suscripción del usuario siempre actualizado entre sesiones y dispositivos
- Integrar tu app con servicios de atribución de marketing y análisis con una sola línea de código
## Cómo funciona \{#how-does-it-work\}
Para una implementación básica del SDK de Adapty, solo necesitas ocuparte de tres cosas:
1. Instalar e inicializar el SDK.
2. Delegar el manejo de las compras in-app a Adapty.
3. Monitorear el estado de la suscripción en el perfil. Adapty determina el estado, el tipo y la fecha de vencimiento de la suscripción; el SDK simplemente consume esa información.
El orden y los detalles pueden variar de una app a otra, pero básicamente eso es todo.
## Empezar \{#get-started\}
Elige tu plataforma y comienza:
**iOS**
- **[Inicio rápido del SDK](ios-sdk-overview)**
- **[Apps de ejemplo](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples)**
**Android**
- **[Inicio rápido del SDK](android-sdk-overview)**
- **[App de ejemplo](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app)**
**React Native**
- **[Inicio rápido del SDK](react-native-sdk-overview)**
- **[Apps de ejemplo](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/)**
**Flutter**
- **[Inicio rápido del SDK](flutter-sdk-overview)**
- **[App de ejemplo](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example)**
**Unity**
- **[Inicio rápido del SDK](unity-sdk-overview)**
- **[App de ejemplo](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets)**
**Capacitor**
- **[Inicio rápido del SDK](capacitor-sdk-overview)**
- **[Apps de ejemplo](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples)**
**Kotlin Multiplatform**:
- **[Inicio rápido del SDK](kmp-sdk-overview)**
- **[App de ejemplo](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example)**
## Próximos pasos \{#next-steps\}
Una vez que hayas configurado el SDK de Adapty en el código de la app, puedes pasar a [probar la implementación](quickstart-test).
---
# File: quickstart-test
---
---
title: "Prueba tu integración con Adapty"
description: "Verifica rápidamente tu integración con Adapty probando la activación del SDK, la obtención de paywalls y las compras in-app en App Store, Google Play, Stripe y Paddle."
---
¡Todo listo! Ahora asegúrate de que tu integración funciona como se espera y de que puedes ver tus compras en el Adapty Dashboard.
Realizar una compra de prueba es la mejor forma de verificar que tu integración funciona de extremo a extremo. Empieza con una compra in-app y luego valida los resultados.
## 1. Prueba las compras in-app \{#1-test-in-app-purchases\}
Sigue la guía según tu store o plataforma de pago.
### App Store \{#app-store\}
Te recomendamos usar una cuenta de prueba (Sandbox Apple ID) y realizar las pruebas en un dispositivo real. Para conocer todos los pasos de prueba en detalle, consulta el artículo sobre [pruebas en el Sandbox de App Store](test-purchases-in-sandbox).
:::warning
Realiza las pruebas en un dispositivo real para obtener los resultados más fiables. Opcionalmente puedes usar el simulador, pero no lo recomendamos ya que es menos confiable.
:::
### Google Play Store \{#google-play-store\}
Crea un usuario de prueba y prueba tu app en un dispositivo real. Para conocer todos los pasos de prueba en detalle, consulta el artículo sobre [pruebas en Google Play Store](testing-on-android).
:::note
Google [recomienda](https://support.google.com/googleplay/android-developer/answer/14316361) usar un dispositivo real para las pruebas. Si decides usar un emulador, asegúrate de que tenga Google Play instalado para garantizar que tu app funciona correctamente.
:::
### Stripe \{#stripe\}
Para probar compras en Stripe, necesitas conectar Stripe a Adapty usando la clave API del modo de prueba de Stripe. Las transacciones que realices desde el modo de prueba de Stripe se considerarán Sandbox en Adapty.
Para conocer todos los pasos de conexión, consulta el [artículo de integración con Stripe](stripe#6-test-your-integration).
### Paddle \{#paddle\}
Para probar compras en Paddle, necesitas conectar Paddle a Adapty usando la clave API del entorno de prueba de Paddle. Las transacciones que realices desde el entorno de prueba de Paddle se considerarán Test en Adapty.
Para conocer todos los pasos de conexión, consulta el [artículo de integración con Paddle](paddle#4-test-your-integration).
## 2. Valida las compras de prueba \{#2-validate-test-purchases\}
Después de realizar una compra de prueba, comprueba si aparece la transacción correspondiente en el [**Event Feed**](https://app.adapty.io/event-feed) del Adapty Dashboard. Si la compra no aparece en el **Event Feed**, significa que Adapty no la está registrando.
Más información en la guía detallada sobre [validación de compras de prueba](validate-test-purchases).
## Próximos pasos \{#next-steps\}
¡Felicidades por completar el onboarding de Adapty! Ya estás listo para hacer crecer tus compras in-app.
Prepárate para el lanzamiento en producción:
O puedes continuar con lo siguiente:
- **[Pruebas A/B](ab-tests)**: Experimenta con distintos precios, duraciones de suscripción, períodos de prueba y elementos visuales para identificar las combinaciones más efectivas.
- **[Analíticas](how-adapty-analytics-works)**: Explora métricas de monetización detalladas para entender el comportamiento de los usuarios y optimizar el rendimiento de los ingresos.
- **Integraciones**: Adapty envía [eventos de suscripción](events) a herramientas de analítica y atribución de terceros, como [Amplitude](amplitude), [AppsFlyer](appsflyer), [Adjust](adjust), [Branch](branch), [Mixpanel](mixpanel), [Facebook Ads](facebook-ads), [AppMetrica](appmetrica) y un [Webhook](webhook) personalizado.
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
Viable, pero requiere una cantidad significativa de código y configuración adicionales, más que en el modo completo.
| ✅ | | **Tiempo de implementación** |Para analítica e integraciones: menos de una hora
Con pruebas A/B: hasta una semana con pruebas exhaustivas
| Varias horas | ## Cómo funciona el modo Observer \{#how-observer-mode-works\} En el modo Observer, tú reportas las nuevas transacciones de Apple/Google al SDK de Adapty, y el SDK las reenvía al backend de Adapty. Eres responsable de gestionar el acceso al contenido de pago en tu app, completar las transacciones, gestionar las renovaciones, resolver los problemas de facturación, etc. ## Cómo configurar el modo Observer \{#how-to-set-up-observer-mode\} 1. Configura la integración inicial de Adapty [con Google Play](initial-android) y [con App Store](initial_ios). 2. Actívalo al configurar el SDK de Adapty estableciendo el parámetro `observerMode` en `true`. Sigue las instrucciones de configuración para [iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk), [Android](sdk-installation-android#activate-adapty-module-of-adapty-sdk), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform#activate-adapty-sdk) y [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk). 3. [Reporta las transacciones](report-transactions-observer-mode) desde tu infraestructura de compras existente a Adapty para iOS y frameworks multiplataforma basados en iOS. 4. (opcional) Si quieres usar integraciones con terceros, configúralas como se describe en el artículo [Configurar integraciones con terceros](configuration). :::warning Al operar en modo Observer, el SDK de Adapty no finaliza las transacciones, así que asegúrate de gestionar este aspecto tú mismo. ::: ## Cómo usar paywalls y pruebas A/B en el modo Observer \{#how-to-use-paywalls-and-ab-tests-in-observer-mode\} En el modo Observer, el SDK de Adapty no puede determinar el origen de las compras, ya que estas se realizan en tu propia infraestructura. Por lo tanto, si pretendes usar paywalls y/o pruebas A/B en el modo Observer, debes asociar la transacción procedente de tu store con el paywall correspondiente en el código de tu app móvil al reportar una transacción. Además, los paywalls diseñados con el Paywall Builder deben mostrarse de una forma especial cuando se usa el modo Observer: - Muestra paywalls en el modo Observer para [iOS](implement-observer-mode) o [Android](android-present-paywall-builder-paywalls-in-observer-mode). - [Asocia paywalls a transacciones de compra](report-transactions-observer-mode) al reportar transacciones en el modo Observer. --- # File: migration-from-revenuecat --- --- title: "Migración desde RevenueCat" description: "Migra de RevenueCat a Adapty con nuestra guía paso a paso." --- Tu plan de migración tiene 5 pasos lógicos y dura una media de 2 horas. El 90 % de todas las migraciones se completan en menos de un día laborable. 1. Aprende las diferencias clave y crea y prepara una cuenta de Adapty _(5 minutos)_; 2. Instala el SDK de Adapty para tu plataforma ([iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity)) en lugar del SDK de RevenueCat _(1 hora)_; 3. Configura las [notificaciones de servidor de Apple App Store](enable-app-store-server-notifications) para Adapty y (opcionalmente) el [reenvío de eventos sin procesar](enable-app-store-server-notifications#raw-events-forwarding) _(5 minutos)_; 4. Prueba y publica la actualización de tu app _(30 minutos)_; 5. (Opcional) Solicita al soporte de RevenueCat los datos históricos en formato CSV _(5 minutos)_; 6. (Opcional) Importa los datos históricos a través del soporte de Adapty _(30 minutos)_. :::info Tus suscriptores migrarán automáticamente Todos los usuarios que alguna vez hayan activado una suscripción pasarán a Adapty automáticamente en cuanto abran la nueva versión de tu app con el SDK de Adapty. La validación del estado de la suscripción y el acceso premium se restaurarán de forma automática. ::: Antes de publicar una nueva versión de tu app con el SDK de Adapty, asegúrate de revisar nuestra [lista de verificación para el lanzamiento](release-checklist). ## Aprende las diferencias clave y crea y prepara una cuenta de Adapty \{#learn-the-core-differences-create-and-prepare-an-adapty-account\} Los SDKs de Adapty y RevenueCat tienen un diseño similar. La mayor diferencia está en el uso de red y la velocidad: el SDK de Adapty está diseñado para proporcionarte información lo más rápido posible cuando la solicitas. Por ejemplo, al pedir un paywall, primero recibes el [Remote Config](customize-paywall-with-remote-config) para precomponer tu onboarding o paywall, y luego solicitas los productos en una petición separada. Los nombres son ligeramente distintos: | RevenueCat | Adapty | | :---------- | :-------------- | | Package | Product | | Offering | Paywall | | Paywall | Paywall Builder | | Entitlement | Access level | Adapty tiene el concepto de [placement](placements). Es un lugar lógico dentro de tu app donde el usuario puede realizar una compra. En la mayoría de los casos, tendrás uno o dos placements: - Onboarding (ya que el 80 % de todas las compras se realizan ahí); - General (se muestra en los ajustes o dentro de la app después del onboarding).
## Instala el SDK de Adapty y reemplaza el SDK de RevenueCat \{#install-adapty-sdk-and-replace-revenuecat-sdk\}
Instala el SDK de Adapty para tu plataforma ([iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity)) en tu app.
Necesitas reemplazar algunos métodos del SDK en el lado de la app. Veamos las funciones más comunes y cómo sustituirlas por las del SDK de Adapty.
### Activación del SDK \{#sdk-activation\}
Reemplaza `Purchases.configure` con `Adapty.activate`.
### Obtener paywalls (offerings) \{#getting-paywalls-offerings\}
Reemplaza `Purchases.shared.getOfferings` con [`Adapty.getPaywall`](fetch-paywalls-and-products#fetch-paywall-information).
En Adapty, siempre solicitas el paywall mediante el [placement id](placements). En la práctica, solo obtienes 1 o 2 paywalls como máximo, así que lo hemos diseñado así a propósito para acelerar el SDK y reducir el uso de red.
### Obtener un usuario (perfil del cliente) \{#getting-a-user-customer-profile\}
Reemplaza `Purchases.shared.getCustomerInfo` con `Adapty.getProfile`.
### Obtener productos \{#getting-products\}
En RevenueCat, usas la siguiente estructura: `Purchases.shared.getOfferings` y luego `self.offering?.availablePackages`.
En Adapty, primero solicitas un paywall (ver arriba) para acceder de inmediato al [Remote Config](customize-paywall-with-remote-config) de Adapty, y luego obtienes los productos con [`Adapty.getPaywallProducts`](fetch-paywalls-and-products#fetch-products).
### Realizar una compra \{#making-a-purchase\}
Reemplaza `Purchases.shared.purchase` con [`Adapty.makePurchase`](making-purchases#make-purchase).
### Verificar el nivel de acceso (entitlement) \{#checking-access-level-entitlement\}
Obtén el perfil del cliente (lee el apartado anterior primero) y luego reemplaza
`customerInfo?.entitlements["premium"]?.isActive == true`
con
[`profile.accessLevels["premium"]?.isActive == true`](subscription-status#retrieving-the-access-level-from-the-server).
### Restaurar una compra \{#restore-purchase\}
Reemplaza `Purchases.shared.restorePurchases` con [`Adapty.restorePurchases`](restore-purchase).
### Comprobar si el usuario ha iniciado sesión \{#check-if-the-user-is-logged-in\}
Reemplaza `Purchases.shared.isAnonymous` con `if profile.customerUserId == nil`.
### Iniciar sesión con un usuario \{#log-in-user\}
Reemplaza `Purchases.shared.logIn` con [`Adapty.identify`](identifying-users#set-customer-user-id-after-configuration).
### Cerrar sesión de un usuario \{#log-out-user\}
Reemplaza `Purchases.shared.logOut` con [`Adapty.logout`](identifying-users#logging-out-and-logging-in).
## Cambia las notificaciones del servidor de App Store a Adapty \{#switch-app-store-server-side-notifications-to-adapty\}
Lee cómo hacerlo [aquí](migrate-to-adapty-from-another-solutions#changing-apple-server-notifications).
## Prueba y publica una nueva versión de tu app \{#test-and-release-a-new-version-of-your-app\}
Si estás leyendo esto, ya has:
- [x] Configurado el Adapty Dashboard
- [x] Instalado el SDK de Adapty
- [x] Reemplazado la lógica del SDK con las funciones de Adapty
- [x] Cambiado las notificaciones del servidor de App Store a Adapty y, opcionalmente, activado el reenvío de eventos sin procesar a RevenueCat
- [ ] Realizado una compra en sandbox
- [ ] Publicado una nueva versión de la app
Si has marcado los puntos anteriores, haz una compra de prueba en el Sandbox y luego publica la app.
:::info
Repasa la [lista de verificación para el lanzamiento](release-checklist).
Haz la revisión final con nuestra lista para validar la integración existente o añadir funciones adicionales como integraciones de [atribución](attribution-integration) o [análisis](analytics-integration).
:::
## (Opcional) Exporta tus datos históricos de RevenueCat en formato CSV \{#optional-export-your-revenuecat-historical-data-in-csv-format\}
:::warning
No te precipites con la importación de datos históricos
Deberías esperar al menos una semana después de publicar la versión con el SDK antes de importar los datos históricos. Durante ese tiempo recopilaremos toda la información sobre los precios de compra desde el SDK, por lo que los datos que importes serán más relevantes.
:::
Exporta tus datos históricos de RevenueCat en formato CSV siguiendo las instrucciones de la [documentación oficial de RevenueCat](https://www.revenuecat.com/docs/integrations/scheduled-data-exports).
## (Opcional) Solicita al soporte de RevenueCat los tokens de compra de Google \{#optional-ask-revenuecat-support-for-google-purchase-tokens\}
Si necesitas importar transacciones de Google Play, contacta con el soporte de RevenueCat para obtener un archivo CSV con los Google Purchase Tokens a través de su [página de soporte](https://app.revenuecat.com/settings/support). El Google Purchase Token es un identificador único que proporciona Google Play para cada transacción, imprescindible para rastrear y verificar las compras con precisión en Adapty. Esta información no se incluye en el archivo de exportación estándar. El archivo contiene las siguientes tres columnas:
- `user_id`
- `google_purchase_token`
- `google_product_id`
## Escríbenos para importar tus datos históricos \{#write-us-to-import-your-historical-data\}
Contáctanos a través del chat del sitio web o envíanos un correo a [support@adapty.io](mailto:support@adapty.io) con tus archivos CSV.
1. Envía el archivo CSV que exportaste de RevenueCat directamente a nuestro equipo de soporte.
2. Si vas a importar transacciones de Google Play, incluye el archivo CSV con los Google Purchase Tokens que recibiste del soporte de RevenueCat.
3. Indícanos qué ID de usuario debe usarse como Customer User ID (el identificador principal de usuario en Adapty): `rc_original_app_user_id` o `rc_last_seen_app_user_id_alias`.
Nuestro equipo de soporte importará tus transacciones a Adapty. Se importarán los siguientes datos para cada transacción:
| Parámetro | Descripción |
| ----------------------------- | ------------------------------------------------------------ |
| user_id | Customer User ID, el identificador principal de tu usuario en Adapty y en tu sistema. |
| apple_original_transaction_id | Para cadenas de suscripciones, esta es la fecha de compra de la transacción original, vinculada por `store_original_transaction_id`. |
| google_product_id | El ID del producto en Google Play Store. |
| google_purchase_token | Un identificador único proporcionado por Google Play para cada transacción, necesario para la validación. |
| country | El país del usuario. |
| created_at | La fecha y hora de creación del usuario. |
| subscription_expiration_date | La fecha y hora en que expira la suscripción. |
| email | El correo electrónico del usuario final. |
| phone_number | El número de teléfono del usuario final. |
| idfa | El Identificador para Anunciantes (IDFA), asignado por Apple al dispositivo de un usuario. |
| idfv | El Identificador para Proveedores (IDFV), un código asignado a todas las apps de un mismo desarrollador y compartido entre esas apps en un dispositivo. |
| advertising_id | Un identificador único proporcionado por el sistema operativo Android que los anunciantes pueden usar para el seguimiento. |
| attribution_channel | El nombre del canal de marketing. |
| attribution_campaign | El nombre de la campaña de marketing. |
| attribution_ad_group | El grupo de anuncios de atribución. |
| attribution_ad_set | El conjunto de anuncios de atribución. |
| attribution_creative | La palabra clave creativa de atribución. |
Además, se importarán los identificadores de integración para las siguientes integraciones: Amplitude, Mixpanel, AppsFlyer, Adjust y FacebookAds.
## Preguntas frecuentes \{#faq\}
### Instalé el SDK de Adapty correctamente y publiqué una nueva versión de la app. ¿Qué pasará con mis suscriptores existentes que no actualicen a la versión con el SDK de Adapty? \{#i-successfully-installed-adapty-sdk-and-released-a-new-app-version-with-it-what-will-happen-to-my-legacy-subscribers-who-did-not-update-to-a-version-with-adapty-sdk\}
La mayoría de los usuarios cargan sus teléfonos por la noche, que es cuando App Store suele actualizar automáticamente todas sus apps, por lo que no debería ser un problema. Puede que quede un pequeño número de suscriptores de pago que no hayan actualizado, pero seguirán teniendo acceso al contenido premium. No tienes que preocuparte por ello ni forzarlos a actualizar.
### ¿Necesito exportar mis datos históricos de RevenueCat lo antes posible o los perderé? \{#do-i-need-to-export-my-historical-data-from-revenuecat-as-quickly-as-possible-or-will-i-lose-it\}
No hace falta hacerlo con prisa; primero publica la versión con el SDK de Adapty y luego compártenos tus datos históricos. Restauraremos el historial de pagos de tus usuarios y completaremos los [perfiles](profiles-crm) y los [gráficos](charts).
### Uso MMP (AppsFlyer, Adjust, etc.) y herramientas de análisis (Mixpanel, Amplitude, etc.). ¿Cómo me aseguro de que todo funcionará correctamente? \{#i-use-mmp-appsflyer-adjust-etc-and-analytics-mixpanel-amplitude-etc-how-do-i-make-sure-that-everything-will-work\}
Primero tienes que pasarnos los IDs de esos servicios de terceros a través de nuestro SDK para que podamos enviarles datos. Lee la guía de [integración de atribución](attribution-integration) y de [integración de análisis](analytics-integration). Para los datos históricos y los usuarios existentes, **asegúrate de pasarnos esos IDs a partir de los datos que exportaste de RevenueCat.**
---
# File: migration-from-superwall
---
---
title: "Migración desde Superwall"
description: "Migra de Superwall a Adapty con una guía paso a paso que mapea cada llamada al SDK y cada concepto."
---
La mayoría de las migraciones desde Superwall a Adapty llevan unas dos horas. Cambias el SDK, apuntas las notificaciones del servidor de la store a Adapty y publicas una nueva versión de la app. Tus suscriptores de pago conservan su acceso — Adapty lo restaura desde los recibos de App Store y Google Play en el primer arranque.
:::info
Tus suscriptores migrarán automáticamente
Todos los usuarios que alguna vez hayan activado una suscripción pasan a Adapty en cuanto abran una nueva versión de tu app con el SDK de Adapty. La validación del estado de la suscripción y el acceso premium se restauran automáticamente.
:::
## Cómo está organizada esta guía \{#how-this-guide-is-organized\}
La migración tiene seis pasos:
1. [Mapea los conceptos de Superwall a Adapty](#map-your-superwall-concepts-to-adapty)
2. [Instala el SDK de Adapty](#install-the-adapty-sdk)
3. [Reemplaza las llamadas al SDK](#replace-sdk-calls)
4. [Cambia las notificaciones del servidor de App Store y Google Play](#switch-app-store-and-google-play-server-notifications)
5. [Prueba y publica](#test-and-release)
6. [(Opcional) Importa datos históricos](#optional-import-historical-data)
## Mapea los conceptos de Superwall a Adapty \{#map-your-superwall-concepts-to-adapty\}
La mayoría de los conceptos de Superwall tienen un equivalente directo en Adapty:
| Superwall | Adapty | Qué cambia |
| :------------------- | :------------------------------------------------ | :--------------------------------------------------------------------------- |
| Campaign | [Placement](placements) + [Audience](audience) | La lógica de la campaña se divide en un placement (la ubicación) y una audiencia (la regla). |
| Placement | [Placement](placements) | Mismo concepto, mismo nombre. |
| Audience filter | [Audience](audience) | Los conjuntos de reglas viven dentro de un placement. |
| Entitlement | [Nivel de acceso](access-level) | Identificador con nombre (por ejemplo, `premium`). |
| WebView paywall | [Paywall de Paywall Builder](adapty-paywall-builder) | Renderizado por el SDK de Adapty de forma nativa en lugar de un `WKWebView`. |
| `PurchaseController` | Integrado | No hay protocolo que implementar — Adapty gestiona las compras. |
| Feature gating | Comprobación de [nivel de acceso](access-level) | Comprueba `profile.accessLevels["premium"]?.isActive`. |
Hay dos cambios conceptuales que vale la pena tener en cuenta antes de tocar el código:
- **Obtener y presentar son pasos separados**: El método `register` de Superwall obtiene el paywall, evalúa la campaña y presenta la interfaz en una sola llamada. Adapty divide estos pasos — obtienes el paywall, su configuración de vista y luego lo presentas. Esto añade unas pocas líneas, pero te permite precargar configuraciones, mostrar un estado de carga personalizado o cancelar la presentación según tu propia lógica.
- **El estado de la suscripción es por nivel de acceso**: Superwall expone una sola propiedad publicada `subscriptionStatus`. Adapty devuelve un [`AdaptyProfile`](https://swift.adapty.io/documentation/adapty/adaptyprofile) con niveles de acceso con nombre, de modo que un usuario puede tener los niveles de acceso `sports` y `science` de forma independiente. Para lecturas síncronas, guarda en caché el perfil del `AdaptyDelegate` en lugar de llamar a `getProfile()` en cada carga de vista.
## Instala el SDK de Adapty \{#install-the-adapty-sdk\}
Instala el SDK de Adapty para tu plataforma — [iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity) o [Capacitor](sdk-installation-capacitor) — y elimina SuperwallKit de tu proyecto al mismo tiempo.
## Reemplaza las llamadas al SDK \{#replace-sdk-calls\}
Revisa cada área de tu integración y sustituye la llamada de Superwall por su equivalente en Adapty. Los enlaces al final de cada subsección cubren los siete SDKs de plataforma — sigue el que corresponda a tu app.
### Inicializa el SDK \{#initialize-the-sdk\}
Reemplaza `Superwall.configure` con `Adapty.activate`.
Consulta la guía de instalación para tu plataforma — [iOS](sdk-installation-ios), [Android](sdk-installation-android), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter), [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform), [Unity](sdk-installation-unity) o [Capacitor](sdk-installation-capacitor).
### Identifica y desconecta usuarios \{#identify-and-log-out-users\}
Reemplaza `Superwall.shared.identify` con `Adapty.identify` y `Superwall.shared.reset` con `Adapty.logout`. Ambos SDKs generan un perfil anónimo en el primer arranque, por lo que estas llamadas solo son necesarias cuando un usuario inicia o cierra sesión. Vuelve a obtener los paywalls después de identificar — el nuevo usuario puede resolverse a una audiencia diferente.
Consulta la guía de identificación para tu plataforma — [iOS](identifying-users), [Android](android-identifying-users), [React Native](react-native-identifying-users), [Flutter](flutter-identifying-users), [Kotlin Multiplatform](kmp-identifying-users), [Unity](unity-identifying-users) o [Capacitor](capacitor-identifying-users).
### Obtén y presenta un paywall \{#fetch-and-present-a-paywall\}
Reemplaza `Superwall.shared.register` con un flujo de dos pasos: obtén el paywall con `Adapty.getPaywall`, carga su configuración de vista con `AdaptyUI.getPaywallConfiguration` y luego preséntalo.
Dos diferencias a destacar:
- **El feature gating reemplaza el closure `feature:`**: Después de que se cierre el paywall, comprueba el nivel de acceso activo en el perfil devuelto (o en `Adapty.getProfile`) y ramifica desde ahí.
- **Los paywalls son renderizados por el SDK**: Superwall renderiza los paywalls dentro de un `WKWebView`. Adapty renderiza los paywalls del Paywall Builder de forma nativa — las fuentes, la información del producto y los botones los dibuja el SDK.
Consulta la guía de inicio rápido de paywalls para tu plataforma — [iOS](ios-quickstart-paywalls), [Android](android-quickstart-paywalls), [React Native](react-native-quickstart-paywalls), [Flutter](flutter-quickstart-paywalls), [Kotlin Multiplatform](kmp-quickstart-paywalls), [Unity](unity-quickstart-paywalls) o [Capacitor](capacitor-quickstart-paywalls).
### Comprueba el estado de la suscripción \{#check-subscription-status\}
Reemplaza `Superwall.shared.subscriptionStatus` con una comprobación del nivel de acceso con nombre en el perfil: `profile.accessLevels["premium"]?.isActive`. Observa los cambios mediante `AdaptyDelegate.didLoadLatestProfile(_:)` en lugar del patrón de propiedad `@Published`, y guarda el perfil en caché en tu lado para lecturas síncronas.
Consulta la guía de estado de suscripción para tu plataforma — [iOS](ios-check-subscription-status), [Android](android-check-subscription-status), [React Native](react-native-check-subscription-status), [Flutter](flutter-check-subscription-status), [Kotlin Multiplatform](kmp-check-subscription-status), [Unity](unity-check-subscription-status) o [Capacitor](capacitor-check-subscription-status).
### Gestiona compras y restauraciones \{#handle-purchases-and-restores\}
Con el Paywall Builder, ambos SDKs procesan las compras automáticamente dentro de la interfaz del paywall — **puedes saltarte este paso**.
Para paywalls personalizados, Superwall requiere una implementación de `PurchaseController`. Adapty no: reemplaza `PurchaseController.purchase` con `Adapty.makePurchase` y `PurchaseController.restorePurchases` con `Adapty.restorePurchases`. El SDK gestiona la validación por su cuenta.
Consulta la guía de inicio rápido de paywall personalizado para tu plataforma — [iOS](ios-quickstart-manual), [Android](android-quickstart-manual), [React Native](react-native-quickstart-manual), [Flutter](flutter-quickstart-manual), [Kotlin Multiplatform](kmp-quickstart-manual), [Unity](unity-quickstart-manual) o [Capacitor](capacitor-quickstart-manual).
### Configura atributos de usuario \{#set-user-attributes\}
Reemplaza `Superwall.shared.setUserAttributes` con `Adapty.updateProfile`.
Consulta la guía de atributos de usuario para tu plataforma — [iOS](setting-user-attributes), [Android](android-setting-user-attributes), [React Native](react-native-setting-user-attributes), [Flutter](flutter-setting-user-attributes), [Kotlin Multiplatform](kmp-setting-user-attributes), [Unity](unity-setting-user-attributes) o [Capacitor](capacitor-setting-user-attributes).
## Cambia las notificaciones del servidor de App Store y Google Play \{#switch-app-store-and-google-play-server-notifications\}
Apunta las notificaciones del servidor de la store a Adapty. Adapty funciona sin ellas, pero las analíticas, las integraciones de terceros y las métricas de pruebas A/B dependen de ellas:
- **App Store**: Sigue [Habilitar notificaciones del servidor de App Store](enable-app-store-server-notifications).
- **Google Play**: Sigue [Habilitar notificaciones en tiempo real para desarrolladores](enable-real-time-developer-notifications-rtdn).
Si quieres ejecutar Superwall y Adapty en paralelo durante el lanzamiento, usa el [reenvío de eventos sin procesar](enable-app-store-server-notifications#raw-events-forwarding) — Adapty reenvía los eventos de la store a Superwall mientras verificas la nueva integración.
## Prueba y publica \{#test-and-release\}
Antes de publicar, comprueba cada elemento:
- [x] Configurado el Adapty Dashboard (productos, paywalls, placements, niveles de acceso)
- [x] Instalado el SDK de Adapty
- [x] Reemplazadas las llamadas al SDK de Superwall por sus equivalentes en Adapty
- [x] Apuntadas las notificaciones del servidor de App Store y Google Play a Adapty
- [ ] Realizada una compra en sandbox
- [ ] Enviada una nueva versión de la app
Revisa el [checklist de lanzamiento](release-checklist) para una validación final.
## (Opcional) Importa datos históricos \{#optional-import-historical-data\}
Superwall no es dueño de tu estado de suscripción — lo son App Store y Google Play. Adapty valida los recibos en el primer arranque, por lo que los usuarios de pago conservan su acceso sin necesidad de ninguna importación.
Si quieres que las transacciones históricas queden registradas en las analíticas de Adapty, sigue [Importar datos históricos a Adapty](importing-historical-data-to-adapty). Espera al menos una semana después del lanzamiento del SDK para que tenga tiempo de recopilar precios de compra actualizados.
## Preguntas frecuentes \{#faq\}
### ¿Qué pasa con los suscriptores que no actualizan la app? \{#what-happens-to-subscribers-who-dont-update-the-app\}
La mayoría de los usuarios actualizan sus apps automáticamente durante la noche, por lo que la proporción de usuarios en la versión anterior disminuye rápidamente. Los suscriptores en la versión antigua conservan su acceso directamente a través de App Store o Google Play — no es necesario forzar una actualización.
### ¿Las audiencias de mis campañas de Superwall se migran? \{#do-my-superwall-campaign-audiences-carry-over\}
No. Los filtros de audiencia de Superwall y las audiencias de Adapty se configuran en dashboards diferentes y usan identificadores distintos. Recrea tu segmentación como [audiencias](audience) dentro de los [placements](placements) de Adapty. La mayoría de las apps tienen uno o dos placements (onboarding y un trigger general dentro de la app), por lo que la reconstrucción suele ser rápida.
### ¿Tiene Adapty un equivalente a `getPresentationResult`? \{#does-adapty-have-an-equivalent-to-getpresentationresult\}
No como una sola llamada. Para comprobar si un placement mostraría un paywall, llama a `Adapty.getPaywall(placementId:)` y ramifica según el resultado. Si la llamada tiene éxito, hay un paywall asignado para la audiencia de ese usuario. Si falla porque no hay ningún paywall configurado, omite la presentación y ejecuta tu lógica de respaldo.
---
# File: importing-historical-data-to-adapty
---
---
title: "Importar datos históricos en Adapty"
description: "Importa datos históricos en Adapty para obtener analíticas detalladas."
---
Después de instalar el SDK de Adapty y publicar tu app, puedes acceder a tus usuarios y suscriptores en la sección [Profiles](profiles-crm). Pero ¿qué pasa si tienes una infraestructura legacy y necesitas migrar a Adapty, o simplemente quieres ver tus datos existentes en Adapty?
:::note
La importación de datos no es obligatoria
Adapty otorgará automáticamente niveles de acceso a los usuarios históricos y restaurará sus eventos de compra en cuanto abran la app con el SDK de Adapty integrado. Para este caso de uso, importar datos históricos no es necesario. Sin embargo, importar los datos garantiza unas analíticas precisas si tienes un volumen significativo de transacciones históricas, aunque en general no es un requisito para la migración.
:::
Para importar datos en Adapty:
1. Exporta tus transacciones a un archivo CSV (se deben proporcionar archivos separados para iOS, Android y Stripe). Consulta la sección [Formato del archivo de importación](importing-historical-data-to-adapty#import-file-format) más abajo para conocer los requisitos detallados.
2. Si algún archivo supera 1 GB, prepara una muestra de datos con aproximadamente 100 líneas.
3. Sube todos los archivos a Google Drive (puedes comprimirlos, pero mantenlos separados).
4. Para las transacciones de iOS, asegúrate de que la sección **In-app purchase API** en [**App settings**](https://app.adapty.io/settings/ios-sdk) esté completada con el **Issuer ID**, **Key ID** y la **Private key** (archivo .P8), incluso si usas StoreKit 1. Consulta las secciones [Provide Issuer ID and Key ID](app-store-connection-configuration#step-2-provide-issuer-id-and-key-id) y [Upload In-App Purchase Key file](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file) para obtener instrucciones detalladas.
5. Comparte los enlaces con nuestro equipo a través de [correo electrónico](mailto:support@adapty.io) o del chat en línea en el Adapty Dashboard.
No te preocupes: importar datos históricos no creará duplicados, aunque esos datos se solapen con entradas ya existentes en Adapty.
## Limitaciones conocidas para Android \{#known-limitations-for-android\}
1. Solo se restaurarán las suscripciones activas; las transacciones expiradas no se restaurarán.
2. Solo se restaurarán las renovaciones más recientes de una suscripción; no se restaurará toda la cadena de compras.
3. Si el precio del producto ha cambiado desde la compra, se utilizará el precio actual, lo que puede dar lugar a precios incorrectos.
:::note
Si tienes un gran volumen de transacciones de Android, es posible que necesites [solicitar un aumento de cuota de la Google Play Developer API](google-play-quota-increase) antes de comenzar la importación para evitar superar el límite predeterminado de la API.
:::
## Formato del archivo de importación \{#import-file-format\}
:::tip
Si estás migrando desde RevenueCat, puedes enviar el archivo de exportación de RevenueCat directamente, sin necesidad de convertirlo. Consulta la [documentación de RevenueCat](https://www.revenuecat.com/docs/integrations/scheduled-data-exports) para obtener instrucciones de exportación.
:::
Prepara tus datos en uno o varios archivos que cumplan las siguientes reglas:
- [ ] El formato del archivo es .CSV.
- [ ] Archivos separados para importaciones de Android, iOS y Stripe.
- [ ] Cada archivo de importación contiene todas las [columnas requeridas](importing-historical-data-to-adapty#required-fields).
- [ ] Las columnas de los archivos de importación tienen encabezados.
- [ ] Los encabezados de columna coinciden exactamente con los de la columna **Column name** de la tabla de abajo. Comprueba que no haya errores tipográficos.
- [ ] Las columnas que no son obligatorias pueden estar ausentes del archivo. No añadas columnas vacías para datos que no tengas.
- [ ] Los archivos de importación no deben tener columnas adicionales que no se mencionen en la tabla. Si las hay, elimínalas.
- [ ] Los valores están separados por comas.
- [ ] Los valores no están entre comillas.
- [ ] Si hay varios **apple_original_transaction_id** para un mismo usuario, añádelos todos como líneas separadas para cada **apple_original_transaction_id**. De lo contrario, es posible que no podamos restaurar las compras consumibles.
Usa los siguientes archivos como ejemplos para [iOS](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/adapty_import_ios_sample.csv) y [Android](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/adapty_import_android_sample.csv).
### Columnas disponibles en el archivo de importación \{#available-import-file-columns\}
| Nombre de columna | Presencia | Descripción |
|-----------|--------|-----------|
| **user_id** | obligatorio | ID de tu usuario |
| **apple_original_transaction_id** | obligatorio para iOS | El ID de transacción original u OTID ([más información](https://developer.apple.com/documentation/appstoreserverapi/originaltransactionid)), utilizado en el mecanismo de importación de StoreKit 2. Como un usuario puede tener varios OTID, basta con proporcionar al menos uno para una importación exitosa.
**Nota:** Para esta importación es necesario que las credenciales de la In-app purchase API estén configuradas en tu Adapty Dashboard. Aprende cómo hacerlo [aquí](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file).
| | **google_product_id** | obligatorio para Google | ID del producto en la Google Play Store. | | **google_purchase_token** | obligatorio para Google | Identificador único que representa al usuario y el ID del producto de la compra in-app que realizó | | **google_is_subscription** | obligatorio para Google | Los valores posibles son `1` \| `0` | | **stripe_token** | obligatorio para Stripe | Token de un objeto de Stripe que representa una compra única. Puede ser el token de una Suscripción de Stripe (`sub_...`) o de un Payment Intent (`pi_...`). | | **subscription_expiration_date** | opcional | La fecha de expiración de la suscripción, es decir, la próxima fecha de cobro, con fecha y hora con zona horaria (2020-12-31T23:59:59-06:00) | | **created_at** | opcional | Fecha y hora de creación del perfil (2019-12-31 23:59:59-06:00) | | **birthday** | opcional | La fecha de nacimiento del usuario en formato 2000-12-31 | | **email** | opcional | El correo electrónico de tu usuario | | **gender** | opcional | El género del usuario | | **phone_number** | opcional | El número de teléfono de tu usuario | | **country** | opcional | formato [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) | | **first_name** | opcional | El nombre de tu usuario | | **last_name** | opcional | El apellido de tu usuario | | **last_seen** | opcional | La fecha y hora con zona horaria (2020-12-31T23:59:59-06:00) | | **idfa** | opcional | El identificador para anunciantes (IDFA) es un identificador de dispositivo aleatorio que Apple asigna al dispositivo del usuario. Solo aplicable a apps de iOS | | **idfv** | opcional | El identificador para proveedores (IDFV) es un código único asignado a todas las apps desarrolladas por un mismo desarrollador, en este caso las tuyas. Solo aplicable a apps de iOS | | **advertising_id** | opcional | El Advertising ID es un código único asignado por el sistema operativo Android que los anunciantes pueden usar para identificar de forma única el dispositivo de un usuario | | **amplitude_user_id** | opcional | El ID de usuario de Amplitude | | **amplitude_device_id** | opcional | El ID de dispositivo de Amplitude | | **mixpanel_user_id** | opcional | ID de usuario de Mixpanel | | **appmetrica_profile_id** | opcional | ID de perfil de usuario de AppMetrica | | **appmetrica_device_id** | opcional | El ID de dispositivo de AppMetrica | | **appsflyer_id** | opcional | Identificador único de AppsFlyer | | **adjust_device_id** | opcional | El ID de dispositivo de Adjust | | **facebook_anonymous_id** | opcional | Identificador único generado por Facebook para usuarios que interactúan con tu app o sitio web de forma anónima, es decir, sin haber iniciado sesión en Facebook | | **branch_id** | opcional | Identificador único de Branch | | **attribution_source** | opcional | La integración de origen de la atribución, por ejemplo, appsflyer | | **attribution_status** | opcional | organic | | **attribution_channel** | opcional | El canal de atribución que trajo la transacción | | **attribution_campaign** | opcional | La campaña de atribución que trajo la transacción | | **attribution_ad_group** | opcional | El grupo de anuncios de atribución que trajo la transacción | | **attribution_ad_set** | opcional | El conjunto de anuncios de atribución que trajo la transacción | | **attribution_creative** | opcional | Elementos visuales o textuales específicos utilizados en un anuncio o campaña de marketing que se rastrean para determinar su efectividad a la hora de generar acciones deseadas, como clics, conversiones o instalaciones | | **custom_attributes** | opcional | Define hasta 30 atributos personalizados como un diccionario JSON en formato clave-valor:Formato: `"{'string_value': 'some_value', 'float_value': 123.0, 'int_value': 456}"`.
Ten en cuenta el uso de comillas dobles y simples en el formato. Los valores booleanos y enteros se convertirán a float.
| ### Campos obligatorios \{#required-fields\} Hay 2 grupos de campos obligatorios para cada plataforma: **user_id** y los datos que identifican las compras específicas de la plataforma correspondiente. Consulta la tabla a continuación para conocer los campos obligatorios por plataforma. | Plataforma | Campos obligatorios | |--------|---------------| | iOS |user_id
apple_original_transaction_id
| | Android |user_id
google_product_id
google_purchase_token
google_is_subscription
| | Stripe |user_id
stripe_token
| Sin estos campos, Adapty no podrá obtener las transacciones. Para unas analíticas de cohorte precisas, especifica `created_at`. Si no se proporciona, asumiremos que la fecha de instalación coincide con la fecha de la primera compra. ### Importar datos en Adapty \{#import-data-to-adapty\} Ponte en contacto con nosotros y comparte tus archivos de importación a través de [support@adapty.io](mailto:support@adapty.io) o del chat en línea en el [Adapty Dashboard](https://app.adapty.io/overview). --- # File: migrate-integrations-to-adapty --- --- title: "Migrar integraciones a Adapty" description: "Cambia las integraciones de analytics y atribución de una solución legacy a Adapty sin duplicar eventos ni interrumpir campañas." --- Migrar a Adapty requiere algo más que cambiar el SDK. Tus integraciones de analytics y atribución con terceros — herramientas como Amplitude y Adjust — también necesitan una transición coordinada. Si se hace con cuidado, el cambio genera muy pocos eventos duplicados o perdidos y no interrumpe tus campañas. ## Mapea tus eventos \{#map-your-events\} Los nombres de eventos son personalizables en la mayoría de las integraciones de Adapty. Puedes configurarlos para que coincidan con los nombres que ya usas en tus dashboards y campañas. Tanto tus informes de analytics como los de campañas seguirán funcionando con los mismos nombres de eventos tras el cambio. Para ver la lista completa de eventos disponibles en Adapty, consulta [Eventos](events). En el caso de Adjust, la integración utiliza IDs de eventos en lugar de nombres de eventos personalizados. Transfiere tus IDs de eventos existentes desde el dashboard de Adjust a la configuración de la integración de Adapty. Consulta la [guía de integración de Adjust](adjust) para más detalles. ## Cómo crea Adapty los eventos de integración \{#how-adapty-creates-integration-events\} Para enviar un evento a una integración, Adapty necesita tener un perfil de usuario. Un perfil se crea de una de estas dos formas: - **Importación histórica**: el perfil se crea cuando [importas datos históricos de transacciones](importing-historical-data-to-adapty) antes de que el SDK entre en funcionamiento. - **Interacción con el SDK**: el perfil se crea automáticamente cuando el usuario abre la app con el SDK de Adapty por primera vez. Adapty se entera de las compras realizadas en el sistema legacy en tiempo real. Sin embargo, solo puede enviar un evento de integración una vez que el perfil del comprador existe. Ese perfil se crea cuando el usuario abre la app con el SDK de Adapty. Los usuarios que no actualicen a la nueva versión no generarán eventos de integración. ## Prepárate antes del día de la migración \{#prepare-before-migration-day\} ### Excluye los eventos históricos \{#exclude-historical-events\} Activa **Exclude Historical Events** en los [ajustes de tu integración](configuration). Esto impide que los eventos anteriores a la primera sesión del usuario con el SDK de Adapty se envíen a la integración. Esta configuración es especialmente importante durante la [importación histórica](importing-historical-data-to-adapty), cuando Adapty procesa un gran volumen de transacciones pasadas de una vez. Sin ella, esas transacciones generarán un gran volumen de eventos en tu herramienta de analytics. ### Configura la integración con antelación \{#set-up-the-integration-in-advance\} Adapty te permite configurar y probar una integración mientras la mantienes desactivada. Puedes establecer credenciales, mapeo de eventos y filtros sin activar la integración hasta que estés listo. La configuración se guarda cuando la activas, así que no se pierde nada por mantenerla desactivada hasta el día de la migración. Para encontrar tu integración, consulta [Integraciones de atribución](attribution-integration), [Integraciones de analytics](analytics-integration), [Integraciones de servicios de mensajería](messaging) o [Integraciones de Webhook y ETL](webhook-and-etl). ## Realiza el cambio el día de la migración \{#switch-on-migration-day\} Desactiva la integración en tu solución legacy y actívala en Adapty al mismo tiempo. Ejecutar ambas simultáneamente generará eventos duplicados. Pausa las campañas de adquisición grandes el día de la migración. Esto reduce el riesgo de errores en la optimización de campañas causados por eventos en la ventana de solapamiento. ## Qué esperar \{#what-to-expect\} Algunos eventos de integración perdidos o duplicados durante la migración son inevitables. Cuando el cambio se realiza correctamente, el número de eventos afectados es insignificante. La principal fuente de huecos es el momento descrito anteriormente: Adapty solo puede enviar eventos de integración para una compra después de que exista el perfil del usuario. Las compras realizadas en el sistema legacy no generan eventos de integración en Adapty hasta que el comprador abre la app con el SDK de Adapty. ## Integraciones frente a notificaciones server-to-server \{#integrations-vs-server-to-server-notifications\} Adapty recomienda usar integraciones en lugar de reenviar las notificaciones server-to-server sin procesar del store directamente a tus herramientas de analytics o atribución. Con las integraciones: - **Formato unificado**: los eventos de todos los stores — App Store, Google Play, Stripe — utilizan el mismo formato de evento. - **Datos enriquecidos**: los eventos incluyen datos que Adapty recopila, como el estado de la suscripción y los atributos del usuario. Las notificaciones sin procesar no incluyen esto. --- # File: whats-new --- --- title: "Novedades" description: "Mantente al día con las últimas funciones y mejoras de Adapty" --- Descubre las últimas funciones, mejoras, actualizaciones del SDK y mejoras en la documentación que te ayudan a optimizar la estrategia de monetización de tu app. Esta página destaca los lanzamientos más importantes de cada mes. :::note ¿Tienes comentarios sobre las nuevas funciones? ¡Nos encantaría escucharte! Contáctanos a través del [tablón de comentarios sobre el producto](https://adapty.featurebase.app/en?b=69831ba5e82e7a3391632ec2). ::: ## Abril 2026 \{#april-2026\} - **Adapty Mail**: Campañas de email generadas por IA que convierten a usuarios en prueba en suscriptores de pago. Crea, envía y atribuye campañas desde tu proyecto de Adapty sin necesidad de ninguna plataforma de email independiente. [Más información](adapty-mail) - **Diagnóstico de paywall en Autopilot**: Descubre qué mejorar en tu paywall antes de crear una prueba. Sube una captura de pantalla y Autopilot te devuelve recomendaciones basadas en benchmarks de las apps con mejor rendimiento en tu categoría, además de sugerencias de diseño y texto generadas por IA. Las recomendaciones con benchmark se convierten en rondas de prueba A/B en tu plan de crecimiento. [Más información](autopilot-analysis#paywall-analysis) - **Orientación más clara para cada sugerencia de Autopilot**: Cada hipótesis ahora explica por qué es importante (una explicación basada en datos de cómo tu paywall se desvía de los patrones establecidos), qué cambiar y cómo configurar la prueba A/B, y qué métricas observar en la nueva sección "Cómo interpretar tus resultados". [Más información](autopilot-growth-plan#step-1-view-the-hypothesis) - **Mantén actualizado tu plan de crecimiento de Autopilot**: Actualiza el análisis para incorporar los últimos datos de mercado y nuevas sugerencias, y restaura cualquier versión anterior desde el historial de versiones si las nuevas no dan en el clavo. Las hipótesis ahora están agrupadas en pestañas de Precios, Visual y Geoprecios, y se pueden omitir o eliminar rondas individuales. [Más información](autopilot-growth-plan#restore-an-older-version-of-the-growth-plan) - **Distribución de ingresos por duración en Autopilot**: Comprueba si tus ingresos están sobreconcentrados en una duración de suscripción. Un nuevo gráfico de Market Insights muestra la composición de tus ingresos por duración junto con la media del sector para tu categoría y país. [Más información](autopilot-analysis#revenue-distribution-by-duration) - **LTV y predicciones de ingresos actualizadas**: El LTV predicho y los ingresos ahora utilizan los datos de retención de cohortes de tu propia app cuando hay suficiente historial, y promedios entre apps en caso contrario — así incluso las apps más nuevas obtienen predicciones utilizables en análisis y pruebas A/B. [Más información](predicted-ltv-and-revenue) - **Enviar todos los eventos en Adapty UA**: Dale a Meta y TikTok una visión más completa de las conversiones para un modelado de audiencias más preciso. Adapty ahora permite reenviar instalaciones y transacciones de usuarios orgánicos y no atribuidos a tu píxel, no solo de usuarios vinculados a una campaña. [Meta](ua-facebook#send-all-events) | [TikTok](ua-tiktok#send-all-events) - **Documentación en ruso y turco**: La documentación de Adapty ya está disponible en ruso (Русский) y turco (Türkçe). Cambia de idioma usando el selector de idioma en la navegación superior. ## Marzo 2026 \{#march-2026\} - **CLI para desarrolladores**: Gestiona tu cuenta de Adapty desde la terminal sin abrir el Dashboard. El CLI te permite crear apps, definir niveles de acceso, configurar productos, crear paywalls y configurar placements — todo scriptable para entornos automatizados. También hay disponible una [skill de Adapty CLI](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) para ayudar a los asistentes de programación con IA a trabajar con el CLI. [Más información](developer-cli) - **Página general en Apple Ads Manager**: Consulta todas las métricas clave de Apple Ads en un solo lugar, cada una con un gráfico de tendencias. Filtra por app mediante el desplegable del encabezado, personaliza qué métricas se muestran y ajusta el tipo de gráfico y la visualización de ingresos. [Más información](ads-manager-overview) - **Inteligencia de mercado en Apple Ads Manager**: Descubre en qué palabras clave publican anuncios tus competidores en más de 50 países y añade las palabras clave de mejor rendimiento directamente a tus campañas. [Más información](ads-manager-market-intelligence) - **Automatizaciones de palabras clave de ciclo completo en Apple Ads Manager**: Ajusta pujas automáticamente, pausa o activa palabras clave y muévelas entre grupos de anuncios según las reglas de rendimiento que definas. [Más información](ads-manager-automations-keyword-rules) - **Historial de pujas en Apple Ads Manager**: Consulta el registro completo de cambios de la puja CPT de cualquier palabra clave: cuándo ocurrió cada cambio, los valores anterior y nuevo, y qué regla de automatización lo desencadenó. [Más información](ads-manager-manage-keywords#bid-history) - **Rondas visuales en Autopilot**: Las sugerencias de diseño de paywall ahora son rondas de primera clase en tu plan de crecimiento — aparecen en la barra lateral junto a las rondas de monetización. Cada ronda visual incluye un mockup de diseño, una descripción de cuándo funciona mejor ese patrón y las métricas clave que tiene como objetivo. [Más información](autopilot-growth-plan#view-the-growth-plan) - **Añade tu propia hipótesis a Autopilot**: Amplía tu plan de crecimiento con rondas personalizadas. Añade un título, descripción, tipo de ronda (monetización o visual), métricas objetivo y — en el caso de rondas de monetización — los productos involucrados. [Más información](autopilot-growth-plan#add-your-own-hypothesis) - **Reordena las rondas de Autopilot**: Arrastra y reordena las etapas de tu plan de crecimiento para ejecutar los experimentos en el orden que mejor se adapte a tu estrategia. [Más información](autopilot) - **Precios geográficos en Autopilot**: Prueba cambios de precio por país como un nuevo tipo de ronda en tu plan de crecimiento. A partir de los datos de Market Insights, Autopilot recomienda si aumentar, reducir o mantener los precios en cada país. Añade una recomendación como ronda de precios geográficos para ejecutarla como prueba A/B — se pueden ejecutar hasta 5 simultáneamente. [Más información](autopilot-growth-plan#geo-pricing-hypotheses) - **Automatizaciones de términos de búsqueda en Apple Ads Manager**: Promociona automáticamente los términos de búsqueda ganadores a palabras clave de coincidencia exacta y niégalos en el origen, sin necesidad de descargar informes manualmente. Las reglas se pueden crear desde plantillas o construir desde cero con condiciones y programaciones personalizadas. [Más información](ads-manager-automations-search-terms) - **Puja de Maximizar Conversiones en Apple Ads Manager**: Al crear campañas, ahora puedes seleccionar Maximizar Conversiones como estrategia de puja. El algoritmo de Apple maximiza las descargas dentro de tu presupuesto, guiado por un CPA objetivo opcional. [Más información](ads-manager-create-campaign) - **Integración con FunnelFox en Adapty UA**: Ya está disponible la nueva integración con FunnelFox en Adapty UA. [FunnelFox](ua-funnelfox) - **Documentación en chino**: La documentación de Adapty ya está disponible en chino (中文). Cambia de idioma con el selector de idioma en la navegación superior. ## Febrero de 2026 \{#february-2026\} - **Precios de productos por país**: Establece precios distintos por país directamente en el Adapty Dashboard — Adapty sincroniza los cambios con App Store Connect y Google Play de forma automática. Cada actualización de precios queda registrada en el registro de auditoría, sin que ningún cambio pase desapercibido. [Más información](edit-product) - **Precios de la competencia por país en Autopilot**: Compara los precios de tu suscripción con los de la competencia en tus mercados principales. [Más información](autopilot-analysis#market-and-competitor-analysis) - **Control de versiones de onboarding**: Rastrea y gestiona versiones de tus onboardings con un historial completo de versiones. Revisa los cambios y revierte cuando lo necesites. [Más información](onboarding-version-control) - **Gráficos de conversión de paywall en analytics**: Dos nuevos gráficos de conversión — Paywall view → Trial y Paywall view → Paid — muestran cómo tus paywalls convierten visitantes en suscriptores. [Más información](analytics-conversion) - **Segmentos duplicados**: Copia un segmento existente con todos sus filtros en lugar de reconstruir uno similar desde cero. Útil cuando se gestionan varias campañas o pruebas A/B con audiencias superpuestas. [Más información](segments#duplicate-segments) - **Notificaciones push en la app móvil de Adapty**: Configura notificaciones push para 14 tipos de eventos directamente en la app de Adapty para iOS y mantente al tanto de la actividad de suscripciones sin abrir el dashboard. [Más información](push-notifications) - **Kotlin Multiplatform SDK 3.15**: Añade soporte para onboardings, paywalls web y mejoras en la API. [Más información](migration-to-kmp-315) - **Capacitor SDK 3.16**: Añade soporte para Capacitor 8. Los proyectos que usen Capacitor 7 deben quedarse en el SDK v3.15. [Más información](migration-to-capacitor-316) - **Guías de integración del SDK asistidas por LLM**: Guías paso a paso para integrar Adapty con la ayuda de asistentes de programación con IA. Cada guía lleva a tu LLM a través de la implementación completa, desde la configuración en el dashboard hasta las compras. [iOS](adapty-cursor) | [Android](adapty-cursor-android) | [React Native](adapty-cursor-react-native) | [Flutter](adapty-cursor-flutter) | [Unity](adapty-cursor-unity) | [Kotlin Multiplatform](adapty-cursor-kmp) | [Capacitor](adapty-cursor-capacitor) ## Enero de 2026 \{#january-2026\} - **SDK de Capacitor publicado oficialmente**: El SDK de Capacitor ya está listo para producción tras un exhaustivo proceso de pruebas. Crea apps de suscripción para iOS y Android con Capacitor y soporte completo de integración con Adapty. [Más información](capacitor-sdk-overview) - **Autopilot para apps nuevas**: El análisis de Autopilot ya está disponible aunque tu app no tenga un historial extenso de transacciones. Obtén recomendaciones de optimización de precios basadas en datos y crea tu plan de crecimiento desde el primer día. [Más información](autopilot) - **Oportunidades de precios globales en Autopilot**: Identifica el potencial de ingresos en tus mercados más rentables con recomendaciones de precios por país. Autopilot analiza las tasas de conversión y el poder adquisitivo de tus 5 principales países, y te ofrece información basada en datos sobre si conviene subir, bajar o mantener los precios según el Índice de Precios de Adapty. [Más información](autopilot) - **Métricas de conversión de recuperación de facturación**: Nuevos gráficos de análisis rastrean los ingresos recuperados por problemas de facturación y períodos de gracia. Monitoriza "Billing issue converted", "Billing issue converted revenue", "Grace period converted" y "Grace period converted revenue" para medir tus esfuerzos de retención y recuperación. - **Gestión de anuncios directa en Apple Ads Manager**: Crea y gestiona tus campañas de Apple Ads directamente desde Adapty sin cambiar de plataforma. [Más información](ads-manager-manage-ads) - **Análisis de Apple Ads Manager**: Accede a métricas de rendimiento detalladas a nivel de anuncio y datos de atribución dentro de Adapty. Consulta el rendimiento de campañas, análisis de grupos de anuncios e información de atribución en un dashboard unificado. [Más información](adapty-ads-manager-analytics) - **Gráficos de atribución de Apple Ads**: Combina múltiples métricas de atribución en gráficos personalizables para analizar el rendimiento de tus Apple Ads junto con los datos de suscripción. [Más información](adapty-ads-manager-analytics#charts) - **Segmentos de atribución de Apple Ads**: Crea segmentos de usuarios basados en datos de atribución de Apple Ads con un flujo de trabajo simplificado de dos clics. Dirige tus campañas a usuarios por campaña, grupo de anuncios o palabra clave para análisis y experimentos más precisos. [Más información](ads-manager-create-segments) - **Nueva plataforma de documentación**: El sitio de documentación ha migrado a una nueva plataforma, lo que permite actualizaciones de funciones más rápidas y una experiencia de usuario mejorada con búsqueda, navegación y organización de contenido optimizadas. ## Diciembre 2025 \{#december-2025\} - **Documentación de Apple Ads Manager**: Combina los datos de tus campañas de Apple Search Ads con métricas de ingresos en un único dashboard de análisis. La nueva documentación cubre la creación de campañas, la gestión de grupos de anuncios y las formas de hacer seguimiento del ROI de tu inversión publicitaria junto al rendimiento de las suscripciones. [Más información](ads-manager) - **Paywalls web in-app**: Muestra paywalls basados en web dentro de tu app usando un navegador in-app, ofreciendo una experiencia fluida sin redirecciones externas. [iOS](ios-web-paywall#open-web-paywalls-in-an-in-app-browser) | [Android](android-web-paywall#open-web-paywalls-in-an-in-app-browser) | [React Native](react-native-web-paywall#open-web-paywalls-in-an-in-app-browser) | [Flutter](flutter-web-paywall#open-web-paywalls-in-an-in-app-browser) - **Traducción por línea con IA en Paywall Builder**: Selecciona elementos de texto específicos en tu paywall y tradúcelos con ayuda de la IA, lo que hace la localización más precisa y flexible. [Más información](add-paywall-locale-in-adapty-paywall-builder#translating-paywalls-with-ai) - **Segmentos dinámicos**: Crea segmentos de audiencia dinámicos que se actualizan automáticamente en función de ventanas de tiempo móviles. Por ejemplo, crea un segmento para "usuarios que instalaron la app en los últimos 7 días" que se actualice continuamente para mostrar siempre a tus clientes más recientes. [Más información](segments#available-attributes) - **Guías de configuración de campañas en Meta y TikTok**: Documentación paso a paso para crear y hacer seguimiento de campañas en Meta (Facebook e Instagram) y TikTok, con integración de seguimiento de conversiones y analíticas. [Meta](meta-create-campaign) | [TikTok](tiktok-create-campaign) - **Guías de inicio rápido para implementación manual de paywalls**: Implementa compras in-app más rápido con guías paso a paso que muestran cómo integrar el SDK de Adapty en tu UI de paywall personalizada. [iOS](ios-implement-paywalls-manually) | [Android](android-implement-paywalls-manually) | [React Native](react-native-implement-paywalls-manually) | [Flutter](flutter-implement-paywalls-manually) | [Unity](unity-implement-paywalls-manually) | [Kotlin Multiplatform](kmp-quickstart-manual) | [Capacitor](capacitor-quickstart-manual) - **Navegador integrado para los enlaces del onboarding**: Los enlaces externos en los onboardings se abren ahora por defecto en un navegador integrado, manteniendo a los usuarios dentro de la app. Puedes personalizar este comportamiento para usar navegadores externos si lo necesitas. [iOS](ios-present-onboardings#customize-how-links-open-in-onboardings) | [Android](android-present-onboardings#customize-how-links-open-in-onboardings) | [React Native](react-native-present-onboardings#customize-how-links-open-in-onboardings) - **Sugerencias mejoradas de Autopilot**: Autopilot ahora ofrece mejores recomendaciones de optimización de precios basadas en un análisis más detallado de los datos de tu suscripción. [Prueba Autopilot](autopilot) - **Modo oscuro en la documentación**: La documentación ahora es compatible con el modo oscuro, con detección automática de las preferencias del sistema o activación manual desde la esquina superior derecha. --- # File: generate-in-app-purchase-key --- --- title: "Generar la In-App Purchase Key en App Store Connect" description: "Genera una clave de compra in-app para transacciones seguras." --- La **In-App Purchase Key** es una clave de API especializada que se crea en App Store Connect para validar las compras confirmando su autenticidad. :::note Para generar claves de API para la App Store Server API, debes tener el rol de Admin o de Account Holder en App Store Connect. También puedes consultar cómo generar claves de API en la [Documentación para Desarrolladores de Apple](https://developer.apple.com/documentation/appstoreserverapi/creating-api-keys-to-authorize-api-requests). ::: 1. Abre **App Store Connect**. Ve a la sección [**Users and Access** → **Integrations** → **In-App Purchase**](https://appstoreconnect.apple.com/access/integrations/api/subs). 2. Haz clic en el botón de añadir **(+)** junto al título **Active**.
3. En la ventana **Generate In-App Purchase Key** que se abre, introduce el nombre de la clave para tu referencia futura. No se utilizará en Adapty.
4. Haz clic en el botón **Generate**. Una vez que se cierre la ventana **Generate in-App Purchase Key**, verás la clave creada en la lista **Active**.
5. Una vez generada tu clave de API, haz clic en el botón **Download In-App Purchase Key** para obtener la clave como archivo.
6. En la ventana **Download in-App Purchase Key**, haz clic en el botón **Download**. El archivo se guardará en tu ordenador.
Es fundamental mantener este archivo seguro para subirlo al Adapty Dashboard en el futuro. Ten en cuenta que el archivo generado solo se puede descargar una vez, así que asegúrate de guardarlo en un lugar seguro hasta que lo subas. La clave .p8 generada desde la sección **In-App Purchase** se utilizará al [configurar la integración inicial de Adapty con el App Store](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file).
**Próximos pasos:**
- [Configurar la integración con App Store](app-store-connection-configuration)
---
# File: app-store-connection-configuration
---
---
title: "Configurar la integración con App Store"
description: "Configura tu conexión con App Store para un seguimiento de suscripciones sin problemas."
---
3. Copia el **Issuer ID** y pégalo en el campo **In-app purchase Issuer ID** del Adapty Dashboard.
4. Copia el **Key ID** y pégalo en el campo **In-app purchase Key ID** del Adapty Dashboard.
## Paso 3. Sube el archivo In-App Purchase Key \{#step-3-upload-in-app-purchase-key-file\}
Sube el archivo **In-App Purchase Key** que descargaste en la sección [Generar In-App Purchase Key en App Store Connect](generate-in-app-purchase-key)
en el campo **Private key (.p8 file)** del Adapty Dashboard.
## Paso 4. Para pruebas y ofertas especiales – configura las ofertas promocionales \{#step-4-for-trials-and-special-offers--set-up-promotional-offers\}
:::important
Este paso es necesario si tu app tiene [pruebas u otras ofertas promocionales](offers).
:::
1. Copia el mismo Key ID que usaste en el [Paso 2](#step-2-provide-issuer-id-and-key-id) en el campo **Subscription key ID** de la sección **App Store promotional offers**.
2. Sube el mismo archivo **In-App Purchase Key** que usaste en el [Paso 3](#step-3-upload-in-app-purchase-key-file) en el área **Subscription key (.p8 file)** de la sección **App Store promotional offers**.
## Paso 5. Introduce el App Store shared secret \{#step-5-enter-app-store-shared-secret\}
El **App Store shared secret**, también conocido como App Store Connect Shared Secret, es una cadena hexadecimal de 32 caracteres que se usa para las compras in-app y la validación de recibos de suscripciones.
1. Abre [App Store Connect](https://appstoreconnect.apple.com/apps). Selecciona tu app y ve a la sección **General** → **App Information**.
2. Desplázate hacia abajo hasta la subsección **App-Specific Shared Secret**.
:::info
Si la subsección **App-Specific Shared Secret** no aparece, asegúrate de tener el rol de Account Holder o Admin. Si tienes el rol de Admin y aun así no ves la subsección **App-Specific Shared Secret**, pide al Account Holder de la app (la persona que creó la aplicación en App Store Connect) que genere el App Store shared secret para la app. Después de eso, la subsección también será visible para los Admins.
:::
3. Haz clic en el botón **Manage**.
4. En la ventana **App-Specific Shared Secret** que se abre, copia el **Shared Secret**. Si no aparece ningún shared secret, primero haz clic en el botón **Manage** o **Generate** (el que esté disponible) y luego copia el **Shared Secret**.
5. Pega el **Shared Secret** copiado en el campo **App Store shared secret** del Adapty Dashboard.
6. Haz clic en el botón **Save** del Adapty Dashboard para confirmar los cambios.
## Paso 6. Añade la clave API de App Store Connect \{#step-6-add-app-store-connect-api-key\}
Genera una clave API de App Store Connect y añádela a Adapty para poder [gestionar tus productos en el App Store desde el Adapty dashboard](create-product#create-product-and-push-to-store):
1. En App Store Connect, ve a [**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api) y haz clic en **+**.
2. En la ventana **Generate API key**, introduce un nombre para la clave y concédele acceso **Admin**.
3. Haz clic en **Download** junto a tu clave. Ten en cuenta que solo puedes descargarla una vez.
4. En el Adapty dashboard, ve a [**App settings > iOS SDK**](https://app.adapty.io/settings/ios-sdk) y haz clic en **Connect API key**.
5. Rellena los campos de la ventana:
- **Issuer ID**: Cópialo desde [**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api). Está encima de la tabla **API keys**.
- **Key ID**: Cópialo desde [**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api). Está en la tabla **API keys**, junto a tu clave.
- **API key**: Sube el archivo de clave API que descargaste desde App Store Connect.
6. Haz clic en **Connect**.
**Próximos pasos**
- [Habilitar notificaciones del servidor de App Store](enable-app-store-server-notifications)
---
# File: enable-app-store-server-notifications
---
---
title: "Activar notificaciones de servidor de App Store"
description: "Activa las notificaciones de servidor de App Store para rastrear eventos de suscripción en tiempo real."
---
Configurar las notificaciones de servidor de App Store es fundamental para garantizar la precisión de los datos, ya que te permite recibir actualizaciones en tiempo real desde App Store, incluyendo información sobre reembolsos y otros eventos.
:::important
Se requiere Adapty iOS SDK 2.10.0 o posterior para soporte completo de App Store Server Notifications V2.
:::
1. Copia la **URL for App Store server notification** en el Adapty Dashboard.
2. Abre [App Store Connect](https://appstoreconnect.apple.com/apps). Selecciona tu aplicación y ve a la sección **General** → **App Information**, subsección **App Store Server Notifications**.
3. Pega la **URL for App Store server notification** copiada en los campos **Production Server URL** y **Sandbox Server URL**.
## Reenvío de eventos sin procesar \{#raw-events-forwarding\}
En algunos casos, puede que quieras seguir recibiendo eventos S2S sin procesar desde Apple. Para continuar recibiéndolos mientras usas Adapty, simplemente añade tu endpoint al campo **URL for forwarding raw Apple events** y te enviaremos los eventos tal como los recibimos de Apple.
**Siguientes pasos**
Configura el SDK de Adapty para:
- [iOS](sdk-installation-ios)
- [React Native](sdk-installation-reactnative)
- [Flutter](sdk-installation-flutter)
- [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform)
- [Unity](sdk-installation-unity)
---
# File: troubleshoot-app-store-integration
---
---
title: "Solucionar problemas de integración con App Store"
description: "Resuelve los problemas más comunes de configuración con la App Store de Apple: acuerdos pendientes, retrasos en notificaciones del servidor y discrepancias de precios."
---
Este artículo cubre los problemas más comunes de integración con App Store. Cada sección describe los síntomas, la causa raíz y la solución.
## Los productos no aparecen \{#products-dont-appear\}
Dos síntomas distintos apuntan a la misma causa raíz:
- La clave API de App Store Connect está configurada correctamente, pero Adapty no puede obtener los productos.
- Los productos existen en App Store Connect pero no aparecen en Adapty, o aparecen menos de los esperados. El SDK reporta "Product Id not found" al intentar realizar una compra.
La causa más común es que los **acuerdos de Apple estén sin firmar** — el acuerdo de pago, los formularios fiscales o los formularios bancarios en estado pendiente o sin firmar. Cuando los acuerdos están pendientes, la API de App Store Connect devuelve silenciosamente un 403 en los endpoints relacionados con productos. No se muestra ningún error claro en Adapty; los productos simplemente se descartan sin aviso.
Ve a **App Store Connect → Agreements, Tax, and Banking** y firma todos los acuerdos pendientes. Luego vuelve a sincronizar en **App settings → iOS SDK** de Adapty.
## Las notificaciones del servidor de App Store muestran "Delayed" \{#app-store-server-notifications-show-delayed\}
En App Store Connect, el estado de las App Store Server Notifications puede aparecer como **Delayed**. Esto significa que Apple tiene retraso en el envío de notificaciones de eventos de suscripción: renovaciones, cancelaciones y problemas de facturación se acumulan en cola y llegan tarde.
Las estadísticas de instalaciones no se ven afectadas. Adapty contabiliza las instalaciones desde el primer lanzamiento de la app, no a partir de notificaciones del servidor.
Si los datos de renovación o cancelación van por detrás, el estado Delayed es la causa más probable. El estado suele desaparecer automáticamente a medida que Apple procesa el backlog.
## Los precios en Adapty no coinciden con App Store \{#prices-in-adapty-dont-match-app-store\}
El campo **price** en la página de edición de productos de Adapty se comporta de forma distinta según cómo se haya añadido el producto.
Si creas un producto en Adapty y lo publicas en la store desde el dashboard, este precio se utiliza como precio inicial en la store.
Si añades un producto que ya existe en la store, este precio es un marcador de posición. Las analíticas, integraciones y SDK de Adapty utilizan los precios reales obtenidos de App Store, independientemente de este valor. Los cambios en los precios de App Store no se sincronizan para actualizar el marcador de posición, y por ahora no es posible editar ese marcador desde el dashboard.
## La exportación de precios en CSV está vacía \{#csv-price-export-is-empty\}
Si tu exportación de precios en CSV solo devolvió las cabeceras de columna, significa que la clave API de App Store Connect no está completamente configurada. Consulta [Paso 6 — Añadir clave API de App Store Connect](app-store-connection-configuration#step-6-add-app-store-connect-api-key).
## No se pueden publicar nuevos productos en App Store \{#cant-push-new-products-to-app-store\}
Adapty puede publicar nuevos productos en App Store Connect cuando los creas en el dashboard. La opción de publicar queda bloqueada si la integración con App Store no está completamente configurada. Se requieren dos ajustes:
- **Apple app ID**: Configúralo en [Paso 1 — Proporcionar Bundle ID y Apple app ID](app-store-connection-configuration#step-1-provide-bundle-id-and-apple-app-id).
- **App Store Connect API key**: Configúrala en [Paso 6 — Añadir clave API de App Store Connect](app-store-connection-configuration#step-6-add-app-store-connect-api-key).
---
# File: enabling-of-devepoler-api
---
---
title: "Habilitar las APIs de desarrollador en Google Play Console"
description: "Habilita la API de desarrollador de Adapty para automatizar y simplificar la gestión de suscripciones en tu app."
---
3. Abre la página de la [**Google Play Android Developer API**](https://console.cloud.google.com/apis/library/androidpublisher.googleapis.com).
4. Haz clic en el botón **Enable** y espera a que aparezca el estado **Enabled**. Esto indica que la Google Android Developer API está habilitada.
5. Abre la página de la [**Google Play Developer Reporting API**](https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com).
6. Haz clic en el botón **Enable** y espera a que aparezca el estado **Enabled**.
7. Abre la página de la [**Cloud Pub/Sub API**](https://console.cloud.google.com/marketplace/product/google/pubsub.googleapis.com).
8. Haz clic en el botón **Enable** y espera a que aparezca el estado **Enabled**.
Las APIs de desarrollador están habilitadas.
Puedes verificarlo en la página [**APIs & Services**](https://console.cloud.google.com/apis/dashboard) de la Google Cloud Console. Desplázate hacia abajo por la página y comprueba que la tabla al final contiene las 3 APIs:
- Google Play Android Developer API
- Google Play Developer Reporting API
- Cloud Pub/Sub API
**Siguiente paso**
- [Crear una cuenta de servicio en la Google Cloud Console](create-service-account)
---
# File: create-service-account
---
---
title: "Crear una cuenta de servicio en Google Cloud Console"
description: "Aprende a crear una cuenta de servicio para el acceso seguro a la API en Adapty."
---
Para que Adapty pueda automatizar el acceso a los datos, es necesario crear una cuenta de servicio en Google Play Console.
1. Abre la sección [**IAM & Admin** -> **Service accounts**](https://console.cloud.google.com/iam-admin/serviceaccounts) de Google Cloud Console. Asegúrate de estar usando el proyecto correcto.
2. En la ventana **Service accounts**, haz clic en el botón **Create service account**.
3. En la subsección **Service account details** de la ventana **Create service account**, introduce el **Service Account Name** que quieras. Te recomendamos incluir "Adapty" en el nombre para indicar el propósito de esta cuenta. El **Service account ID** se generará automáticamente.
4. Copia la dirección de correo electrónico de la cuenta de servicio y guárdala para usarla más adelante.
5. Haz clic en el botón **Create and continue**.
6. En la lista desplegable **Select a role** de la subsección **Grant this service account access to project**, selecciona **Pub/Sub -> Pub/Sub Admin**. Este rol es necesario para habilitar las notificaciones en tiempo real para desarrolladores.
7. Haz clic en el botón **Add another role**.
8. En la nueva lista desplegable **Role**, selecciona **Monitoring -> Monitoring Viewer**. Este rol es necesario para permitir la monitorización de la cola de notificaciones.
9. Haz clic en el botón **Continue**.
10. Haz clic en el botón **Done** sin realizar ningún cambio. Se abrirá la ventana **Service accounts**.
**Siguiente paso**
- [Conceder permisos a la cuenta de servicio en Google Play Console](grant-permissions-to-service-account)
---
# File: grant-permissions-to-service-account
---
---
title: "Conceder permisos a la cuenta de servicio en la Google Play Console"
description: "Concede permisos a las cuentas de servicio para un acceso seguro y eficiente a la API."
---
Concede los permisos necesarios a la cuenta de servicio que Adapty utilizará para gestionar suscripciones y validar compras.
1. Abre la página [**Users and permissions**](https://play.google.com/console/u/0/developers/8970033217728091060/users-and-permissions) en la Google Play Console y haz clic en el botón **Invite new users**.
2. En la página **Invite user**, introduce el correo electrónico de los usuarios de servicio que has creado.
3. Cambia a la pestaña **Account permissions**.
4. Selecciona los siguientes permisos:
- View app information and download bulk reports (read-only)
- View financial data, orders, and cancellation survey responses
- Manage orders and subscriptions
- Manage store presence
5. Haz clic en el botón **Invite user**.
6. En la ventana **Send invite?**, haz clic en el botón **Send invite**. La cuenta de servicio aparecerá en la lista de usuarios.
**Siguientes pasos**
- [Genera el archivo de clave de la cuenta de servicio en la Google Play Console](create-service-account-key-file)
---
# File: create-service-account-key-file
---
---
title: "Generar el archivo de clave de cuenta de servicio en Google Play Console"
description: "Aprende a crear un archivo de clave de cuenta de servicio para una integración fluida con Adapty."
---
Para vincular tu app móvil en Play Store con Adapty, necesitarás generar archivos especiales de clave de cuenta de servicio en Google Play Console y subirlos a Adapty. Estos archivos ayudan a proteger tu app y evitan accesos no autorizados.
:::warning
Por lo general, la nueva cuenta de servicio tarda al menos 24 horas en activarse. Sin embargo, existe un [truco](https://stackoverflow.com/a/60691844). Tras crear la cuenta de servicio en [Google Play Console](https://play.google.com/apps/publish/), abre cualquier aplicación y ve a **Monetize** -> **Products** -> **Subscriptions/In-app products**. Edita la descripción de cualquier producto y guarda los cambios. Esto debería activar la cuenta de servicio de inmediato, y luego puedes revertir los cambios.
:::
1. Abre la sección [**Service accounts**](https://console.cloud.google.com/iam-admin/serviceaccounts) en Google Play Console. Asegúrate de haber seleccionado el proyecto correcto.
2. En la ventana que se abre, haz clic en **Add key** y elige **Create new key** en el menú desplegable.
3. En la ventana **Create private key for [Your_project_name]**, haz clic en **Create**. Tu clave privada se guardará en tu ordenador como un archivo JSON. Puedes encontrarlo usando el nombre de archivo que aparece en la ventana **Private key saved to your computer**.
4. En la ventana **Create private key for Your_project_name**, haz clic en el botón **Create**. Esta acción guardará tu clave privada en tu ordenador como un archivo JSON. Puedes usar el nombre del archivo que aparece en la ventana **Private key saved to your computer** para localizarlo si lo necesitas.
Necesitarás este archivo cuando [configures la integración con Google Play Store](google-play-store-connection-configuration).
:::warning
Por lo general, la nueva cuenta de servicio tarda al menos 24 horas en activarse. Sin embargo, existe un [truco](https://stackoverflow.com/a/60691844). Tras crear la cuenta de servicio en [Google Play Console](https://play.google.com/apps/publish/), abre cualquier aplicación y ve a **Monetize** -> **Products** -> **Subscriptions/In-app products**. Edita la descripción de cualquier producto y guarda los cambios. Esto debería activar la cuenta de servicio de inmediato, y luego puedes revertir los cambios.
:::
**Siguientes pasos**
- [Configurar la integración con Google Play Store](google-play-store-connection-configuration)
---
# File: google-play-store-connection-configuration
---
---
title: "Configurar la integración con Google Play Store"
description: "Configura la conexión con Google Play Store en Adapty para gestionar las compras in-app sin problemas."
---
Esta sección describe el proceso de integración de tu aplicación móvil distribuida a través de Google Play con Adapty. Tendrás que introducir los datos de configuración de tu app desde la Play Store en el Adapty Dashboard. Este paso es fundamental para validar las compras y recibir actualizaciones de suscripciones desde la Play Store dentro de Adapty.
Puedes completar este proceso durante el onboarding inicial o realizar cambios posteriormente en los **App Settings** del Adapty Dashboard.
:::danger
Los cambios de configuración solo son válidos antes de publicar tu aplicación móvil con los paywalls de Adapty integrados. Modificar la configuración tras el lanzamiento romperá la integración y los paywalls dejarán de mostrarse en tu aplicación.
:::
## Paso 1. Proporciona el Package name \{#step-1-provide-package-name\}
El Package name es el identificador único de tu app en Google Play Store. Es necesario para el funcionamiento básico de Adapty, como el procesamiento de suscripciones.
1. Abre la [Google Play Developer Console](https://play.google.com/console/u/0/developers).
2. Selecciona la app cuyo ID necesitas. Se abrirá la ventana **Dashboard**.
3. Busca el ID del producto bajo el nombre de la aplicación y cópialo.
4. Abre los [**App settings**](https://app.adapty.io/settings/android-sdk) desde el menú superior de Adapty.
5. En la pestaña **Android SDK** de la ventana **App settings**, pega el **Package name** copiado.
## Paso 2. Sube el archivo de clave de cuenta \{#step-2-upload-the-account-key-file\}
1. Sube el archivo de clave privada de cuenta de servicio en formato JSON que creaste en el paso [Crear archivo de clave de cuenta de servicio](create-service-account) en el área **Service account key file**.
No olvides hacer clic en el botón **Save** para confirmar los cambios.
**Próximos pasos**
- [Activar las notificaciones en tiempo real para desarrolladores (RTDN) en la Google Play Console](enable-real-time-developer-notifications-rtdn)
---
# File: enable-real-time-developer-notifications-rtdn
---
---
title: "Habilitar notificaciones en tiempo real para desarrolladores (RTDN) en Google Play Console"
description: "Mantente informado sobre eventos críticos y garantiza la exactitud de los datos habilitando las Notificaciones en Tiempo Real para Desarrolladores (RTDN) en Google Play Console para Adapty. Aprende a configurar RTDN para recibir actualizaciones instantáneas sobre reembolsos y otros eventos importantes de la Play Store"
---
Configurar las notificaciones en tiempo real para desarrolladores (RTDN) es fundamental para garantizar la exactitud de los datos, ya que te permite recibir actualizaciones al instante desde la Play Store, incluyendo información sobre reembolsos y otros eventos.
## Habilitar notificaciones \{#enable-notifications\}
1. Asegúrate de tener **Google Cloud Pub/Sub** habilitado. Abre [este enlace](https://console.cloud.google.com/flows/enableapi?apiid=pubsub) y selecciona el proyecto de tu app. Si todavía no has habilitado **Google Cloud Pub/Sub**, debes hacerlo aquí.
2. Ve a [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) desde el menú superior de Adapty y copia el contenido del campo **Enable Pub/Sub API** que aparece junto al título **Google Play RTDN topic name**.
:::note Si el contenido del campo **Enable Pub/Sub API** tiene un formato incorrecto (el formato correcto empieza por `projects/...`), consulta la sección [Corregir el formato incorrecto en el campo Enable Pub/Sub API](enable-real-time-developer-notifications-rtdn#fixing-incorrect-format-in-enable-pubsub-api-field) para obtener ayuda. ::: 3. Abre la [Google Play Console](https://play.google.com/console/), elige tu app y ve a **Monetize with Play** -> **Monetization setup**. En la sección **Google Play Billing**, marca la casilla **Enable real-time notifications**. 4. Pega el contenido del campo **Enable Pub/Sub API** que copiaste en los **App Settings** de Adapty en el campo **Topic name**. 5. Haz clic en **Save changes** en la Google Play Console.
## Probar las notificaciones \{#test-notifications\}
Para comprobar si te has suscrito correctamente a las notificaciones en tiempo real para desarrolladores:
1. Guarda los cambios en la configuración de Google Play Console.
2. Debajo del campo **Topic name** en Google Play Console, haz clic en **Send test notification**.
3. Ve a [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) en Adapty. Si se ha enviado una notificación de prueba, verás su estado encima del nombre del topic.
## Corregir el formato incorrecto en el campo Enable Pub/Sub API \{#fixing-incorrect-format-in-enable-pubsub-api-field\}
Si el contenido del campo **Enable Pub/Sub API** tiene un formato incorrecto (el formato correcto empieza por `projects/...`), sigue estos pasos para solucionar el problema:
### 1. Verificar la habilitación de la API y los permisos \{#1-verify-api-enablement-and-permissions\}
Comprueba detenidamente que todas las APIs necesarias estén habilitadas y que los permisos estén correctamente concedidos a la cuenta de servicio. Aunque ya hayas completado estos pasos, es importante revisarlos de nuevo para asegurarte de que no se omitió ninguno. Repite los pasos de las siguientes secciones:
1. [Habilitar las APIs de desarrollador en Google Play Console](enabling-of-devepoler-api)
2. [Crear una cuenta de servicio en Google Cloud Console](create-service-account)
3. [Conceder permisos a la cuenta de servicio en Google Play Console](grant-permissions-to-service-account)
4. [Generar el archivo de clave de la cuenta de servicio en Google Play Console](create-service-account-key-file)
5. [Configurar la integración con Google Play Store](google-play-store-connection-configuration)
### 2. Ajustar las políticas de dominio \{#2-adjust-domain-policies\}
Cambia las políticas **Domain restricted contacts** y **Domain restricted sharing**:
1. Abre la [Google Cloud Console](https://console.cloud.google.com/) y selecciona el proyecto donde creaste la cuenta de servicio para gestionar tu app.
2. En la sección **Quick Access**, elige **IAM & Admin**.
3. En el panel izquierdo, elige **Organization Policies**.
4. Busca la política **Domain restricted contacts**.
5. Haz clic en el botón de puntos suspensivos en la columna **Actions** y elige **Edit policy**.
6. En la ventana de edición de la política:
1. En **Policy source**, selecciona el botón de opción **Override parent's policy**.
2. En **Policy enforcement**, selecciona el botón de opción **Replace**.
3. En **Rules**, haz clic en el botón **ADD A RULE**.
4. En **New rule** -> **Policy values**, elige **Allow All**.
5. Haz clic en **SET POLICY**.
7. Repite los pasos 4-6 para la política **Domain restricted sharing**.
Por último, vuelve a generar el contenido del campo **Enable Pub/Sub API** situado junto al título **Google Play RTDN topic name**. El campo tendrá ahora el formato correcto.
Asegúrate de cambiar **Policy source** de vuelta a **Inherit parent's policy** para las políticas actualizadas una vez que hayas habilitado correctamente las Notificaciones en Tiempo Real para Desarrolladores (RTDN).
## Reenvío de eventos sin procesar \{#raw-events-forwarding\}
En algunos casos, puede que quieras seguir recibiendo eventos S2S sin procesar de Google. Para continuar recibiéndolos mientras usas Adapty, simplemente añade tu endpoint en el campo **URL for forwarding raw Google events** y enviaremos los eventos tal cual los recibimos de Google.
---
**Próximos pasos**
Configura el SDK de Adapty para:
- [Android](sdk-installation-android)
- [React Native](sdk-installation-reactnative)
- [Flutter](sdk-installation-flutter)
- [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform)
- [Unity](sdk-installation-unity)
---
# File: stripe
---
---
title: "Integración inicial con Stripe"
description: "Integra Stripe con Adapty para gestionar pagos de suscripciones sin problemas."
---
Adapty admite flujos de suscripción web2app rastreando pagos y suscripciones web realizados a través de [Stripe](https://stripe.com/).
Esta integración cubre compras iniciadas en la web (Stripe Checkout, páginas de pago alojadas o flujos web personalizados) y las sincroniza con el acceso a la app móvil y con los datos de analítica.
Es útil en los siguientes escenarios:
- Proporcionar automáticamente acceso a funciones de pago a usuarios que compraron en la web y después instalaron la app e iniciaron sesión en su cuenta
- Centralizar toda la analítica de suscripciones en un único Adapty Dashboard (incluidas cohortes, predicciones y el resto de las herramientas de analítica)
Aunque las compras web son cada vez más populares para las apps, la Apple App Store solo permite un sistema diferente al de las compras in-app para bienes digitales en Estados Unidos. Asegúrate de no promocionar tus suscripciones web dentro de la app en otros países, ya que podrías recibir un rechazo o un baneo.
A continuación se describen los pasos para configurar la integración con Stripe.
:::important
Esta integración se centra en rastrear y sincronizar compras web de Stripe. Si necesitas redirigir a los usuarios desde la app a un checkout web, consulta [Paywalls web](web-paywall).
:::
## 1\. Conectar Stripe a Adapty \{#1-connect-stripe-to-adapty\}
Esta integración se basa principalmente en que Adapty obtenga datos de suscripciones de Stripe a través del webhook. Por eso, debes conectar tu cuenta de Adapty a tu cuenta de Stripe proporcionando las API Keys y usando la URL del webhook de Adapty en Stripe. Para automatizar la configuración del webhook, instala la app de Adapty en Stripe:
:::note
Los pasos a continuación son los mismos para los modos de Producción y Test de Stripe, pero deberás usar diferentes API keys para cada uno.
:::
0. Decide si vas a conectar Stripe en modo test o en modo live. Si lo haces primero en modo test, deberás repetir los pasos a continuación para el modo live.
1. Ve al [Stripe App Marketplace](https://marketplace.stripe.com/apps/adapty) e instala la app de Adapty. Ten en cuenta que el modo sandbox no permite instalar apps; solo puedes hacerlo en modo de producción o test.
2. Concede a la app los permisos necesarios. Esto permitirá a Adapty acceder a los datos e historial de suscripciones. Luego haz clic en **Continue to app settings** para continuar.
En la parte inferior del pop-up de permisos puedes elegir si instalar la app en modo live o test.
3. En el pop-up, genera una nueva clave restringida. Deberás verificar tu identidad mediante tu correo electrónico, Touch ID o clave de seguridad. Una vez generada la clave, no podrás volver a verla, así que guárdala de forma segura en un gestor de contraseñas o un almacén de secretos.
4. Copia la clave generada del pop-up y ve a [App Settings → Stripe](https://app.adapty.io/settings/stripe) en Adapty. Pega la clave en la sección **Stripe App Restricted API Key** según tu modo. Ten en cuenta que debes generar claves diferentes para los modos test y live.
¡Listo! A continuación, crea tus productos en Stripe y agrégalos a Adapty.
2. Haz clic en el botón **Reveal live (test) key button** junto al título **Secret key**, cópiala y ve a [App Settings → Stripe](https://app.adapty.io/settings/stripe) en Adapty. Pega la clave aquí:
3. A continuación, copia la Webhook URL de la parte inferior de la misma página en Adapty. Ve a [**Developers** → **Webhooks**](https://dashboard.stripe.com/webhooks) en Stripe y haz clic en el botón **Add endpoint**:
4. Pega la URL del webhook de Adapty en el campo **Endpoint URL**. Luego elige **Latest API version** en el campo **Version** del webhook. A continuación, selecciona los siguientes eventos:
- charge.refunded
- customer.subscription.created
- customer.subscription.deleted
- customer.subscription.paused
- customer.subscription.resumed
- customer.subscription.updated
- invoice.created
- invoice.updated
- payment_intent.succeeded
5. Pulsa "Add endpoint" y luego "Reveal" bajo "Signing secret". Esta es la clave que se usa para decodificar los datos del webhook en Adapty; cópiala tras revelarla:
6. Por último, pega esta clave en App Settings → Stripe de Adapty, bajo "Stripe Webhook Secret":
:::warning
Por el momento, Adapty solo admite precios de tipo **Flat rate** ($9,99/mes) o **Package pricing** ($9,99/10 unidades), ya que se comportan de forma similar a los stores de apps. Las opciones **Tiered pricing**, **Usage-based fee** y **Customer chooses price** no están soportadas.
:::
## 3\. Añadir productos de Stripe a Adapty \{#3-add-stripe-products-to-adapty\}
:::warning
¡Los productos son obligatorios! Asegúrate de crear tus productos de Stripe en el Adapty Dashboard. Adapty solo rastrea eventos para transacciones vinculadas a estos productos, así que no omitas este paso; de lo contrario, no se crearán eventos de transacción.
:::
Tratamos Stripe igual que App Store y Google Play: es simplemente otro store donde vendes tus productos digitales. Por eso se configura de forma similar: añade los productos de Stripe (concretamente su `product_id` y `price_id`) en la sección de Productos de Adapty:
Los IDs de producto en Stripe tienen el formato `prod_...` y los IDs de precio `price_...`. Son fáciles de encontrar para cada producto en el [Catálogo de productos](https://dashboard.stripe.com/products?active=true) de Stripe, una vez que abres cualquier producto:
Una vez añadidos todos los productos necesarios, el siguiente paso es informar a Stripe sobre qué usuario está realizando la compra, para que Adapty pueda identificarlo.
## 4\. Enriquecer las compras web con tu ID de usuario \{#4-enrich-purchases-made-on-the-web-with-your-user-id\}
Adapty se basa en los webhooks de Stripe como única fuente de información para otorgar y actualizar los niveles de acceso de los usuarios. Pero debes proporcionar información adicional desde tu lado cuando trabajas con Stripe para que esta integración funcione correctamente.
Para que los niveles de acceso sean consistentes entre plataformas (web o móvil), debes asegurarte de que haya un único ID de usuario en el que Adapty pueda basarse al reconocer los webhooks. Puede ser el correo electrónico, el número de teléfono o cualquier otro ID del sistema de autenticación que utilices.
Decide qué ID quieres usar para identificar a tus usuarios. Luego, accede a la parte de tu código que inicializa el pago a través de Stripe y añade este ID de usuario al objeto `metadata` de la [Suscripción de Stripe](https://docs.stripe.com/api/subscriptions/object#subscription_object-metadata) (`sub_...`) o del objeto [Checkout Session](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-metadata) (`ses_...`) con la clave `customer_user_id`, así:
```json showLineNumbers title="Stripe Metadata contents"
{'customer_user_id': "YOUR_USER_ID"}
```
Esta simple adición es lo único que tienes que hacer en tu código. Después de eso, Adapty procesará todos los webhooks que reciba de Stripe, extraerá este `metadata` y asociará correctamente las suscripciones con tus clientes.
:::warning
El ID de usuario es obligatorio
De lo contrario, no tenemos forma de identificar a este usuario y otorgarle el nivel de acceso en el móvil.
Si no proporcionas `customer_user_id` en el `metadata`, tendrás la opción de hacer que Adapty busque `customer_user_id` en otros lugares: bien en el campo `email` del objeto Customer de Stripe, o bien en el `client_reference_id` de la Session de Stripe.
Más información sobre cómo configurar el comportamiento de creación de perfiles [más abajo](stripe#profile-creation-behavior).
:::
:::note
El Customer en Stripe también es obligatorio
Si usas Checkout Sessions, [asegúrate de que estás creando un Customer de Stripe](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-customer_creation) estableciendo `customer_creation` en `always`.
:::
## 5\. Dar acceso a los usuarios en el móvil \{#5-provide-access-to-users-on-the-mobile\}
Para asegurarte de que tus usuarios móviles que llegan desde la web puedan acceder a las funciones de pago, simplemente llama a `Adapty.activate()` o `Adapty.identify()` con el mismo `customer_user_id` que proporcionaste en el paso anterior (consulta
2. Dale un nombre a la clave y establece la fecha de expiración. Para que la clave API funcione con Adapty, necesitas concederle el permiso **Read** para todas las entidades. Haz clic en **Save**.
3. Haz clic en **Copy key**.
4. En Adapty, ve a [App Settings → Paddle](https://app.adapty.io/settings/paddle) y pega la clave en la sección **Paddle API key**.
:::warning
Si estableciste una fecha de vencimiento para tu clave de API de Paddle, debes generar manualmente una nueva clave y actualizarla en Adapty antes de que expire. La integración dejará de funcionar sin previo aviso cuando la clave caduque, y los usuarios no podrán realizar compras.
:::
### 1.2. Añadir eventos que se enviarán a Adapty \{#add-events-that-will-be-sent-to-adapty\}
1. Copia la **Webhook URL** de la misma página de **Paddle** en Adapty.
2. En Paddle, ve a [**Developer Tools → Notifications**](https://vendors.paddle.com/notifications-v2) y haz clic en **New destination** para añadir un webhook.
3. Introduce un nombre descriptivo para el webhook. Te recomendamos incluir "Adapty" en él para que puedas encontrarlo fácilmente cuando lo necesites.
4. Pega la **Webhook URL** de Adapty en el campo **URL**. Asegúrate de usar el webhook para el entorno correcto.
5. Establece **Notification type** en **Webhook**.
6. Selecciona los siguientes eventos:
- `subscription.created`
- `subscription.updated`
- `transaction.created`
- `transaction.updated`
- `adjustment.created`
- `adjustment.updated`
7. Haz clic en **Save destination** para finalizar la configuración del webhook.
### 1.3. Obtener y añadir la clave secreta del webhook \{#retrieve-and-add-the-webhook-secret-key\}
1. En la ventana **Notifications**, haz clic en los tres puntos junto al webhook que acabas de crear y selecciona **Edit destination**.
2. Aparecerá un nuevo campo llamado **Secret key** en el panel **Edit destination**. Cópialo.
3. En Adapty, ve a [App Settings → Paddle](https://app.adapty.io/settings/paddle) y pega la clave en el campo **Notification secret key**. Esta clave se usa para verificar los datos del webhook en Adapty.
### 1.4. Vincula los clientes de Paddle con los perfiles de Adapty \{#14-match-paddle-customers-with-adapty-profiles\}
Adapty necesita vincular cada compra a un [perfil de cliente](profiles-crm) para que pueda usarse en tu app. De forma predeterminada, los perfiles se crean automáticamente cuando Adapty recibe webhooks de Paddle. Puedes elegir qué valor usar como `customer_user_id` en Adapty:
1. **Predeterminado y recomendado:** El `customer_user_id` que pasas en el campo `custom_data` (ver [documentación de Paddle](https://developer.paddle.com/build/transactions/custom-data))
2. El `email` del objeto Paddle Customer (ver [documentación de Paddle](https://developer.paddle.com/paddle-js/methods/paddle-checkout-open/#parameters))
3. El ID de cliente de Paddle en formato `ctm-...` (ver [documentación de Paddle](https://developer.paddle.com/paddle-js/methods/paddle-checkout-open/#parameters))
4. No crear perfiles. Elige esta opción si quieres tener mayor control sobre los perfiles de tus clientes y gestionarlos tú mismo.
Puedes configurar qué valor usar en el campo **Profile creation behavior** en [App Settings → Paddle](https://app.adapty.io/settings/paddle).
## 2. Añade productos de Paddle a Adapty \{#2-add-paddle-products-to-adapty\}
:::warning
Asegúrate de añadir tus productos de Paddle al Adapty Dashboard o de agregar un ID de producto de Paddle a tus productos existentes. Adapty solo registra eventos para transacciones vinculadas a estos productos. Si omites este paso, no se crearán eventos de transacción.
:::
Paddle funciona en Adapty igual que App Store y Google Play: es otra plataforma donde vendes productos digitales. Para configurarlo, añade los valores de `product_id` y `price_id` correspondientes de Paddle en la sección [Products](https://app.adapty.io/products) de Adapty.
En Paddle, los IDs de producto tienen el formato `pro_...` y los IDs de precio `pri_...`. Los encontrarás en tu [catálogo de productos de Paddle](https://vendors.paddle.com/products-v2) una vez que abras un producto específico:
Una vez añadidos tus productos, el siguiente paso es asegurarte de que Adapty pueda vincular la compra al usuario correcto.
## 3\. Dar acceso a los usuarios en el móvil \{#provide-access-to-users-on-the-mobile\}
Para asegurarte de que los usuarios que compran en la web obtengan acceso en el móvil, llama a `Adapty.activate()` o `Adapty.identify()` usando el mismo `customer_user_id` que pasaste al realizar la compra. Consulta [Identificar usuarios](identifying-users) para más detalles.
## 4\. Probar tu integración \{#test-your-integration\}
Una vez que todo esté configurado, puedes probar tu integración. Las transacciones realizadas en el entorno de Test de Paddle aparecerán como **Test** en Adapty. Las transacciones del entorno de Producción aparecerán como **Production**.
Tu integración ya está completa. Los usuarios pueden comprar suscripciones en tu sitio web y acceder automáticamente a las funciones premium en tu aplicación móvil, mientras tú haces seguimiento de todos los análisis de suscripciones desde tu Adapty Dashboard unificado.
## Consideraciones importantes \{#important-considerations\}
- En las analíticas de Adapty, los importes de las transacciones incluyen impuestos y comisiones de Paddle, lo que difiere del dashboard de Paddle, donde los importes se muestran después de impuestos y comisiones. Esto significa que las cifras que ves en Adapty serán más altas que las de tu dashboard de Paddle.
- A diferencia de otros stores, los reembolsos en Paddle solo afectan a la transacción específica que se reembolsa y no cancelan automáticamente la suscripción. La suscripción seguirá activa a menos que se cancele de forma explícita.
- También puedes incluir `variation_id` en el campo `custom_data` para atribuir compras a instancias de paywall específicas. Adapty procesará estos datos desde los webhooks y los incluirá en las analíticas.
### Períodos de prueba de pago \{#paid-trials\}
Al trabajar con períodos de prueba de pago en Paddle, necesitas crear dos productos en Adapty:
1. Crea un producto que no sea suscripción y vincúlalo al precio de Paddle que cobra por el período de prueba.
2. Luego crea un producto de suscripción (mensual, semanal, etc.) y vincúlalo al precio de Paddle que tiene el componente de prueba gratuita.
Desde el punto de vista de Paddle, se trata de un único producto con dos precios en una sola transacción: un precio para el cargo del período de prueba (p. ej., $0,99) y otro precio para la prueba gratuita ($0,00).
Desde la perspectiva de Adapty, esto genera dos eventos separados: una compra única por el pago de la prueba y un evento de inicio de prueba para el producto de suscripción.
Por ejemplo, cuando un usuario inicia una prueba de pago de $0,99 para una suscripción de $9,99/mes, Paddle crea una sola transacción con ambos precios, mientras que Adapty lo procesa como una compra única de $0,99 (pago inmediato) y un evento de inicio de prueba a $0,00 (suscripción futura a $9,99/mes).
:::note
Cuando los usuarios cancelan una prueba de pago, recibirás los eventos **Trial expired** y **Trial renewal canceled**.
:::
## Saca más partido a tus datos de Paddle \{#get-more-from-your-paddle-data\}
:::important
Para que tus eventos de Paddle funcionen con las integraciones, tus usuarios deben haber iniciado sesión en la app con su cuenta de App Store/Google Play al menos una vez.
:::
Una vez que te integres con Paddle, Adapty está listo para ofrecer información de inmediato. Para aprovechar al máximo tus datos de Paddle, puedes configurar integraciones adicionales de Adapty para reenviar eventos de Paddle, centralizando todos tus análisis de suscripciones en un único Adapty Dashboard.
Integraciones que puedes usar para reenviar y analizar tus eventos de Paddle:
- [AppsFlyer](appsflyer)
- [Webhook](webhook)
- [Posthog](posthog)
## Limitaciones actuales \{#current-limitations\}
- **Cancelaciones**: Paddle tiene dos opciones de cancelación de suscripción:
1. Cancelación inmediata: La suscripción se cancela de inmediato.
2. Cancelación al final del período: La suscripción se cancela al final del período de facturación actual (similar a las suscripciones in-app en los stores).
- **Reembolsos**: Adapty registra los reembolsos totales y parciales.
- **Período de gracia**: Por defecto, Paddle aplica un período de gracia fijo de 30 días para problemas de facturación, durante el cual la suscripción permanece activa. Puedes [personalizar la duración del período de gracia y la acción al final del mismo (pausar o cancelar la suscripción)](https://developer.paddle.com/build/retain/configure-payment-recovery-dunning#prerequisites).
**Pruebas**: Si el cobro falla al finalizar una prueba, el estado de la suscripción cambia a `past_due`. En producción, Paddle Retain aplica una ventana de gestión de impagos para intentar recuperar el pago antes de cancelar o pausar la suscripción. En sandbox, Retain no está disponible, por lo que no se realizan reintentos de pago y la suscripción permanece en `past_due` indefinidamente.
---
**Ver también:**
- [Validar una compra en Paddle, obtener un nivel de acceso e importar el historial de transacciones desde Paddle con la API del lado del servidor](api-adapty/operations/validatePaddlePurchase)
---
# File: custom-store
---
---
title: "Integración inicial con otras stores"
description: "Integración inicial de Adapty con App Store: Guía rápida"
---
¡Nos alegra mucho tenerte con nosotros en Adapty! Nuestra prioridad es ayudarte a ponerte en marcha cuanto antes y obtener los mejores resultados posibles para tu app.
La integración inicial solo es necesaria para [App Store](initial_ios), [Google Play](initial-android), [Stripe](stripe) y [Paddle](paddle), ya que Adapty verifica tus apps, productos y ofertas con estas stores.
Adapty no valida datos con otras app stores ni procesa las compras realizadas a través de ellas. Sin embargo, puedes marcar los productos vendidos en otras stores para que Adapty conceda acceso al contenido de pago tras una compra exitosa, refleje las transacciones en tus analíticas y las comparta mediante integraciones.
:::important Asegúrate de que tu backend procese la compra y envíe la transacción a Adapty mediante la [API server-side de Adapty](getting-started-with-server-side-api). Adapty solo concederá acceso, disparará un evento de transacción, lo enviará a las integraciones y lo reflejará en las analíticas una vez que se reciba la transacción. ::: Para marcar un producto como vendido a través de una app store personalizada, selecciona la app store al crear el producto. Si la store que necesitas no aparece en la lista, así es como puedes crearla: 1. En la página **Products**, abre el producto que quieres vender a través de una app store personalizada. 2. Elige la app store a través de la que quieres vender. Si no aparece en la lista, haz clic en el botón **Create Custom Store**.
3. Introduce el **Title** y el **Store ID** de la store.
4. Haz clic en el botón **Create store**.
Si tu backend está configurado correctamente, Adapty recibirá las transacciones de productos de esta store personalizada, las reflejará en las analíticas, en el [**Event Feed**](event-feed) y en las [integraciones](https://app.adapty.io/integrations), y concederá acceso según corresponda.
## Saca más partido a los datos de tu store personalizada \{#get-more-from-your-custom-store-data\}
:::important
Para que los eventos de tu store personalizada funcionen con las integraciones, tus usuarios deben haber iniciado sesión en la app con su cuenta de App Store/Google Play al menos una vez.
:::
Una vez que configures la integración con tu store personalizada, Adapty está listo para ofrecerte información de inmediato. Para aprovechar al máximo tus datos, puedes configurar integraciones adicionales de Adapty para reenviar los eventos de la store personalizada y reunir todas tus analíticas de suscripciones en un único Adapty Dashboard.
Integraciones que puedes usar para reenviar y analizar los eventos de tu store personalizada:
- [AppsFlyer](appsflyer)
- [Webhook](webhook)
- [Posthog](posthog)
---
# File: transfer-apps
---
---
title: "Transferir tu app a una cuenta diferente"
description: "Cambia el propietario de la app en Adapty"
---
Transfiere tu app a un propietario diferente cuando tu empresa sea adquirida, estés vendiendo tu app o reorganizando entidades empresariales. El proceso de transferencia implica coordinar cambios en Adapty, App Store Connect y Google Play Console para garantizar la continuidad del servicio.
## Transferir la propiedad de la app \{#transfer-app-ownership\}
Completa primero la transferencia en la store y luego transfiere la app en Adapty. Este orden garantiza que las compras sigan funcionando durante toda la transición.
:::note
No elimines ni vuelvas a crear productos durante el proceso de transferencia. No cambies los IDs de los productos hasta después de verificar que la transferencia se completó correctamente.
:::
### Transferencia en App Store (iOS) \{#app-store-ios-transfer\}
:::important
Las claves de la API de App Store Connect (Issuer ID, Key ID, archivo .p8) están vinculadas a la cuenta, no a la app. Tras la transferencia, debes generar nuevas claves de API desde la cuenta del nuevo propietario y actualizarlas en Adapty.
:::
1. **Nuevo propietario:** Crea una cuenta en Adapty en [app.adapty.io](https://app.adapty.io) si aún no tienes una.
2. **Propietario anterior:** Inicia la transferencia de la app en App Store Connect siguiendo la [guía de transferencia](https://developer.apple.com/help/app-store-connect/transfer-an-app/overview-of-app-transfer) de Apple.
3. **Nuevo propietario:** Acepta la transferencia en App Store Connect.
4. **Propietario anterior:** Envía un correo a [support@adapty.io](mailto:support@adapty.io) para transferir la app en Adapty. Indica el nombre de la app y la dirección de correo electrónico del nuevo propietario.
5. **Nuevo propietario:** Tras recibir la app en Adapty, completa la [guía de integración de App Store](initial_ios) para generar y configurar todas las credenciales desde tu cuenta.
### Transferencia en Google Play (Android) \{#google-play-android-transfer\}
1. **Nuevo propietario:** Crea una cuenta en Adapty en [app.adapty.io](https://app.adapty.io) si aún no tienes una.
2. **Ambos propietarios:** Asegúrate de que ambas cuentas de desarrollador de Google Play estén completamente registradas.
3. **Propietario anterior:** Envía una solicitud de transferencia a través de Google Play Console o del soporte para desarrolladores de Google Play. Google puede solicitar documentación adicional como números DUNS, contratos o prueba de venta.
4. **Nuevo propietario:** Revisa y aprueba la solicitud de transferencia.
5. **Google:** El equipo de soporte de Google procesa la transferencia, normalmente en unos pocos días hábiles, aunque puede tardar más según la verificación de la cuenta, la complejidad de las suscripciones y la configuración de pagos.
6. **Propietario anterior:** Una vez que Google complete la transferencia, envía un correo a [support@adapty.io](mailto:support@adapty.io) para transferir la app en Adapty. Indica el nombre de la app y la dirección de correo electrónico del nuevo propietario.
7. **Nuevo propietario:** Tras recibir la app en Adapty, completa la [guía de integración de Google Play](initial-android) para generar y configurar todas las credenciales desde tu cuenta.
La transferencia incluye usuarios, suscripciones, estadísticas, valoraciones y la ficha de la store. La continuidad de facturación se mantiene para los suscriptores existentes, pero los pagos pasan a la cuenta de comerciante del nuevo propietario solo después de que se complete la transferencia. Los informes de pagos y los pedidos anteriores a la transferencia permanecen en la cuenta original. Consulta la [guía de transferencia](https://support.google.com/googleplay/android-developer/answer/6230247) de Google para conocer los requisitos detallados.
## Mitigación de riesgos y tiempos \{#risk-mitigation-and-timing\}
**Lo que sigue funcionando durante la transferencia:**
- Compras (el shared secret de la app valida los recibos)
- Renovaciones (el shared secret sigue siendo válido)
- Acceso de los suscriptores existentes
- El SDK sigue funcionando
**Lo que deja de funcionar temporalmente:**
- Llamadas a la API de App Store Connect (hasta que se configuren las nuevas claves)
- Notificaciones del servidor (hasta que se reconfigure el endpoint)
- Los análisis pueden tener huecos durante la transición de credenciales
**Momento recomendado:**
- Realiza las transferencias en períodos de poco tráfico (entre las 3 a.m. y las 6 a.m. en la zona horaria principal de tus usuarios)
- Ten al nuevo propietario listo para configurar las credenciales inmediatamente después de aceptar la transferencia en la store
- Reserva entre 15 y 30 minutos entre la aceptación de la transferencia y la finalización de la integración con Adapty
**Tras completar la transferencia:**
- Verifica la validación de recibos de inmediato
- Supervisa las tasas de éxito de la renovación automática durante 48 horas
- Comprueba que las notificaciones del servidor están llegando a tus sistemas
- Verifica que las nuevas compras se están registrando correctamente
## Verificar que la transferencia se completó correctamente \{#verify-transfer-completed-successfully\}
Tras completar tanto la transferencia en Adapty como en la store:
1. **Comprobar el acceso al Dashboard**: El nuevo propietario debe ver la app en su Adapty Dashboard.
2. **Verificar la conexión de la clave de API**: Comprueba que la nueva clave de API de App Store Connect o la cuenta de servicio de Google Play se conecta correctamente en Adapty.
3. **Probar la conexión del SDK**: Ejecuta tu app y verifica que el SDK de Adapty se inicializa sin errores.
---
# File: installation-of-adapty-sdks
---
---
title: "Instalación del SDK de Adapty"
description: "Instala los SDKs de Adapty para iOS, Android y apps multiplataforma."
---
Tienes tres formas de empezar según tus preferencias:
- **Sigue las guías de inicio rápido por plataforma**: Las guías incluyen fragmentos de código listos para producción, así que la implementación no lleva mucho tiempo.
- [iOS](ios-sdk-overview)
- [Android](android-sdk-overview)
- [React Native](react-native-sdk-overview)
- [Flutter](flutter-sdk-overview)
- [Unity](unity-sdk-overview)
- [Kotlin Multiplatform](kmp-sdk-overview)
- [Capacitor](capacitor-sdk-overview)
- **Usa LLMs**: Nuestra documentación es compatible con LLMs. Lee nuestra [guía](adapty-cursor) sobre cómo sacar el máximo partido a los LLMs con la documentación de Adapty.
- **Explora las apps de ejemplo**:
- [iOS (Swift)](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples)
- [Android (Kotlin)](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app)
- [React Native (Ejemplo básico en RN puro)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/BasicExample)
- [React Native (Ejemplo avanzado – útil para desarrollo, ya que permite trabajar con casos más complejos)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/AdaptyDevtools)
- [React Native (Build de desarrollo con Expo)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo)
- [React Native (Expo Go y Web)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock)
- [Flutter (Dart)](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example)
- [Unity (C#)](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets)
- [Kotlin Multiplatform](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example)
- [Capacitor](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples)
---
# File: sample-apps
---
---
title: "Apps de ejemplo"
description: ""
---
Para ayudarte a empezar con el SDK de Adapty, hemos preparado apps de ejemplo que muestran cómo integrar y usar sus funciones principales. Estas apps incluyen implementaciones listas para usar de paywalls, compras y seguimiento de analíticas.
## ¿Por qué usar las apps de ejemplo? \{#why-use-sample-apps\}
- **Integración rápida:** Descubre cómo funciona el SDK de Adapty en una app real.
- **Buenas prácticas:** Sigue los patrones de implementación recomendados.
- **Depuración y pruebas:** Usa las apps de ejemplo para resolver problemas y experimentar antes de integrar Adapty en tu propio proyecto.
## Apps de ejemplo disponibles \{#available-sample-apps\}
- [iOS (Swift)](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples)
- [Android (Kotlin)](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app)
- [React Native (Ejemplo básico en RN puro)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/BasicExample)
- [React Native (Ejemplo avanzado — útil para desarrollo, ya que permite trabajar con casos más complejos)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/AdaptyDevtools)
- [React Native (Expo dev build)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo)
- [React Native (Expo Go & Web)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock)
- [Flutter (Dart)](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example)
- [Unity (C#)](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets)
- [Kotlin Multiplatform](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example)
- [Capacitor (React)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-react-example)
- [Capacitor (Vue.js)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-vue-example)
- [Capacitor (Angular)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-angular-example)
- [Capacitor (Herramientas de desarrollo avanzadas)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/adapty-devtools)
---
# File: create-product
---
---
title: "Crear producto"
description: "Guía paso a paso para crear nuevos productos de suscripción en Adapty para una mejor gestión de ingresos."
---
La forma de crear productos en Adapty depende de si ya los tienes en los stores:
- **[Si los productos aún no existen en App Store y/o Google Play, créalos en Adapty y envíalos directamente a los stores](#create-product-and-push-to-store)**.
- **[Si los productos ya existen en App Store y/o Google Play, créalos en Adapty y conecta los productos existentes del store.](#create-product-and-connect-existing-store-products)**
:::tip
También puedes crear productos de forma programática usando el [Developer CLI](developer-cli-reference#adapty-products-create).
:::
## Crear producto y enviarlo al store \{#create-product-and-push-to-store\}
:::warning
Antes de empezar, asegúrate de haber configurado la integración con los stores que necesitas:
- [App Store](initial_ios)
- [Google Play](initial-android)
Si configuraste la integración con App Store hace tiempo, asegúrate también de haber [añadido la clave API de App Store Connect](app-store-connection-configuration#step-6-add-app-store-connect-api-key).
:::
2. Haz clic en **Create product** en la esquina superior derecha. Adapty admite todos los tipos de productos: suscripciones, no consumibles \(incluido acceso de por vida\) y consumibles.
3. Selecciona **Create a new product and push to stores**.
4. Introduce los siguientes datos:
- **Product name**: escribe el nombre del producto que se usará en el Adapty Dashboard. El nombre es principalmente para tu referencia, así que elige el que te resulte más cómodo en el Adapty Dashboard.
- **Access Level**: selecciona el [nivel de acceso](access-level) al que pertenece el producto. El nivel de acceso determina las funciones que se desbloquean tras la compra. Ten en cuenta que esta lista solo contiene los niveles de acceso creados previamente. El nivel de acceso `premium` se crea en Adapty por defecto, pero también puedes [añadir más niveles de acceso](access-level).
- **Subscription duration**: selecciona la duración de la suscripción de la lista.
- **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**: la duración de la suscripción.
- **Lifetime**: usa el período de por vida para los productos que desbloquean las funciones premium de la app para siempre.
- **Non-Subscriptions**: para los productos que no son suscripciones y por tanto no tienen duración, usa non-subscriptions. Pueden usarse para desbloquear funciones adicionales, productos consumibles, etc.
- **Consumables**: los artículos consumibles se pueden comprar varias veces y se agotan durante la vida útil de la aplicación. Ejemplos son la moneda del juego y los extras. Ten en cuenta que los productos consumibles no afectan a los niveles de acceso.
- **Price (USD)**: el precio del producto en USD. Este precio se usará como base para calcular y establecer automáticamente los precios en todos los países. Podrás [personalizar el precio para distintos países y regiones](edit-product#set-country-specific-prices) más adelante.
5. Haz clic en **Save & Continue**.
6. Configura la información del producto para App Store si tienes previsto publicar allí:
- **Product ID**: crea un ID único y permanente para el producto.
- **Product group**: selecciona un grupo de productos existente que hayas creado en App Store Connect o haz clic en **Create new Product Group** e indica su nombre. Cuando Adapty lo cree, podrás seleccionarlo desde el desplegable.
- **Screenshot**: sube una captura de pantalla de la compra in-app que muestre claramente el artículo o servicio que se ofrece. Esta captura de pantalla se usa solo para la revisión de App Store y no se muestra en la App Store. Consulta los requisitos de tamaño y formato de la captura de pantalla [aquí](https://developer.apple.com/help/app-store-connect/reference/app-information/screenshot-specifications/).
7. Haz clic en **Push data to App Store**.
:::warning
Si es tu primer producto para esta app, debes enviarlo manualmente para revisión en App Store Connect. Esto no será necesario más adelante. Una vez finalizada la revisión, el estado del producto en Adapty se actualizará automáticamente.
:::
8. Configura la información del producto para Google Play si tienes previsto publicar allí:
- **Base Product ID**: crea un ID único y permanente para el producto.
- **Subscription**: selecciona un grupo de suscripciones existente que hayas creado en Google Play Console o haz clic en **Create new Product Group** e indica su nombre e ID. Cuando Adapty lo cree, podrás seleccionarlo desde el desplegable.
:::note
El período de gracia y el período de retención de cuenta se establecerán automáticamente con los valores predeterminados según las reglas de Play Store. Puedes cambiarlos más adelante en Google Play Console.
:::
9. Haz clic en **Push data to Play Store**.
10. Para iOS, configura la oferta introductoria —prueba gratuita— seleccionando su **Free duration** desde el desplegable. En esta configuración inicial puedes añadir una prueba gratuita introductoria. Una vez que los stores aprueben el producto principal, podrás [añadir más ofertas](offers) (p. ej., promocionales, de recuperación) vinculando sus ID existentes desde la consola de tu store.
:::important
Las ofertas introductorias no se sincronizan automáticamente con Google Play. A diferencia de App Store, Google Play no tiene un tipo de "oferta introductoria" independiente: las pruebas gratuitas y las ofertas con descuento se configuran como **offers** en un plan base. [Crea la oferta en Google Play Console y vincúlala a tu producto de Adapty](google-play-offers).
:::
11. Por último, haz clic en **Save** para confirmar la creación del producto.
## Crear producto y conectar productos existentes del store \{#create-product-and-connect-existing-store-products\}
:::warning
Antes de empezar, asegúrate de haber:
- Configurado la integración con los stores que necesitas:
- [App Store](initial_ios)
- [Google Play](initial-android)
- Creado productos en los stores que necesitas:
- [App Store](app-store-products)
- [Google Play](android-products)
**Si no tienes ningún producto creado**, considera seguir la guía [Enviar a los stores](#create-product-and-push-to-store) para crearlos tanto en Adapty como en los stores al mismo tiempo.
:::
2. Haz clic en **Create product** en la esquina superior derecha. Adapty admite todos los tipos de productos: suscripciones, no consumibles \(incluido acceso de por vida\) y consumibles.
3. Selecciona **Connect an existing store product**.
4. Introduce los siguientes datos:
- **Product name**: escribe el nombre del producto que se usará en el Adapty Dashboard. El nombre es principalmente para tu referencia, así que elige el que te resulte más cómodo en el Adapty Dashboard.
- **Access Level ID**: selecciona el [nivel de acceso](access-level) al que pertenece el producto. El nivel de acceso determina las funciones que se desbloquean tras la compra. Ten en cuenta que esta lista solo contiene los niveles de acceso creados previamente. El nivel de acceso `premium` se crea en Adapty por defecto, pero también puedes [añadir más niveles de acceso](access-level).
- **Subscription duration**: selecciona la duración de la suscripción de la lista.
- **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**: la duración de la suscripción.
- **Lifetime**: usa el período de por vida para los productos que desbloquean las funciones premium de la app para siempre.
- **Non-Subscriptions**: para los productos que no son suscripciones y por tanto no tienen duración, usa non-subscriptions. Pueden usarse para desbloquear funciones adicionales, productos consumibles, etc.
- **Consumables**: los artículos consumibles se pueden comprar varias veces y se agotan durante la vida útil de la aplicación. Ejemplos son la moneda del juego y los extras. Ten en cuenta que los productos consumibles no afectan a los niveles de acceso.
- **Price (USD)**: el precio del producto en USD. Si tu producto ya está en el store, este valor no afectará a su precio real en el store; puedes seleccionar cualquier valor de la lista. Más adelante, puedes [personalizar los precios para distintas regiones](edit-product#set-country-specific-prices) directamente en el Adapty Dashboard.
5. Haz clic en **Continue**.
6. Configura la información del producto de cada store:
- **App Store:**
- **App Store Product ID:** este identificador único se usa para acceder a tu producto en los dispositivos. Selecciónalo de la lista. Si no lo ves en la lista, revisa su configuración en App Store Connect y asegúrate de que es correcta y pertenece a esta app.
- **Play Store:**
- **Google Play Product ID:** este es el identificador del producto en Play Store. Selecciónalo de la lista. Si no lo ves en la lista, revisa su configuración en Google Play Console y asegúrate de que es correcta y pertenece a esta app.
- **Base Plan ID:** este ID define el plan base del producto en Play Store. Al añadir el Product ID de una suscripción en Play Store, debes proporcionar un Base Plan ID. Un plan base define los detalles esenciales de una suscripción: el período de facturación, el tipo de renovación (automática o de prepago) y el precio asociado. Ten en cuenta que, en Adapty, cada combinación de la misma suscripción con diferentes planes base se trata como un producto separado.
- **Legacy fallback product**: un producto de respaldo se usa exclusivamente para apps que usan versiones antiguas del SDK de Adapty (versiones 2.5 e inferiores). Al marcar un producto como compatible con versiones anteriores en Google Play Console, Adapty puede identificar si puede ser comprado por versiones antiguas del SDK. Para este campo, especifica el valor en el siguiente formato: `
## Establecer precios por país \{#set-country-specific-prices\}
Puedes configurar precios diferentes para distintas regiones directamente en el Adapty Dashboard, y estos precios por país se aplicarán automáticamente a tus productos en App Store Connect y/o Google Play Console.
Para establecer precios por país:
1. [Abre el producto para editarlo](#edit-product).
2. Haz clic en **Download** para exportar tus precios actuales de las stores en el formato correcto, o crea un nuevo archivo CSV.
3. Actualiza los precios en el archivo CSV. Respeta el [formato](#csv-file-format). Si dejas el precio de algún país sin cambios o no lo incluyes en el archivo, no ocurrirá nada. Al subir el CSV, Adapty compara los precios y actualiza únicamente los que sean diferentes.
4. En la ventana **Edit**, haz clic en **Upload** y selecciona el archivo CSV.
5. Si quieres que los cambios también se apliquen a los suscriptores existentes, selecciona **Apply to existing subscribers**.
6. Revisa los cambios que se aplicarán y haz clic en **Save changes**.
### Formato del archivo CSV \{#csv-file-format\}
:::tip
Puedes reutilizar el mismo archivo CSV si tienes productos similares en una misma app o si quieres establecer los mismos precios en diferentes apps.
:::
La forma más sencilla de editar precios en CSV es [descargar un archivo con los precios actuales y editarlo directamente](#set-country-specific-prices).
Sin embargo, si lo creas tú mismo, el archivo debe contener las siguientes columnas:
- `region_name`
- `region_code`
- `app_store_currency`
- `app_store_requested_price`
- `play_store_currency`
- `play_store_requested_price`
Ejemplo:
```
region_name,region_code,app_store_currency,app_store_requested_price,play_store_currency,play_store_requested_price
United States,US,,8.99,,8.99
United Arab Emirates,AE,USD,8.99,AED,39.99
Germany,DE,USD,8.99,USD,8.99
```
## Ver el registro de auditoría \{#view-audit-log\}
Adapty registra todos los cambios de precio de cada producto, para que puedas hacer seguimiento de quién realizó los cambios y cuándo. Para ver el registro de auditoría:
1. Ve a **[Products](https://app.adapty.io/products)** desde el menú principal de Adapty.
2. Haz clic en los tres puntos junto al producto y selecciona **Audit log**.
La tabla del registro de auditoría muestra cada cambio de precio con la fecha, el nombre y rol del miembro del equipo, y el número de cambios.
Para descargar un desglose CSV detallado de un evento, haz clic en el icono de descarga de esa fila.
---
# File: delete-product
---
---
title: "Eliminar producto"
description: "Descubre cómo eliminar un producto de suscripción en Adapty sin interrumpir el flujo de ingresos de tu app."
---
Solo puedes eliminar productos que no estén en uso en ningún paywall.
Para eliminar el producto:
1. Ve a **[Products](https://app.adapty.io/products)** desde el menú principal de Adapty.
2. Haz clic en el botón de **3 puntos** junto al producto y selecciona **Delete**.
2. Introduce el nombre del producto que vas a eliminar.
3. Haz clic en **Delete forever**.
---
# File: add-product-to-paywall
---
---
title: "Añadir producto a un paywall"
description: "Aprende a añadir y gestionar productos en paywalls en Adapty."
---
Para que un producto sea visible y seleccionable dentro de un [paywall](paywalls) para los usuarios de tu app, sigue estos pasos:
1. Al [configurar un paywall](create-paywall), haz clic en **Add product** bajo el título **Products**.
2. En el menú desplegable que se abre, selecciona los productos que se mostrarán a tus clientes. La lista contiene únicamente los productos creados previamente. El orden de los productos se mantiene en el lado del SDK, por lo que es importante tener en cuenta el orden deseado al configurar el paywall. Además, puedes especificar una oferta para un producto si lo deseas.
3. Haz clic en **Create as draft** o **Save and publish** según el estado del paywall.
Ten en cuenta que, tras la creación, no se recomienda editar, añadir ni eliminar productos del paywall, ya que esto puede afectar a las métricas del paywall.
---
# File: app-store-offers
---
---
title: "Ofertas en App Store"
description: "Configura y gestiona las ofertas de App Store para aumentar la retención de usuarios."
---
:::info
Configura tus [productos de la store](quickstart-products) antes de seguir esta guía.
:::
Las ofertas en App Store son promociones especiales, pruebas gratuitas o descuentos para suscripciones de renovación automática. Incluyen descuentos y ofertas combinadas que ayudan a atraer nuevos usuarios y aumentar la conversión.
Hay cuatro tipos de oferta en App Store, y Adapty los admite todos:
- **[Ofertas introductorias](#introductory-offers) para nuevos usuarios**:
- Períodos de suscripción gratuitos o con descuento
- Solo los nuevos usuarios son elegibles (aquellos que nunca han activado una oferta introductoria ni han tenido una suscripción)
- No necesitas vincularlas a productos en Adapty. Adapty aplica las ofertas automáticamente para los usuarios elegibles que compran el producto.
- **Ofertas [promocionales](#promotional-offers) y de [recuperación](#win-back-offers)**:
- Adapty aplica estas ofertas automáticamente en el momento de la compra, pero primero debes configurarlas en tus productos y paywalls.
- Las ofertas promocionales incluyen períodos de suscripción gratuitos, descuentos en porcentaje y descuentos de precio fijo. Cualquier usuario puede ser elegible.
- Las ofertas de recuperación incluyen períodos de suscripción gratuitos o descuentos en porcentaje. Solo los usuarios que se han dado de baja son elegibles.
- **Códigos de oferta**: Para más información, consulta [Canjear códigos de oferta en iOS](making-purchases#redeem-offer-codes-in-ios).
:::important
Para usar las ofertas de App Store, sube tu [clave de suscripción](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers) al Adapty Dashboard.
:::
## Ofertas introductorias \{#introductory-offers\}
Adapty aplica automáticamente las ofertas introductorias en iOS si el usuario es elegible.
Para activar las ofertas introductorias en los productos que vendes, solo tienes que crearlas en App Store Connect:
1. Abre tu app en App Store Connect y ve a **Monetization > Subscriptions**.
2. Selecciona un grupo de suscripciones y navega hasta la suscripción que necesitas. La suscripción debe tener una duración configurada.
3. Haz clic en **View all Subscription Pricing** y cambia a la pestaña **Introductory offers**. Haz clic en **Set up introductory offer**.
4. Selecciona los países y regiones donde estará disponible la oferta introductoria.
5. Selecciona las fechas de inicio y fin de la oferta introductoria. Si la oferta introductoria no tiene una fecha de fin específica, selecciona **No end date**. Haz clic en **Next**.
6. Selecciona el tipo de oferta introductoria. Según lo que elijas, también deberás definir la duración y el precio de la oferta. Lee más en la [documentación de Apple](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-introductory-offers-for-auto-renewable-subscriptions).
7. Revisa tu selección y haz clic en **Confirm**.
Una vez que termines esta configuración, no necesitas hacer nada más en Adapty. La oferta se activa para los usuarios elegibles que compran el producto. Asegúrate de mostrar un paywall con este producto solo a los usuarios que son elegibles para la oferta.
## Ofertas promocionales \{#promotional-offers\}
Adapty aplica automáticamente las ofertas promocionales si los usuarios son elegibles. Configura tus ofertas en App Store Connect primero y luego añádelas a un producto y paywall en Adapty:
1. Abre tu app en App Store Connect y ve a **Monetization > Subscriptions** desde el menú de la izquierda.
2. Selecciona un grupo de suscripciones y navega hasta la suscripción que necesitas. La suscripción debe tener una duración configurada.
3. Haz clic en **View all Subscription Pricing** y cambia a la pestaña **Promotional offers**. Haz clic en **Set up promotional offer**.
4. Introduce los detalles de la oferta promocional. Estos valores no se pueden cambiar después de crearlos y se reutilizarán, así que elige con cuidado.
- **Promotional offer reference name**: El nombre de la oferta promocional. No será visible para tus usuarios.
- **Promotional offer identifier**: El código de identificación de la oferta promocional. Lo usarás para añadir la oferta a Adapty.
5. Selecciona el tipo de oferta promocional. El tipo determina si los usuarios pagan un precio reducido o reciben un período gratuito. Para un descuento, selecciona **Pay as you go** o **Pay up front**. Para un período de suscripción gratuito, selecciona **Free**. Luego establece la duración y el precio de la oferta. Lee más en la [documentación de Apple](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-promotional-offers-for-auto-renewable-subscriptions).
6. Si es necesario, establece precios diferentes para distintos países y regiones y haz clic en **Next**.
7. Revisa tu elección y haz clic en **Confirm**.
8. [Añade la oferta promocional](create-offer) a Adapty.
## Ofertas de recuperación \{#win-back-offers\}
:::important
Antes de poder crear una oferta de recuperación, tu suscripción debe estar aprobada por App Review.
:::
Adapty aplica automáticamente las ofertas de recuperación si los usuarios son elegibles. Configura tus ofertas en App Store Connect primero y luego añádelas a un producto y paywall en Adapty:
1. Abre tu app en App Store Connect y ve a **Monetization > Subscriptions** desde el menú de la izquierda.
2. Selecciona un grupo de suscripciones y navega hasta la suscripción que necesitas. La suscripción debe tener una duración configurada.
3. Haz clic en **View all Subscription Pricing** y cambia a la pestaña **Win-back offers**. Haz clic en **Create offer**.
4. Introduce los detalles de la oferta de recuperación. Estos valores no se pueden cambiar después de crearlos.
- **Reference name**: El nombre de la oferta. No será visible para tus usuarios.
- **Offer identifier**: El código de identificación de la oferta. Lo usarás para añadir la oferta a Adapty.
5. Configura el tipo, la duración y el precio de la oferta. Lee más en la [documentación de Apple](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-win-back-offers).
6. Revisa tu elección y haz clic en **Confirm**.
7. [Añade la oferta](create-offer) a Adapty.
## Pasos siguientes \{#next-steps\}
Después de añadir las ofertas, continúa con la configuración:
- Si también tienes **apps en Google Play**, configura las [ofertas de Google Play](google-play-offers).
- Si tienes **ofertas promocionales o de recuperación**, [añádelas a Adapty](create-offer).
- Si solo tienes **ofertas introductorias** y no tienes ofertas promocionales ni de recuperación, ya has terminado. Estas secciones pueden seguir siendo útiles:
- [Trabajar con ofertas en el Paywall Builder de Adapty](create-offer#paywall-builder)
- [Cómo funciona Adapty con las ofertas](create-offer#how-adapty-works-with-offers)
---
# File: google-play-offers
---
---
title: "Ofertas en Google Play"
description: "Configura las ofertas de Google Play para mejorar la monetización y la retención de tu app."
---
En Google Play, las ofertas de cualquier tipo (períodos de prueba gratuitos o pagos con descuento) se añaden como **offers**. Para crear una oferta, primero debes crear una suscripción y añadir un plan base de renovación automática.
Las ofertas siempre se crean para planes base dentro de suscripciones. En la captura de pantalla a continuación, puedes ver una suscripción `premium_access`(1) con dos planes base: `1-month` (2) y `1-year` (3).
Para crear una oferta en Google Play Console:
1. Haz clic en **Add offer** y elige el plan base de la lista.
2. Introduce el ID de la oferta. Se usará más adelante en los análisis y en el Adapty Dashboard, así que dale un nombre descriptivo.
3. Elige los criterios de elegibilidad:
1. **New customer acquisition**: la oferta estará disponible solo para nuevos suscriptores que no la hayan utilizado antes. Es la opción más habitual y la que deberías usar por defecto.
2. **Upgrade**: esta oferta estará disponible para los clientes que actualicen desde otra suscripción. Úsala cuando quieras promocionar planes más caros a tus suscriptores actuales; por ejemplo, clientes que pasan del nivel bronce al nivel oro de tu suscripción.
3. **Developer determined**: puedes controlar quién puede usar esta oferta desde el código de la app. Úsala con precaución en producción para evitar posibles fraudes: los clientes podrían activar una suscripción gratuita o con descuento una y otra vez. Un buen caso de uso para este tipo de oferta es recuperar suscriptores que han cancelado.
4. Añade hasta dos fases de precio a tu oferta. Hay tres tipos de fase disponibles:
1. **Free trial**: la suscripción se puede usar gratis durante un período de tiempo configurado (mínimo 3 días). Es la oferta más habitual.
2. **Single payment**: la suscripción es más barata si los clientes pagan por adelantado. Por ejemplo, normalmente un plan mensual cuesta 9,99 $, pero con este tipo de oferta, los primeros tres meses cuestan 19,99 $, un descuento del 30%.
3. **Discounted recurring payment**: la suscripción es más barata durante los primeros `n` períodos. Por ejemplo, normalmente un plan mensual cuesta 9,99 $, pero con este tipo de oferta, cada uno de los primeros tres meses cuesta 4,99 $, un descuento del 50%.
Una oferta puede tener dos fases. En ese caso, la primera fase debe ser un Free trial y la segunda puede ser un Single payment o un Discounted recurring payment. Se aplicarán en ese orden.
:::important
Ten en cuenta que los paywalls creados con el Adapty Paywall Builder mostrarán únicamente la primera fase de una oferta de suscripción de Google con varias fases. No obstante, cuando un usuario compre el producto, todas las fases de la oferta se aplicarán tal como están configuradas en Google Play.
:::
5. Activa la oferta para usarla en la app.
6. Continúa con [cómo añadir la oferta a Adapty](create-offer).
:::note
Los IDs de oferta pueden ser iguales para distintos planes base.
:::
## Pasos siguientes \{#next-steps\}
Una vez añadidas las ofertas, continúa con la configuración:
- Si también tienes **apps en App Store**, consulta la [guía de App Store](app-store-offers).
- Si tienes **apps solo en Google Play**, sigue [esta guía](create-offer) para añadir ofertas a Adapty.
---
# File: create-offer
---
---
title: "Añadir ofertas a Adapty"
description: "Crea y gestiona ofertas especiales de suscripción con las herramientas de Adapty."
---
Adapty te permite ofrecer pruebas o descuentos a suscriptores nuevos, actuales o que han cancelado.
Una vez que los hayas configurado en App Store Connect o Google Play Console, debes añadirlos a Adapty en dos pasos:
1. [Añadir ofertas a los productos en Adapty usando los IDs de oferta de las stores.](#1-create-offer)
2. [Añadir ofertas a los paywalls para que puedan aplicarse.](#2-add-offer-to-paywall)
:::warning
Las ofertas introductorias (App Store) se aplican automáticamente si el usuario es elegible. No las añadas a los productos en Adapty.
Esta guía explica cómo configurar ofertas promocionales (App Store), ofertas de recuperación (App Store) y todas las ofertas de Google Play.
:::
## 0. Antes de empezar \{#0-before-you-start\}
Antes de configurar ofertas en Adapty, asegúrate de lo siguiente:
1. Has creado todas las ofertas que necesitas en la store:
- [App Store](app-store-offers)
- [Google Play](google-play-offers)
2. Has creado los [productos](create-product) en Adapty y añadido sus IDs.
3. Para App Store: Has subido [la clave de compra in-app para ofertas promocionales](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers).
## 1. Añadir oferta a un producto en Adapty \{#1-add-offer-to-product-in-adapty\}
Una vez que tu oferta promocional (tanto para Play Store como para App Store) o tu oferta de recuperación (para App Store) esté configurada en las stores, añadirla a Adapty es sencillo:
1. Abre [**Products**](https://app.adapty.io/products) desde el menú principal de Adapty. Busca el producto al que quieres añadir una oferta.
2. Encuentra el producto al que quieres añadir una oferta. En la columna **Actions**, haz clic en el botón de **3 puntos** junto al producto y selecciona **Edit**.
3. En la ventana **Edit product**, haz clic en **+** y selecciona **Add offers**.
4. Haz clic en **Add offer**.
5. Introduce los detalles de la oferta para el producto.
Estos son los campos disponibles:
- **Offer name**: Asigna un nombre a la oferta para identificarla fácilmente en Adapty. Usa el nombre que más te convenga.
- **App Store Offer type**: Selecciona el tipo de oferta de App Store que estás añadiendo: Promotional o Win-back. (Las ofertas introductorias no hace falta añadirlas: se aplican automáticamente si están disponibles.)
- **App Store Offer ID**: Es el ID único de la oferta [que configuraste en App Store](app-store-products).
- **Play Store Offer ID**: De igual modo, es el ID único de la oferta [que configuraste en Play Store](android-products).
:::tip
Si el campo **App Store Offer ID** o **Play Store Offer ID** no está activo, cambia a la pestaña **Products** y selecciona un ID de producto.
:::
6. (opcional) Añade más ofertas si lo necesitas haciendo clic en **Add offer**.
7. Haz clic en **Save** para añadir las ofertas al producto.
## 2. Añadir oferta a un paywall \{#2-add-offer-to-paywall\}
:::info
No puedes añadir ofertas a paywalls en estado **live**. Si quieres añadir una oferta a un paywall existente, [duplícalo](duplicate-paywalls) y configura los productos en el nuevo paywall.
:::
Para que una oferta sea visible y seleccionable dentro de un [paywall](paywalls) para los usuarios de tu app, sigue estos pasos:
1. Al crear o editar un paywall, en la pestaña **General**, añade el producto al que acabas de añadir la oferta.
2. Elige la oferta que [creaste antes](create-offer) para este producto en la lista **Offer**. La lista solo está disponible para los productos que tienen ofertas.
3. Si lo necesitas, añade más productos y ofertas, pero solo puedes añadir una oferta por cada producto.
### Paywall Builder \{#paywall-builder\}
:::info
Los paywalls creados con el Paywall Builder de Adapty mostrarán únicamente la primera fase de una [oferta de suscripción multifase de Google](https://support.google.com/googleplay/android-developer/answer/12154973). Sin embargo, ten en cuenta que cuando un usuario compra el producto, se aplicarán todas las fases de la oferta tal como se configuraron en Google Play.
:::
Cuando creas un paywall en el Paywall Builder de Adapty, tienes más opciones de personalización para los trials:
- **Toggle**: En **Products**, establece **Product grouping** en **Toggle** y añade combinaciones de producto-oferta para cada estado del toggle. El caso de uso más habitual es incluir un producto sin oferta (p. ej., compra directa sin prueba gratuita) y otro producto diferente con una oferta asociada.
- **Texto dinámico**: Puedes hacer que el texto del botón de compra cambie según la oferta disponible para el usuario que ve el paywall. Puedes configurar textos distintos para **Default**, **Free trial**, **Pay as you go** y **Pay up front**.
## Cómo funciona Adapty con las ofertas \{#how-adapty-works-with-offers\}
Ten en cuenta lo siguiente sobre el funcionamiento de las ofertas en Adapty:
- Cuando un usuario es elegible para una oferta, Adapty aplica automáticamente la oferta que hayas configurado en el momento en que el usuario realiza una compra.
- Si un producto tiene tanto una oferta introductoria como ofertas promocionales configuradas en App Store, los usuarios elegibles recibirán primero la oferta introductoria. Una vez finalizado su período, si el usuario sigue siendo elegible para la oferta promocional y la has configurado en Adapty, se aplicará cuando intente comprar el producto de nuevo.
- Si quieres tener más control sobre cómo se aplican las ofertas o necesitas vender tu producto sin ofertas en determinados casos, tienes varias opciones:
- Configura los criterios de elegibilidad en App Store o Google Play Console
- Crea un producto separado sin ofertas en App Store o Google Play Console
- Crea un producto separado sin ofertas en Adapty, añade paywalls con ambas variantes del producto a un [placement](placements) y utiliza [segmentos](segments) de audiencia para controlar qué paywall se muestra a cada usuario. Por ejemplo, puedes crear segmentos basados en **Subscription product** o **Paid access level**, o usar [atributos personalizados](profiles-crm) para implementar tu propia lógica.
---
# File: create-paywall
---
---
title: "Crear paywall"
description: "Aprende a crear paywalls de alta conversión usando el Paywall Builder de Adapty."
---
Un [paywall](paywalls) es una configuración de Adapty que define qué productos ofrecer. En Adapty, los paywalls son la única forma de recuperar productos en tu app.
Necesitas un paywall independientemente de cómo lo muestres:
- [**Paywall Builder**](adapty-paywall-builder): Diseña una pantalla en el editor sin código. Adapty la renderiza y gestiona las compras.
- **Paywall personalizado**: Implementa tu propia interfaz y usa la configuración del paywall para recuperar los productos.
Una vez creado, asigna el paywall a un [placement](placements) — los placements controlan qué paywall ven los usuarios. Los productos de un paywall en producción son fijos, por lo que sus métricas siempre reflejan la misma combinación, lo que te permite comparar el rendimiento entre distintos conjuntos de productos y precios.
:::tip
También puedes crear paywalls mediante programación usando la [CLI para desarrolladores](developer-cli-reference#adapty-paywalls-create).
:::
## Próximos pasos \{#next-steps\}
Después de crear tu primer paywall:
1. Agrégalo a un [placement](placements). Los IDs de placement serán las únicas entidades hardcodeadas. Los usarás para obtener los productos que quieres vender.
2. El modo de trabajo con el paywall a partir de aquí depende de tu implementación:
- Si quieres usar el [Adapty Paywall Builder](adapty-paywall-builder), diseña el paywall en el editor sin código. Adapty renderizará el paywall y gestionará la lógica de compra, mientras que tú solo necesitarás mostrar el paywall en el código de la app.
- Si tienes un paywall personalizado que quieres usar, consulta nuestras guías para implementar compras in-app con Adapty en tu plataforma:
- [iOS](ios-implement-paywalls-manually)
- [Android](android-implement-paywalls-manually)
- [React Native](react-native-implement-paywalls-manually)
- [Flutter](flutter-implement-paywalls-manually)
- [Unity](unity-implement-paywalls-manually)
- [Kotlin Multiplatform](kmp-implement-paywalls-manually)
---
# File: paywall-builder-templates
---
---
title: "Plantilla de paywall"
description: "Usa las plantillas del Paywall Builder de Adapty para crear paywalls de alta conversión."
---
Las plantillas de paywall prediseñadas tienen un diseño profesional y están pensadas para simplificar el proceso de creación de tu paywall. Las crean diseñadores expertos para que puedas presentar tus productos de forma atractiva con el mínimo esfuerzo.
¡Solo añade tu logo, dale el toque de tu marca y listo para cautivar a tu audiencia y disparar las ventas!
:::warning
Esta sección describe el nuevo Paywall Builder, compatible con los SDK de iOS, Android y React Native versión 3.0 o superior, y con los SDK de Flutter y Unity versión 3.3.0 o superior. Para información sobre el Paywall Builder antiguo, compatible con el SDK de Adapty v2.x o anterior, consulta [Plantillas del Paywall Builder antiguo](paywall-builder-templates-legacy).
:::
## Por qué usar plantillas de paywall \{#why-use-paywall-templates\}
Las plantillas son un punto de partida excelente: ofrecen diseños bien estructurados y con gran atractivo visual. Puedes usarlas tal cual o hacer pequeños ajustes para adaptarlas a la estética de tu marca.
Estas son las razones por las que las plantillas prediseñadas son una opción inteligente:
- **Ahorro de tiempo**: monta un paywall de aspecto profesional rápidamente sin necesidad de un trabajo de diseño exhaustivo.
- **Coherencia**: garantiza una apariencia uniforme alineada con estándares de diseño probados.
- **Personalización**: adapta cada plantilla con los elementos de tu marca para hacerla única.
Para quienes prefieren un enfoque más libre, las plantillas de diseño minimalista ofrecen un lienzo en blanco. Estas plantillas incluyen posiciones básicas, lo que facilita dar rienda suelta a tu creatividad y construir un paywall desde cero con el versátil, completo y fácil de usar Paywall Builder de Adapty.
## Elegir plantilla de paywall \{#choose-paywall-template\}
Al crear un nuevo paywall, Adapty ofrece una selección de plantillas. Puedes cambiar de plantilla en cualquier momento después de eso.
Sin embargo, es importante tener en cuenta que reemplazar una plantilla descartará cualquier cambio realizado en el diseño de tu paywall. Para no perder tu trabajo, te recomendamos duplicar el paywall antes de cambiar de plantilla, así podrás volver al paywall guardado si lo necesitas.
1. Ve a los **Layout settings** del paywall.
2. Haz clic en **Change template**.
3. En la ventana **Choose template** que se abre, explora y selecciona una nueva plantilla.
4. Haz clic en **Choose** para confirmar el cambio de plantilla. Ten en cuenta que reemplazar una plantilla descartará cualquier cambio realizado en el diseño de tu paywall.
---
# File: paywall-generator
---
---
title: "Generador de paywalls"
description: "Genera paywalls con IA y lánzalos rápidamente."
---
:::info
El generador de paywalls con IA solo está disponible para apps publicadas en la Apple App Store.
:::
Puedes crear un paywall único y con alta tasa de conversión adaptado a tu app en cuestión de segundos con nuestro generador de IA integrado.
Así podrás lanzar tus paywalls más rápido y dejar de perder tiempo pensando por dónde empezar.
:::note
No puedes indicar qué elementos aparecerán dentro del paywall. El generador de paywalls está pensado principalmente para conseguir unos visuales perfectos generando textos e imágenes.
:::
## Generar paywalls \{#generate-paywalls\}
Para generar un paywall:
1. En los **Layout settings** del paywall, haz clic en **Change template > Generate template**. O, para un paywall nuevo, haz clic en **Generate paywall** desde la pestaña **Builder & Generator tab**.
2. Escribe tu prompt en el campo de texto. O selecciona uno de los prompts predefinidos para probar qué puede crear el generador de paywalls para tu app. Consulta [los consejos a continuación](#how-to-write-prompts-for-paywall-generator) para aprender a escribir el prompt más efectivo y obtener un paywall con un aspecto cuidado y listo para producción.
3. El generador de paywalls obtendrá información sobre tu app desde la App Store y generará un paywall relevante con los productos que hayas añadido. Si encuentras algún problema, asegúrate de tener el [**Apple App ID** en los **App settings**](app-store-connection-configuration#step-1-provide-bundle-id-and-apple-app-id).
4. Elige una de las cinco plantillas generadas y haz clic en **Pick & Open in Builder**, o chatea con el generador como lo harías con tus agentes de IA favoritos para mejorar el resultado de la generación.
:::important
Puedes generar hasta 10 conjuntos de plantillas al día para una app. Cada chat puede contener hasta 10 generaciones. Si alcanzas este límite, crea un nuevo chat y usa el contexto del chat anterior para escribir un prompt detallado.
:::
5. Los chats se organizan como hilos y se guardan en la cuenta de tu app. Puedes volver a los chats en cualquier momento y probar otras plantillas de los hilos. Siempre puedes comprobar qué prompts funcionaron mejor o ajustar algunas plantillas que hayas usado anteriormente.
## Cómo escribir prompts para el generador de paywalls \{#how-to-write-prompts-for-paywall-generator\}
Estos consejos te ayudarán a escribir prompts para generar un paywall listo para producción:
- Cuantos más detalles especifiques en el prompt, mejor.
- **Mal**: Haz que mi paywall tenga un aspecto moderno
- **Bien**: Crea un paywall moderno y minimalista con fondo claro, botones redondeados y degradados sutiles.
- No describas tu app en detalle; Adapty la obtiene automáticamente de la App Store:
- **Mal**: Crea un paywall navideño para mi app que enseña a la gente a dibujar.
- **Bien**: Crea un paywall festivo con temática navideña, colores cálidos, copos de nieve dibujados a mano y un titular alegre como "Desbloquea todas las lecciones".
- Describe los visuales y el texto, no el diseño o la estructura:
- **Mal**: Añade reseñas de usuarios al carrusel.
- **Bien**: Incluye una cita breve de un usuario satisfecho, como "¡Esta app mejoró completamente mis habilidades de dibujo!", cerca de la parte inferior de la pantalla.
- Especifica el estilo de la imagen o ilustración con claridad.
- **Mal**: Añade una imagen de personas haciendo ejercicio.
- **Bien**: Añade una ilustración de estilo plano de dos personas haciendo yoga sobre esterillas en un estudio luminoso y minimalista. Usa colores pastel suaves para que encaje con una temática de bienestar.
---
# File: manage-paywall-ui-elements
---
---
title: "Gestionar elementos de la UI del paywall"
description: "Personaliza y gestiona los elementos de la UI del paywall para mejorar la experiencia del usuario."
---
Tras elegir una plantilla, sus elementos se mostrarán en el panel izquierdo. Usa este panel para organizar los elementos de tu paywall. Los elementos aparecerán en el paywall en el mismo orden en que figuran en el panel izquierdo.
:::warning
Esta sección describe el nuevo Paywall Builder, que funciona con los SDKs de iOS, Android y React Native en la versión 3.0 o superior, y con los SDKs de Flutter y Unity en la versión 3.3.0 o superior. Para información sobre el Paywall Builder legacy compatible con Adapty SDK v2.x o anterior, consulta [Legacy Paywall Builder](adapty-paywall-builder-legacy).
:::
## Añadir elemento \{#add-element\}
Para añadir un elemento a tu paywall por encima del layout:
1. Haz clic en el botón **Add Element** del panel izquierdo.
2. Elige el elemento que quieres añadir. El nuevo elemento aparecerá en la lista encima del **Footer**.
Para añadir un elemento a un elemento compuesto:
1. Haz clic en el botón **Plus** junto al elemento compuesto.
2. Selecciona el elemento que quieres añadir.
## Renombrar elemento del paywall \{#rename-paywall-element\}
Para renombrar un elemento:
1. Haz clic en el elemento en el panel izquierdo para abrir sus detalles.
2. Haz clic en el botón de puntos suspensivos en el panel derecho y elige la opción **Edit**.
3. Escribe el nuevo nombre del elemento y pulsa **Enter**.
## Duplicar elemento \{#duplicate-element\}
Para duplicar un elemento:
1. Haz clic en el elemento en el panel izquierdo para abrir sus detalles.
2. Haz clic en el botón de puntos suspensivos en el panel derecho y elige la opción **Duplicate**.
El elemento duplicado, con "Copy" añadido a su nombre, aparecerá en el panel izquierdo como una copia completa del original.
## Mover elemento \{#move-element\}
Para mover un elemento: arrastra y suelta el elemento a su nueva posición en el layout o dentro de un elemento compuesto.
Una línea morada indica una posición disponible para el elemento, mientras que una línea roja muestra una posición no accesible.
## Ocultar / mostrar elemento \{#hide--show-element\}
Aunque ya hayas creado y configurado un elemento, puedes ocultarlo temporalmente del paywall. Esto resulta útil si planeas añadirlo más adelante sin perder toda la configuración que hiciste. Al ocultar un elemento, el paywall se muestra como si el elemento nunca hubiera sido añadido; todos los alineamientos y espacios se recalculan y redesplazan.
Para ocultar un elemento:
1. Haz clic en el elemento en el panel izquierdo para abrir sus detalles.
2. Haz clic en el botón de puntos suspensivos en el panel derecho y elige la opción **Hide**.
El elemento oculto queda marcado tanto en el panel principal —como una nota— como en el panel izquierdo cuando lo seleccionas.
Para volver a mostrar el elemento, haz clic en el botón de puntos suspensivos en el panel derecho y elige la opción **Show**.
## Eliminar elemento \{#delete-element\}
Para eliminar un elemento del paywall:
1. Haz clic en el elemento en el panel izquierdo para abrir sus detalles.
2. Haz clic en el botón de puntos suspensivos en el panel derecho y elige la opción **Delete**.
---
# File: paywall-device-compatibility-preview
---
---
title: "Vista previa de paywalls"
description: "Previsualiza la compatibilidad de los paywalls en distintos dispositivos para una experiencia óptima."
---
:::important
Esta sección describe el nuevo Paywall Builder, que funciona con iOS, Android y los SDK de React Native versión 3.0 o superior, y los SDK de Flutter y Unity versión 3.3.0 o superior. Para información sobre el Paywall Builder heredado compatible con Adapty SDK v2.x o anterior, consulta [Vista previa de compatibilidad de dispositivos del Paywall Builder heredado](paywall-layout-and-products-legacy#device-compatibility-preview).
:::
Tienes dos formas de previsualizar tu paywall en diferentes tipos de pantalla:
- **Vista previa en dispositivos**: Comprueba que todo se ve como esperas en dispositivos reales en cualquier etapa del desarrollo.
- **Vista previa en el Adapty Dashboard**: Previsualiza tu paywall mientras lo diseñas.
## Vista previa en dispositivos \{#preview-on-devices\}
Para previsualizar tu paywall en un dispositivo real:
1. [Descarga la app de Adapty desde la App Store](https://apps.apple.com/us/app/adapty/id6739359219).
2. En el paywall builder, haz clic en **Test on device**.
## Vista previa en el Adapty Dashboard \{#preview-in-the-adapty-dashboard\}
Puedes previsualizar tu paywall en diferentes tipos de pantalla usando el panel del lado derecho del paywall builder. Esto te ayuda a asegurarte de que tu paywall se vea bien en distintos dispositivos y tamaños de pantalla.
Desde aquí puedes:
- Seleccionar el dispositivo en el que previsualizar tu paywall.
- Cambiar entre los modos de vista previa horizontal y vertical — especialmente útil para paywalls diseñados para iPad.
- Acercar o alejar la vista previa.
- Previsualizar [variables de etiquetas para información de productos](paywall-builder-tag-variables#how-to-use-tag-variables).
:::tip
Configura el [ancho máximo](paywall-layout-and-products#content-layout) de los elementos para optimizar el diseño en iPads.
:::
---
# File: paywall-layout-and-products
---
---
title: "Diseño del paywall"
description: "Diseña los layouts de tus paywalls y gestiona productos en Adapty para mejorar la conversión."
---
Tras seleccionar una plantilla para tu paywall en el Paywall Builder de Adapty, puedes personalizar su apariencia visual para que se ajuste al estilo de tu marca. Los ajustes de Layout ofrecen una gran variedad de controles para modificar el layout, el fondo y el aspecto general del paywall. Exploremos estos ajustes: los ajustes de layout controlan los aspectos básicos del paywall, incluyendo la plantilla, el color de fondo, las fuentes predeterminadas, el flujo de compra, el layout del contenido y los botones superiores.
:::warning
Esta sección describe el nuevo Paywall Builder, que funciona con los SDKs de iOS, Android y React Native versión 3.0 o superior, y los SDKs de Flutter y Unity versión 3.3.0 o superior. Para información sobre el Paywall Builder heredado compatible con Adapty SDK v2.x o anterior, consulta [Diseño del paywall en el Legacy Paywall Builder](paywall-layout-and-products-legacy#layout).
:::
## Flujo de compra \{#purchase-flow\}
Decide cómo completarán las compras tus usuarios. Hay dos opciones:
- **Products as list + purchase button**: Los usuarios seleccionan los productos primero y luego pulsan el botón de compra para iniciar la transacción.
- **Products as purchase buttons**: Cada producto es un botón, y la compra comienza cuando el usuario pulsa el botón de ese producto.
## Color de fondo \{#background-color\}
Mantén la coherencia visual estableciendo un fondo predeterminado para tu paywall. Usa el campo **Background color** en los **Layout settings**. Haz clic en el cuadrado de color para abrir la ventana de configuración, donde puedes elegir un color sólido o un degradado en pestañas separadas.
## Ajustes de fuente de tu paywall \{#font-settings-of-your-paywall\}
Es importante que el paywall sea visualmente coherente con el resto de tu app, y uno de los factores visuales más importantes es la fuente que usas. Puedes elegir simplemente usar la fuente del sistema (SF Pro para iOS, Roboto para Android), usar una de las fuentes comunes disponibles o subir tu propia fuente personalizada:
Los ajustes de fuente en los **Layout settings** se aplican a todos los componentes del paywall de forma predeterminada. Puedes sobrescribir estos ajustes para elementos específicos, como cuadros de texto o listas, al editarlos individualmente. Si cambias la fuente predeterminada en los **Layout settings**, no afectará a los elementos que ya tengan fuentes individuales. Aprende cómo subir una fuente personalizada [aquí](using-custom-fonts-in-paywall-builder).
## Layout del contenido \{#content-layout\}
No tienes que ajustar manualmente los márgenes y el ancho de cada elemento de contenido del paywall. Ve a **Content layout** para modificar todos los ajustes siguientes para todos los elementos de contenido a la vez:
- **Default child margin**: Define el espacio alrededor de cada elemento hijo.
- **Spacing**: Define el espacio entre elementos dentro de un layout.
- **Max width**: Establece el ancho máximo de los elementos para optimizar el layout en iPads. Recomendamos 600pt para un diseño limpio y equilibrado.
:::warning
El parámetro Max width solo está disponible a partir de Adapty SDK v3.7.0 o superior.
:::
Para ajustar el layout de un elemento específico —como establecer el ancho máximo del footer— ve a la sección **Layout** en **App Icon, Header, Feature List, Products** o **Footer**.
## Botones superiores \{#top-buttons\}
Añade hasta 2 botones superiores a tu paywall para ofrecer a los usuarios opciones como cerrar el paywall. Personaliza su apariencia y comportamiento de la siguiente manera:
1. Activa el toggle **Top Button** o **Top Button 2**.
2. Elige el aspecto y la posición del botón. La vista previa se actualizará al instante.
| Ajuste del botón | Descripción |
|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Action | Elige la acción que el paywall debe ejecutar cuando un usuario pulse este botón. Si eliges acciones estándar, el paywall generará un evento estándar que podrás gestionar de forma estándar en el código de tu app.
Si eliges una acción personalizada, deberás procesar la acción por su `CustomActionID` en el código de tu app.
| | Style | Elige si quieres que el botón tenga aspecto de icono o de texto. Si eliges un icono, selecciona el tipo de icono en el campo correspondiente. | 3. Para retrasar la aparición del botón, ajusta el control deslizante **Show after delay**.
---
# File: paywall-head-picture
---
---
title: "Imagen principal del paywall"
description: "Personaliza tu paywall con una imagen principal para mejorar las tasas de conversión en Adapty."
---
La imagen principal es el elemento estrella de tu paywall: define el tono, establece el tema y capta la atención del usuario desde el primer momento. Esta imagen juega un papel fundamental en el aspecto y la sensación de tu paywall tanto en iOS como en Android.
:::warning
Esta sección describe el nuevo Paywall Builder, que funciona con los SDKs de iOS, Android y React Native en la versión 3.0 o superior, y con los SDKs de Flutter y Unity en la versión 3.3.0 o superior. Para obtener información sobre el Paywall Builder anterior, compatible con Adapty SDK v2.x o versiones anteriores, consulta [Imagen principal del Paywall Builder heredado](paywall-layout-and-products-legacy#main-image-and-sizing).
:::
## Formato y tamaño de la imagen principal \{#hero-image-format-and-size\}
La imagen principal es el elemento central del diseño de tu paywall, esencial para captar la atención de los usuarios y animarles a actuar. Sigue estas pautas para asegurarte de que tu imagen sea efectiva y visualmente atractiva:
- **Formatos**: JPG y PNG.
- **Tamaño recomendado**: Archivos de hasta 2 MB para una carga más rápida.
- **Composición de la imagen**: Las fotos con el objeto principal centrado y rodeado de espacio suficiente suelen transmitir el mensaje de forma efectiva.
- **Imágenes de impacto**: Las fotos emotivas o con colores vibrantes funcionan muy bien.
- **Uso de gráficos**: Ideal para añadir atractivo visual, con espacios separados reservados para el texto.
Tienes control total sobre el tamaño de la imagen principal: ajusta sus proporciones para conseguir el equilibrio visual que desees en tu paywall. Especifica el tamaño de la imagen como un porcentaje del área total de la pantalla para una alineación perfecta.
## Opciones de diseño de la imagen principal \{#hero-picture-layout-options\}
La **imagen principal superpuesta** añade profundidad y dinamismo a tu paywall. Al estar posicionada como fondo fijo en la parte inferior, crea un efecto impresionante mientras el resto de los elementos se desplazan sobre ella. Esto hace que la imagen principal parezca estática, ofreciendo una experiencia visualmente atractiva mientras los usuarios hacen scroll por el contenido.
El **diseño transparente** ofrece una imagen principal a pantalla completa y muy llamativa que capta la atención de inmediato. Este diseño es perfecto para mostrar una selección limitada de productos o contenido, ocupando toda la pantalla y generando un impacto poderoso y directo sin necesidad de hacer scroll.
:::note
Usa el diseño transparente para mostrar contenido mínimo, ya que no implica scroll, lo que hace que tu mensaje sea claro e impactante.
:::
El **diseño plano** imita una landing page fluida, presentando todos los elementos en una capa continua y desplazable. Los usuarios disfrutan de una narrativa suave y cohesionada mientras hacen scroll por el contenido, perfecta para integrar tus productos o historias de forma efectiva en un flujo unificado.
:::note
Ideal para contar historias o presentar una serie de ofertas, el diseño plano te permite crear una secuencia atractiva que cautiva a los usuarios.
:::
## Máscara de la imagen principal \{#hero-image-mask\}
El **tipo de máscara** define la forma de la imagen principal, permitiéndote aplicar efectos creativos que mejoran la presentación visual. Para los diseños de imagen plana o superpuesta, elige entre distintos tipos de máscara para adaptar el diseño a tus necesidades.
Ajusta el redondeo de la máscara de la imagen usando valores numéricos para conseguir el aspecto perfecto para tu imagen principal.
## Cómo eliminar una imagen principal \{#how-to-remove-a-hero-image\}
Para eliminar una imagen principal de un paywall:
1. Abre el elemento **Hero image**.
2. Cambia su altura a cero.
---
# File: paywall-video
---
---
title: "Vídeo hero del paywall"
description: "Mejora los paywalls con contenido de vídeo para aumentar el engagement en Adapty."
---
Añadir un clip de vídeo a tu paywall es una forma estupenda de captar la atención de los usuarios y aumentar las conversiones. Los vídeos explican tus ofertas con mayor claridad, destacan las funciones clave y crean una experiencia más dinámica y visualmente atractiva.
:::warning
El vídeo hero es compatible con el SDK de Adapty en las siguientes versiones:
- iOS: desde v3.1.0
- Android: desde v3.1.1
- React Native: desde v3.1.0
- Flutter: desde v3.2.0
- Unity: desde v3.3.0
Si el vídeo no es compatible o en casos de respaldo, se mostrará el primer fotograma del vídeo en su lugar.
:::
Añade el **Hero video** en lugar del elemento **Hero image**:
1. Primero, activa el modo de vídeo.
2. Luego, arrastra y suelta tu archivo de vídeo en el área **Video file**.
## Formatos compatibles \{#supported-formats\}
| Especificación | Detalles |
|--------------------|----------------|
| Extensiones | MP4 y WEBM |
| Tamaño mínimo | 640×480 |
| Duración máxima | 30 seg |
| Audio | No compatible |
---
# File: paywall-product-block
---
---
title: "Lista de productos del paywall"
description: "Descubre cómo configurar los bloques de productos del paywall en Adapty para optimizar las compras in-app."
---
La lista de productos es un elemento clave de tu paywall que muestra tus ofertas de forma organizada y atractiva. Esta lista es fundamental para guiar a los usuarios hacia la compra.
La pestaña **Content** contiene los productos que se mostrarán en el paywall. Son los mismos productos que añadiste al paywall cuando lo creaste.
Puedes ajustar la lista de productos. Esto afectará a la lista de productos en la pestaña **General** del paywall.
Después de revisar la lista de productos:
1. Elige qué producto debe estar preseleccionado por defecto en el campo **Selected product**.
2. Define cómo debe verse un producto cuando está seleccionado o no en la pestaña **Style** de la sección **Products**.
3. Configura la vista general del bloque en la pestaña **Layout** o [añade grupos de productos](#add-products-group) para combinar diseños.
:::warning
Esta sección describe el nuevo Paywall Builder, que funciona con los SDK de iOS, Android y React Native versión 3.0 o superior, y los SDK de Flutter y Unity versión 3.3.0 o superior. Para más información sobre el Paywall Builder antiguo compatible con el SDK de Adapty v2.x o anterior, consulta [Productos del paywall en el Paywall Builder antiguo](paywall-layout-and-products-legacy#products).
:::
## Personalización de la vista del producto \{#product-view-customisation\}
Mejorar el atractivo visual de determinados productos puede reorientar significativamente la atención del usuario. Destacar un producto o una oferta especial puede animar a los usuarios a centrarse en él. Veamos algunas opciones de personalización muy útiles.
### Insignia del producto \{#product-badge\}
Una insignia de producto es una pequeña etiqueta que se puede añadir a un producto. Esta insignia puede aportar información promocional adicional y orientar la elección del usuario. El tamaño de la insignia se ajusta automáticamente al texto, y su posición se optimiza según el diseño de tu paywall.
Para añadir una insignia de producto:
1. Activa el interruptor **Product badge** en la configuración de un producto específico.
2. Personaliza la vista y el texto de la insignia según tus necesidades de diseño.
### Producto preseleccionado \{#selected-product\}
Para el flujo de compra **Products as list + purchase button**, puedes **preseleccionar** un producto para orientar sutilmente a los usuarios hacia él. Esto puede ser especialmente eficaz para guiar la elección del usuario.
Si añades varios [grupos de productos](#add-products-group), la misma opción **Selected product** se aplicará a todos los grupos.
Para preseleccionar un producto:
1. Abre el elemento **Products**.
2. En la pestaña **Content**, elige el producto que quieres preseleccionar en la lista desplegable **Selected product**.
3. Ajusta la vista del producto seleccionado y la vista predeterminada de los demás productos en la pestaña **Style** si es necesario.
### Producto destacado \{#highlighted-product\}
Para el flujo de compra **Products as purchase buttons**, puedes **destacar** un producto preferido para convertirlo en la opción principal y captar de inmediato la atención del usuario.
Para destacar un producto:
1. En el panel izquierdo, elige el producto que quieres destacar.
2. En la subsección **Style**, ajusta el diseño para que el producto destaque más.
### Ofertas del producto \{#product-offers\}
Cada producto puede mostrar texto diferente para las ofertas en la subsección **Text**. La pestaña **Default** contiene el texto que se muestra sin oferta.
Es un buen lugar para usar:
- [variables de etiqueta](paywall-builder-tag-variables) para contenido dinámico y localizado
- [etiquetas personalizadas](custom-tags-in-paywall-builder) para tu propio contenido dinámico
Empieza a escribir con un corchete angular y Adapty sugerirá las variables de etiqueta disponibles para insertar datos localizados de los stores.
## Cambiar entre 2 conjuntos de productos con un interruptor de prueba \{#switch-between-2-product-sets-by-trial-toggle\}
Para crear una experiencia de usuario más versátil, puedes permitir a los usuarios cambiar entre dos conjuntos de productos usando un interruptor. Esto es especialmente útil para diferenciar entre productos estándar y pruebas.
Para añadir un interruptor:
1. En el elemento **Products**, cambia la opción **Products grouping** a **Toggle (for free trials and other offers)**. Esto añadirá dos subsecciones: **Toggle on** y **Toggle off**.
2. Añade productos a ambas subsecciones para crear las vistas para cuando el interruptor esté activado o desactivado.
3. En el elemento **Toggle**, establece el **Default state** para elegir si el interruptor debe comenzar activado o desactivado en el paywall.
## Cambiar entre conjuntos de productos por pestañas \{#switch-between-product-sets-by-tab\}
Las pestañas del paywall te permiten agrupar tus productos por categorías, mostrando todas las opciones posibles a tus usuarios. Son especialmente útiles si:
- Tu app ofrece varios planes semanales, mensuales o anuales
- Tienes diferentes niveles como Plus, Gold o Premium
También puedes añadir elementos como listas de características en las pestañas para ayudar a los usuarios a ver las diferencias entre niveles.
Para añadir pestañas:
1. En el elemento **Products**, establece **Products grouping** en **Tabs (for comparing plan groups)**. Esto dividirá tus productos en dos grupos de pestañas iniciales.
2. Si necesitas más pestañas, haz clic en **Add tab group**.
3. Organiza tus productos dentro de estas pestañas.
4. Abre el primer grupo de pestañas y en **Tab title** introduce el nombre que aparecerá en el paywall.
5. Asigna un nombre interno a la pestaña en un campo separado para facilitar su identificación. Este nombre no será visible en el paywall, pero puede ayudarte a identificar la pestaña en las listas.
6. Repite los pasos 4-5 para cada pestaña.
7. Elige qué pestaña estará activa cuando el usuario abra el paywall. Ve a **Tab control** y selecciona la pestaña predeterminada en la lista **Selected tab**.
## Mostrar productos adicionales bajo un botón \{#show-extra-products-under-a-button\}
Para mantener tu paywall simple, puedes ocultar algunos productos o grupos de productos bajo un botón (como "Ver más planes" o la etiqueta que prefieras).
Esto ayuda a los usuarios a centrarse primero en tus principales opciones y, al mismo tiempo, les da la posibilidad de explorar otros planes si lo desean.
Es una forma estupenda de hacer el paywall más limpio y mejorar las conversiones.
Así se hace:
1. En el elemento **Products**, establece la opción **Products grouping** en **Button (for more alternative plans)**. Esto dividirá tus productos en dos grupos: **Shown** y **More plans**.
2. Distribuye tus productos entre estos grupos. **Shown** es para los productos que quieres mostrar de inmediato. **More plans** es para los productos ocultos tras el botón, que solo se muestran cuando el usuario hace clic en él.
3. Personaliza el texto y el diseño del botón en el elemento **View more plans** según tus necesidades.
Estas opciones te ayudan a crear una lista de productos clara y visualmente atractiva que guía a los usuarios hacia la compra.
## Mostrar planes adicionales en una hoja inferior \{#show-extra-plans-in-a-bottom-sheet\}
Para simplificar tu paywall, puedes ocultar algunos productos y mostrarlos solo cuando el usuario haga clic en un botón (como "Ver más planes" o la etiqueta que elijas).
Esta acción abre una hoja deslizante desde abajo con los productos ocultos.
Esta configuración ayuda a los usuarios a centrarse primero en tus opciones principales y, al mismo tiempo, les da flexibilidad para explorar planes adicionales si les interesa.
Es una forma eficaz de simplificar el paywall y potencialmente aumentar las conversiones.
Así se hace:
1. En el elemento **Products**, establece la opción **Products grouping** en **Bottom Sheet (for more alternative plans)**. Esto dividirá tus productos en dos grupos: **Shown** y **More plans**.
2. Distribuye tus productos entre estos grupos. **Shown** es para los productos que quieres mostrar de inmediato. **More plans** es para los productos que están ocultos inicialmente y solo se muestran cuando el usuario hace clic en el botón.
3. Personaliza el texto y el diseño del botón en el elemento **View More Plans** para adaptarlo a tu diseño y mensaje.
4. La hoja inferior usará automáticamente el mismo formato de visualización de la lista de productos que tu paywall principal, ya sean botones de compra independientes o cada producto actuando como un botón. Puedes personalizar el diseño, el texto, el estilo y la selección de producto predeterminada de la hoja inferior.
Estas opciones te ayudan a crear una lista de productos sencilla y fácil de usar.
## Añadir un grupo de productos \{#add-products-group\}
Si quieres aplicar diseños tanto vertical como horizontal a diferentes productos o añadir texto entre productos, puedes añadir otro grupo de productos.
:::note
Añadir un grupo de productos desactiva la opción [Agrupación de productos](#switch-between-2-product-sets-by-trial-toggle). Elige entre añadir otro grupo de productos o agrupar los productos dentro del mismo bloque.
:::
Para añadir un grupo de productos:
1. Haz clic en **Add element** o en **+** en el **Footer**.
2. Selecciona **Products**.
3. Añade productos. Como no puedes tener el mismo producto en grupos diferentes, primero debes eliminarlo del otro grupo.
---
# File: paywall-buttons
---
---
title: "Botón de paywall"
description: "Personaliza los botones de paywall en Adapty para mejorar las interacciones con los usuarios y aumentar las conversiones."
---
:::warning
**Solo las compras y restauraciones se gestionan automáticamente.** Todas las demás acciones de los botones, como cerrar paywalls o abrir enlaces, requieren implementar las respuestas adecuadas en el código de la app:
- [iOS](handle-paywall-actions)
- [Android](android-handle-paywall-actions)
- [React Native](react-native-handle-paywall-actions)
- [Flutter](flutter-handle-paywall-actions)
- [Unity](unity-handle-paywall-actions)
:::
Un botón de paywall es un elemento de interfaz que permite a los usuarios:
- Comprar productos
- Iniciar sesión
- Restaurar compras
- Cerrar el paywall
- Activar acciones personalizadas (por ejemplo, abrir otro paywall)
:::info
Esta sección describe el nuevo Paywall Builder, que funciona con:
- SDKs de iOS, Android y React Native versión 3.0 o superior
- SDKs de Flutter y Unity versión 3.3.0 o superior
:::
### Botones de compra \{#purchase-buttons\}
Los botones de compra:
- Se conectan a los productos seleccionados en tu paywall
- Inician la compra al pulsarlos
Cuando añades un botón de compra a tu paywall, este procesa automáticamente las compras que realizan tus usuarios. Por tanto, no necesitas gestionar las compras en el código de la app.
:::note
Puedes llamar más la atención sobre los botones de compra animándolos. El Paywall Builder admite actualmente los tipos de animación **Arrow** y **Pulse**. Ten en cuenta que, para añadir la animación **Arrow**, primero debes configurar el **Arrow icon** en la sección **Content**.
Cada animación te permite elegir una opción de aceleración (Linear, Ease In, Ease Out, Ease In Out) para controlar cómo se acelera o desacelera.
Las animaciones están disponibles en los SDKs de Adapty para iOS, Android, React Native y Flutter a partir de la versión 3.10.0. Consulta la [guía de migración](migration-to-android-310) para Android.
:::
### Enlaces \{#links\}
Para cumplir con algunos requisitos de la store, puedes añadir enlaces a:
- Términos de servicio
- Política de privacidad
- Restauración de compras
Para añadir enlaces:
1. Añade un elemento **Link** en el Paywall Builder.
2. Añade el manejador `openUrl` a tu código:
- [iOS](handle-paywall-actions)
- [Android](android-handle-paywall-actions)
- [React Native](react-native-handle-paywall-actions)
- [Flutter](flutter-handle-paywall-actions)
- [Unity](unity-handle-paywall-actions)
### Botones personalizados \{#custom-buttons\}
Los botones personalizados son necesarios para:
- Cerrar el paywall (`close`)
- Abrir una URL (`openUrl`)
- Restaurar compras (`restore`)
- Iniciar sesión (`login`)
- Activar acciones personalizadas (por ejemplo, abrir otro paywall)
Para que la mayoría de los botones funcionen, debes **gestionar sus IDs de acción en tu código**:
- [iOS](handle-paywall-actions)
- [Android](android-handle-paywall-actions)
- [React Native](react-native-handle-paywall-actions)
- [Flutter](flutter-handle-paywall-actions)
- [Unity](unity-handle-paywall-actions)
Por ejemplo, un botón de cerrar necesita el manejador de la acción `close`.
:::important
`close` se gestiona automáticamente en los SDKs de iOS, Android y React Native. `openUrl` se gestiona automáticamente en los SDKs de iOS y Android. Sin embargo, si es necesario, puedes sobreescribir el comportamiento predeterminado.
`restore` siempre se gestiona automáticamente.
:::
Al gestionar acciones personalizadas en tu código, puedes implementar escenarios como:
- Abrir otro paywall
- Ejecutar varias acciones en secuencia (como cerrar y abrir)
Ten en cuenta que necesitarás construir estos escenarios usando el sistema de gestión de acciones; no son funciones integradas.
---
# File: paywall-carousel
---
---
title: "Carrusel de paywall"
description: "Configura carruseles de paywall en Adapty para aumentar el engagement y las suscripciones."
---
Un carrusel es un conjunto dinámico de tarjetas deslizables que se pueden mover hacia la izquierda o la derecha, creando una experiencia visual atractiva. Es una herramienta fantástica para diseñar paywalls que no solo llamen la atención, sino que también enganchen a los usuarios con contenido interactivo.
:::warning
Los carruseles solo están disponibles en el [nuevo Paywall Builder](adapty-paywall-builder), que funciona con los SDKs de iOS, Android y React Native versión 3.0 o superior, y los SDKs de Flutter y Unity versión 3.3.0 o superior. El Paywall Builder heredado con el SDK de Adapty v2.x o anterior no admite la funcionalidad de carrusel de paywall.
:::
Aprovecha el poder de los carruseles para elevar el atractivo de tu paywall:
1. **Añade tarjetas**: Empieza añadiendo tarjetas a tu carrusel; cada una es un lienzo para tu toque creativo.
2. **Personaliza las tarjetas**: Rellena tus tarjetas con distintos elementos: imágenes, texto, botones y más. El ajuste de altura del carrusel garantiza que todas las tarjetas tengan el mismo tamaño, dando un aspecto elegante y uniforme.
Saca partido de la flexibilidad de los carruseles para mostrar productos destacados, resaltar ofertas exclusivas o contar historias convincentes. Con este elemento tan dinámico, tus paywalls no solo destacarán, sino que también ofrecerán una experiencia de usuario fluida e inmersiva.
---
# File: paywall-card
---
---
title: "Tarjeta de paywall"
description: "Diseña e implementa tarjetas de paywall en Adapty para mejorar la participación."
---
Una tarjeta es un elemento de paywall que combina varios otros elementos en un único bloque. La tarjeta en sí puede ser visible o no, según lo que necesites. Para hacerla visible, añádele un fondo o imagen de fondo, marco, etc.
:::warning
Las tarjetas de paywall solo están disponibles en el [nuevo Paywall Builder](adapty-paywall-builder), que funciona con los SDKs de iOS, Android y React Native versión 3.0 o superior, y los SDKs de Flutter y Unity versión 3.3.0 o superior. El Paywall Builder heredado con el SDK de Adapty v2.x o anterior no admite la funcionalidad de tarjetas de paywall.
:::
1. Añade una tarjeta como elemento independiente a un paywall o a otro elemento de paywall, por ejemplo, a un carrusel.
2. Añade los elementos que necesites dentro de la tarjeta.
3. Configura la apariencia de la tarjeta: fondo, forma, marco, etc.
---
# File: paywall-timer
---
---
title: "Temporizador de paywall"
description: "Usa la función de temporizador de paywall de Adapty para aumentar las conversiones y crear urgencia."
---
El temporizador del paywall es una herramienta ideal para promocionar ofertas especiales y de temporada con límite de tiempo. Sin embargo, es importante tener en cuenta que este temporizador no está vinculado a la validez de la oferta ni a la duración de la campaña. Es simplemente una cuenta regresiva independiente que parte del valor que tú configures y disminuye hasta cero. Cuando el temporizador llega a cero, no ocurre nada: simplemente se queda en cero.
:::warning
Los temporizadores de paywall solo están disponibles en el [nuevo Paywall Builder](adapty-paywall-builder), que funciona con los SDKs de iOS, Android y React Native versión 3.0 o superior, y los SDKs de Flutter y Unity versión 3.3.0 o superior. El Paywall Builder heredado con el SDK de Adapty v2.x o anterior no es compatible con la funcionalidad de temporizadores de paywall.
:::
Puedes personalizar el texto antes y después del temporizador para crear el mensaje que quieras, por ejemplo: "La oferta termina en: 10:00 seg."
1. Añade un temporizador como elemento independiente en un paywall o dentro de otro elemento del paywall, como una tarjeta.
2. Configura los ajustes del temporizador: formato y separador, valor inicial, texto antes y después (si lo necesitas), color, fuente, espaciado, etc.
## Modo del temporizador \{#timer-mode\}
Puedes controlar el comportamiento del temporizador cuando los usuarios lo ven mediante el parámetro **Timer mode**. Hay 3 modos estándar que funcionan sin configuración adicional: simplemente selecciona la opción que necesites en la lista desplegable:
| Modo | Descripción |
| ------------------------------------- | ------------------------------------------------------------ |
| **Reset timer on every paywall view** | El temporizador se reinicia cada vez que el usuario ve el paywall, comenzando desde el valor inicial cada vez. |
| **Reset timer on every app launch** | El temporizador comienza la primera vez que el usuario ve el paywall y sigue contando en primer plano o en segundo plano hasta que se reinicia la aplicación. Si el usuario ve el paywall varias veces en la misma sesión, verá el mismo temporizador en cuenta regresiva. Una vez que se cierra la aplicación, el temporizador se reinicia, y la próxima vez que se abra la aplicación, el temporizador vuelve a empezar desde el principio. |
| **Keep timer across app launches** | El temporizador comienza la primera vez que el usuario ve el paywall y sigue contando en primer plano o en segundo plano, incluso si se cierra la aplicación. El usuario verá el mismo temporizador cada vez que vuelva al paywall, independientemente de los reinicios de la aplicación o del paywall. |
| **Developer defined** | Puedes configurar cualquier temporizador que necesites directamente en el código de tu aplicación. Empieza introduciendo un **Timer ID** y luego úsalo en tu código tal como se explica en la sección [Cómo configurar temporizadores definidos por el desarrollador en tu aplicación](paywall-timer#how-to-set-up-developer-defined-timers-in-your-mobile-app) para configurar el temporizador como prefieras. |
## ¿Qué ocurre cuando termina el temporizador? \{#what-happens-when-the-timer-ends\}
Puedes personalizar qué sucede cuando se agota el temporizador. ¿Mostrar otra pantalla con una nueva oportunidad? ¿O quizás un paywall diferente? Requiere algo de código, pero con nuestra documentación lo resolverás sin problema.
1. Activa el toggle **Trigger custom action when the timer runs out**.
2. Introduce el ID de la acción que quieres activar en el campo **Timer action ID**.
3. Usa este ID de acción en tu app para definir qué debe ocurrir cuando el temporizador termine. Trátalo como cualquier otra acción personalizada, tal como se explica en nuestra guía **Manejo de Eventos: Acciones** para [iOS](ios-handling-events#user-generated-events) y [Android](android-handling-events#user-generated-events).
## ¿Cómo configurar temporizadores definidos por el desarrollador en tu app? \{#how-to-set-up-developer-defined-timers-in-your-mobile-app\}
Para usar temporizadores personalizados en tu app, crea un objeto que siga el protocolo `AdaptyTimerResolver`. Este objeto define cómo debe renderizarse cada temporizador personalizado. Si lo prefieres, puedes usar directamente un diccionario `[String: Date]`, ya que ya cumple con este protocolo. Aquí tienes un ejemplo:
:::warning
El modo oscuro es compatible con:
- iOS: a partir de la v3.1.0
- Android: a partir de la v3.1.1
- React Native: a partir de la v3.1.0
- Flutter: a partir de la v3.2.0
- Unity: a partir de la v3.3.0
También está disponible en paywalls de respaldo.
:::
Para configurar el modo oscuro en tu paywall:
1. Primero, activa el modo oscuro en **Layout settings** del paywall:
2. Ahora puedes configurar los modos claro y oscuro por separado. Para cambiar al modo oscuro, activa el interruptor **Dark Mode** en el menú izquierdo del paywall:
3. Una vez que hayas cambiado al modo oscuro, puedes ajustar los elementos según sea necesario. El modo oscuro te permite usar una imagen o vídeo diferente, así como opciones de color y fondo independientes.
---
# File: paywall-builder-tag-variables
---
---
title: "Variables de etiqueta para información de productos en Paywall Builder"
description: "Usa variables de etiqueta en el Paywall Builder de Adapty para personalizar la experiencia del usuario y aumentar las ventas."
---
El Paywall Builder de Adapty te permite personalizar todo el texto de tus productos y sus ofertas. Si trabajas con varios idiomas, te recomendamos encarecidamente usar variables.
### Cómo funciona \{#how-it-works\}
Cuando añades variables de etiqueta de nuestra lista a los textos de tus productos, el SDK obtiene los datos localizados ya precargados de los stores para reemplazar las etiquetas. Esto garantiza que el texto de tu paywall siempre esté perfectamente adaptado al idioma correcto.
**Ejemplo**: Supongamos que tienes una "Suscripción Premium" disponible tanto en EE. UU. como en España. En EE. UU. podría mostrarse como "Premium Subscription for $4.99/month", mientras que en España aparecería como "Suscripción Premium por €4,99/mes".
Las variables de etiqueta te permiten localizar automáticamente estas cadenas de texto a partir de los datos del store, garantizando que los títulos y precios sean siempre correctos.
:::warning
Esta sección describe el nuevo Paywall Builder, que funciona con los SDKs de iOS, Android y React Native en la versión 3.0 o superior, y con los SDKs de Flutter y Unity en la versión 3.3.0 o superior. Para información sobre el Paywall Builder legacy compatible con el SDK de Adapty v2.x o anterior, consulta [Variables de etiqueta en el Paywall Builder legacy](paywall-builder-tag-variables-legacy).
:::
### Cómo usar las variables de etiqueta \{#how-to-use-tag-variables\}
:::note
Las variables de etiqueta solo se pueden usar al describir productos y ofertas en el componente Product del Paywall Builder.
:::
1. En el panel izquierdo del Paywall Builder, selecciona el producto que quieres personalizar.
2. Usa las variables de la [tabla a continuación](paywall-builder-tag-variables#full-list-of-variables) en cualquier campo de texto para describir el producto y sus ofertas.
4. Comprueba la vista previa en el lado derecho de la pantalla para asegurarte de que todo se muestra correctamente.
:::note
La vista previa no usa valores reales para reemplazar las variables; estos solo los recupera el SDK en el dispositivo. Sin embargo, sí muestra datos de plantilla en el mismo formato que el resultado real. Puedes desactivar este comportamiento haciendo clic en el icono del ojo en la esquina inferior derecha de la vista previa y desactivando el toggle **Tags preview values**. La vista previa mostrará entonces los valores reales de las variables:
:::
### Lista completa de variables \{#full-list-of-variables\}
| Variable de etiqueta | Descripción | Ejemplo |
| :------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------- |
| `
2. Después de añadir la etiqueta personalizada, asegúrate de introducir un texto de respaldo. Este texto aparecerá en tu app si no reconoce una etiqueta personalizada concreta, evitando que los usuarios vean la etiqueta mostrada como código. El texto de respaldo reemplaza toda la línea que contiene la etiqueta personalizada.
## Cómo usar etiquetas personalizadas en tu app \{#how-to-use-custom-tags-in-your-mobile-app\}
Para usar etiquetas personalizadas en tu app, crea un objeto `tagResolver` —un diccionario o mapa que asocia etiquetas personalizadas con los valores de cadena que las sustituirán cuando se renderice el paywall. Aquí tienes un ejemplo:
---
# File: using-custom-fonts-in-paywall-builder
---
---
title: "Fuentes personalizadas en Paywall Builder"
description: "Mejora el Paywall Builder de Adapty con fuentes personalizadas para optimizar el diseño."
---
La coherencia visual es clave para un buen diseño. Al crear paywalls sin código, puede que quieras usar una fuente personalizada que encaje con el resto de tu app. Aquí explicamos cómo personalizar fuentes y cómo puedes usarlas.
:::warning
Esta sección describe el nuevo Paywall Builder, que funciona con los SDKs de iOS, Android y React Native versión 3.0 o superior, y los SDKs de Flutter y Unity versión 3.3.0 o superior. Para información sobre el Paywall Builder heredado compatible con el SDK de Adapty v2.x o anterior, consulta [Fuentes personalizadas en el Paywall Builder heredado](using-custom-fonts-in-legacy-paywall-builder).
:::
## Qué se puede personalizar \{#what-can-be-customized\}
Cada elemento de texto en el Paywall Builder puede tener su propia fuente y estilo. Puedes ajustarlo en los controles de fuente de cada elemento de texto:
En algunos casos, es más práctico cambiar la fuente de todo el paywall. Puedes hacerlo en la sección Layout del Paywall Builder [ajustando la Fuente del Paywall](paywall-layout-and-products#font-settings-of-your-paywall).
## Fuentes disponibles por defecto \{#fonts-available-by-default\}
Cuando creas un paywall en el Builder, Adapty usa una fuente del sistema por defecto. Esto normalmente significa SF Pro en iOS y Roboto en Android, aunque puede variar según el dispositivo. También puedes elegir entre fuentes de uso común como Arial, Times New Roman, Courier New, Georgia, Palatino y Verdana. Cada una de estas fuentes incluye varias opciones de estilo:
:::note
Estas fuentes no se incluyen como parte del SDK de Adapty y solo se usan con fines de previsualización. No podemos garantizar que funcionen perfectamente en todos los dispositivos. Sin embargo, en nuestras pruebas, la mayoría de los dispositivos las reconocen sin ningún esfuerzo adicional por tu parte. También puedes [consultar qué fuentes están disponibles por defecto en iOS](https://developer.apple.com/fonts/system-fonts/).
:::
## Cómo añadir una fuente personalizada al Adapty Dashboard \{#how-to-add-a-custom-font-to-the-adapty-dashboard\}
Si necesitas más opciones de las que ofrece la configuración por defecto, puedes añadir una fuente personalizada. Una vez añadida, estará disponible en toda la app y podrás usarla en cualquier línea de texto de cualquier paywall.
1. Elige **Add custom font** en cualquiera de los desplegables de fuente:
2. En la ventana **Add Custom Font**:
1. Sube el archivo de fuente (tamaño máximo: 10 MB).
2. Introduce un nombre para referenciarlo en el Paywall Builder.
3. Especifica los nombres de fuente correctos para ambas plataformas.
4. Asegúrate de que el archivo de fuente esté incluido en el bundle de tu app si aún no lo has añadido.
:::warning
El archivo de fuente que subes no se envía al dispositivo; solo se usa con fines de previsualización. Nuestro SDK recibe únicamente las cadenas de texto que referencian la fuente a usar al renderizar el paywall. Por eso, debes incluir el mismo archivo de fuente en el bundle de la app y proporcionar los nombres de fuente correctos para cada plataforma para que todo funcione sin problemas. No te preocupes, no llevará mucho tiempo.
:::
:::note
Al subir el archivo de fuente a Adapty, confirmas que tienes derecho a usarla en tu app.
:::
## Cómo obtener el nombre de fuente correcto en iOS \{#getting-the-correct-font-name-on-ios\}
Hay dos formas de obtener el ID correcto de una fuente: la primera requiere algo de código, y la segunda consiste en usar una app llamada "Font Book", disponible en macOS.
Si ya has añadido una fuente personalizada al bundle de tu app, probablemente ya la estás referenciando por su nombre de fuente. Para confirmarlo, llama a `UIFont.familyNames()` para obtener el nombre de familia de la fuente y luego úsalo en `UIFont.fontNames(forFamilyName: familyName)`. Puedes hacerlo en `viewDidLoad` y después eliminar el fragmento de código:
```swift showLineNumbers title="Swift"
override func viewDidLoad() {
super.viewDidLoad()
...
for family in UIFont.familyNames.sorted() {
print("Family: \(family)")
let names = UIFont.fontNames(forFamilyName: family)
for fontName in names {
print("- \(fontName)")
}
}
}
```
El `fontName` del fragmento anterior es lo que buscas. Podría tener un aspecto similar a "MyFont-Regular".
El segundo método es más sencillo: instala la fuente en tu Mac, abre la app **Font Book**, encuentra la fuente y usa su `PostScript name`:
## Cómo obtener el nombre de fuente correcto en Android \{#getting-the-correct-font-name-on-android\}
Si has añadido correctamente el archivo de fuente a la carpeta de recursos, simplemente proporciona el nombre del archivo. Asegúrate de que esté en minúsculas y solo contenga letras, números y guiones bajos; de lo contrario, puede que no funcione.
Puedes confirmar que el nombre del archivo es correcto llamando a `ResourcesCompat.getFont(context, R.font.my_font)`, donde `my_font` es el nombre de archivo que estás usando. En este caso, `my_font` es exactamente lo que debes introducir al crear una fuente personalizada en Adapty.
## Cómo añadir los archivos de fuente al bundle de tu app \{#adding-the-font-files-to-your-apps-bundle\}
Si ya estás usando una fuente personalizada en otra parte de tu app, solo tienes que añadir las fuentes del paywall de la misma manera. Si no es así, asegúrate de incluir el archivo de fuente en el proyecto y bundle de tu app. Aquí puedes leer cómo hacerlo:
- En iOS: [En la documentación oficial de Apple](https://developer.apple.com/documentation/uikit/adding-a-custom-font-to-your-app)
- En Android: [En la documentación oficial de Android](https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml)
:::important
Al descargar paquetes de fuentes desde Adapty, recibirás todas las variaciones de fuente en un archivo comprimido. Añade al bundle de tu app solo los archivos de fuente específicos que usa tu paywall para minimizar el tamaño de la app. Por ejemplo, si en tu paywall solo usas `OpenSans-Regular.ttf`, no incluyas `OpenSans-Bold.ttf` en el bundle de tu app.
:::
---
# File: migration-to-new-paywall-builder
---
---
title: "Migración al nuevo Paywall Builder"
description: "Migra al nuevo Paywall Builder de Adapty para mejorar el flujo de suscripción."
---
Estamos encantados de presentar el [**nuevo Paywall Builder**](adapty-paywall-builder). Esta avanzada herramienta sin código está diseñada para hacer que la creación de paywalls personalizados sea más intuitiva y potente que nunca, permitiéndote diseñar paywalls atractivos y visualmente cuidados con total facilidad. ¡No necesitas conocimientos técnicos ni de diseño!
## Características clave del nuevo Paywall Builder \{#key-features-of-the-new-paywall-builder\}
- **Amplia selección de plantillas**: Elige entre una gran variedad de plantillas diseñadas profesionalmente para comenzar a crear tu paywall. Estas plantillas ofrecen distintos estilos y disposiciones para adaptarse a diferentes necesidades y preferencias.
- **Mayor flexibilidad**: Disfruta de más libertad creativa gracias al uso de capas de diseño y nuevos elementos como carruseles, tarjetas, listas de productos y pies de página. Estas mejoras te dan la libertad creativa para construir cualquier tipo de paywall que tengas en mente.
- **Elementos existentes mejorados**: Los elementos existentes han sido significativamente mejorados, ofreciendo más opciones y capacidades para dar vida a tus ideas de paywall.
## Versiones paralelas del Paywall Builder \{#parallel-paywall-builder-versions\}
Adapty ofrece dos versiones del Paywall Builder de forma simultánea:
- **Nuevo Paywall Builder**: Ubicado en la pestaña **Builder & Generator** del paywall en el Adapty Dashboard, esta versión es la más reciente y versátil. Los paywalls creados aquí requieren los SDK de iOS, Android y React Native en la versión 3.0 o superior, y los SDK de Flutter y Unity en la versión 3.3.0 o superior.
- **Legacy Paywall Builder**: Disponible en la pestaña **Legacy Builder**, esta versión obsoleta solo debe usarse para dar soporte a versiones antiguas de la app con SDK inferiores a v3.x.x. Recomendamos no usarla para nuevos paywalls, ya que pronto quedará en desuso.
## Migrar paywalls al nuevo builder \{#migrating-paywalls-to-the-new-builder\}
Migrar un paywall del builder antiguo al nuevo creará una versión nueva de tu paywall en la pestaña **Builder & Generator**. Esta versión se puede editar con el nuevo Paywall Builder y se mostrará en apps con el SDK de Adapty v3.0 o posterior. La versión antigua permanece en la pestaña **Legacy Builder** y es compatible con apps con SDK 2.x o anterior.
Mantendrás los paywalls en ambos formatos por separado, y los cambios en un formato no afectarán al otro.
## Pasos para migrar un paywall \{#steps-to-migrate-a-paywall\}
Para migrar un paywall al nuevo Paywall Builder:
1. Abre el paywall que quieres migrar.
2. Ve a la pestaña **Builder & Generator**.
3. Haz clic en **Migrate paywall**.
4. Una vez completada la migración, revisa el resultado y asegúrate de que el paywall tiene el aspecto esperado. Si no es así, corrígelo.
5. Haz clic en **Save**.
6. Si hay algún problema, aparecerá resaltado en rojo para que lo veas de inmediato. Corrígelo y guarda el paywall de nuevo.
Puedes migrar tus paywalls de uno en uno para revisarlos y corregirlos según sea necesario.
:::info
Ten en cuenta que los paywalls creados en el nuevo Paywall Builder solo aparecerán en versiones de la app con el SDK de Adapty v3.0 o posterior.
:::
## Valoramos tu opinión \{#we-value-your-feedback\}
Tu opinión es muy importante para nosotros. Si encuentras algún problema o tienes sugerencias de mejora, no dudes en contactarnos. Estamos aquí para ayudarte y mejorar tu experiencia con el nuevo Paywall Builder.
📧 **Contáctanos**: [Soporte de Adapty](mailto:support@adapty.io)
¡Disfruta creando con el nuevo Paywall Builder y lleva tu estrategia de monetización al siguiente nivel con nuestras herramientas y funciones mejoradas!
---
# File: customize-paywall-with-remote-config
---
---
title: "Diseña tu paywall con Remote Config"
description: "Personaliza tu paywall con Remote Config en Adapty para una mejor segmentación."
---
El Remote Config de un paywall es una herramienta muy potente que ofrece opciones de configuración flexibles. Permite usar payloads JSON personalizados para adaptar tus paywalls con precisión. Con él puedes definir parámetros como títulos, imágenes, fuentes, colores y mucho más.
3. Cambia a la pestaña **Remote config**.
El Remote Config tiene 2 vistas:
- [Tabla](customize-paywall-with-remote-config#table-view-of-the-remote-config)
- [JSON](customize-paywall-with-remote-config#json-view-of-the-remote-config)
Tanto la vista **Table** como la vista **JSON** incluyen los mismos elementos de configuración. La única diferencia es una cuestión de preferencia: la vista de tabla ofrece un menú contextual que puede ser útil para corregir errores de localización.
Puedes alternar entre vistas haciendo clic en la pestaña **Table** o **JSON** cuando lo necesites.
Sea cual sea la vista que elijas para personalizar tu paywall, podrás acceder a estos datos desde el SDK usando las propiedades `remoteConfig` o `remoteConfigString` de `AdaptyPaywall` y hacer ajustes en tu paywall. También puedes actualizar los valores del Remote Config de forma programática mediante la [API del servidor](api-adapty/operations/updatePaywall) para modificar dinámicamente las configuraciones del paywall sin tener que actualizar el dashboard manualmente. Aquí tienes algunos ejemplos de cómo puedes usar un Remote Config.
### Vista de tabla del Remote Config \{#table-view-of-the-remote-config\}
Si no estás acostumbrado a trabajar con código y necesitas corregir algunos valores del JSON, Adapty tiene la vista **Table** para ti.
Es una copia de tu JSON en formato de tabla, fácil de leer y entender. El código de colores ayuda a identificar los distintos tipos de datos.
Para añadir una clave, haz clic en el botón **Add row**. Verificamos automáticamente la correspondencia entre valores y tipos, y mostramos una alerta si tus cambios pueden generar un JSON inválido.
Las opciones adicionales de fila son especialmente útiles para las [localizaciones del paywall](add-remote-config-locale):
Ahora es el momento de [crear un placement](create-placement) y añadir el paywall. Después podrás
2. Abre el menú **Localization** para ver todos los idiomas añadidos. Los nuevos idiomas se rellenarán automáticamente con los valores del idioma predeterminado.
Ahora puedes traducir el contenido manualmente, usar IA o exportar el archivo de localización para traductores externos.
## Traducir paywalls con IA \{#translating-paywalls-with-ai\}
La traducción con IA es una forma rápida y eficiente de localizar tu paywall.
Detectamos automáticamente qué líneas nunca se han traducido o han cambiado en inglés desde su última traducción, y las marcamos como pendientes de actualización. Las líneas que ya estaban traducidas y no han cambiado mantendrán su traducción original y no se volverán a traducir.
El formato de texto enriquecido (negrita, cursiva, texto de color, etc.) no se conservará en la versión traducida. Ajusta manualmente el texto traducido según sea necesario.
1. Haz clic en el icono de localización para seleccionar los idiomas a traducir:
- **En el encabezado de la columna del idioma**: Traduce todas las líneas a la vez; ideal para la traducción inicial o cuando actualices el idioma completo.
- **En líneas individuales**: Traduce líneas concretas de forma independiente; útil para hacer cambios puntuales sin afectar al resto de traducciones.
2. Haz clic en **AI Translate** para aplicar las traducciones. Las líneas del paywall se traducirán y se añadirán a la tabla.
## Exportar archivos de localización para traducción externa \{#exporting-localization-files-for-external-translation\}
Puedes exportar archivos de localización para compartirlos con tus traductores y luego importar los resultados traducidos de vuelta a Adapty.
Al exportar con el botón **Export** se crean archivos `.csv` individuales para cada idioma, agrupados en un único archivo comprimido. Si solo necesitas un archivo, puedes exportarlo directamente desde el menú específico del idioma.
Una vez que recibas los archivos traducidos, usa el botón **Import** para subirlos todos a la vez o de forma individual. Adapty validará automáticamente los archivos para asegurarse de que coinciden con el formato correcto y la estructura de configuración del paywall.
### Formato del archivo de importación \{#import-file-format\}
Para que la importación sea correcta, el archivo debe cumplir los siguientes requisitos:
- **Nombre y extensión del archivo:**
El nombre del archivo debe coincidir con el idioma que representa y tener extensión `.csv`. Puedes verificar y copiar el nombre del idioma en el Adapty Dashboard. Si el nombre no se reconoce, la importación fallará.
- **CSV válido:**
El archivo debe tener un formato CSV válido. Los archivos inválidos no se podrán importar.
- **Solo comas como separadores**:
Usa comas como separadores. Otros separadores producirán errores.
- **Línea de encabezado**:
El archivo debe incluir una línea de encabezado.
- **Nombres de columna correctos:**
Los nombres de las columnas deben ser **id** y **value**.
- **Sin entidades adicionales:**
Asegúrate de que el archivo no incluye entidades que no estén presentes en la configuración actual del paywall. Las entidades adicionales producirán errores.
- **Importación parcial:**
El archivo puede incluir todas o solo algunas entidades de la configuración actual del paywall.
| **Problema** | **Solución** |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Los archivos .csv importados no son válidos** | Valida el archivo para asegurarte de que cumple los estándares CSV. Comprueba si faltan comas o hay comas de más, separadores incorrectos, líneas de encabezado ausentes, y verifica que los nombres de columna sean **id** y **value**. |
| **Algunos idiomas no aparecen en la tabla** | Asegúrate de que los nombres de los archivos coincidan exactamente con los nombres de idioma que aparecen en la tabla de localización. Si no coinciden, renómbralos en consecuencia. Verifica también el contenido del archivo para asegurarte de que corresponde a la configuración del paywall. |
## Localización manual \{#manual-localization\}
A veces puede que quieras ajustar traducciones, añadir imágenes distintas para idiomas concretos, o incluso modificar directamente las configuraciones remotas.
1. Elige el elemento que quieras traducir e introduce el nuevo valor. Puedes actualizar tanto valores de tipo **String** como de tipo **List**, o reemplazar imágenes por otras más adecuadas para el idioma.
2. Aprovecha el menú contextual del idioma inglés para resolver problemas de localización de forma eficiente:
- **Copy this value to all locales**: Sobrescribe cualquier cambio realizado en los idiomas no ingleses de la fila seleccionada, reemplazándolos con el valor del idioma inglés.
- **Revert all row changes to original values**: Descarta los cambios realizados durante la sesión actual y restaura los valores a su último estado guardado.
Después de añadir idiomas a un paywall, asegúrate de implementar correctamente los códigos de idioma en el código de tu app. Consulta
:::note
Presta atención al código de idioma (`en`, `fr` e `it`). Deberás pasarlo al método `getViewConfiguration` de nuestro SDK para obtener la localización correcta.
Puedes obtener más información en
4. Haz clic en **Locales** y selecciona los idiomas que quieres admitir. Guarda los cambios para añadir estas localizaciones al paywall.
Ahora puedes traducir el contenido manualmente, usar IA o exportar el archivo de localización para traductores externos.
## Traducir paywalls con IA \{#translate-paywalls-with-ai\}
La traducción con IA es una forma rápida y eficaz de localizar tu paywall.
Puedes traducir tanto valores de tipo **String** como **List**. Por defecto, todas las líneas están seleccionadas (resaltadas en violeta). Las líneas que ya han sido traducidas aparecen en verde y no se incluirán en la nueva traducción por defecto. Las líneas que no están seleccionadas ni traducidas aparecen en gris.
1. Selecciona las líneas que quieres traducir. Es recomendable desmarcar las líneas con IDs, URLs y variables para que la IA no las traduzca.
2. Selecciona los idiomas para la traducción.
3. Haz clic en **AI Translate** para aplicar las traducciones. Las líneas seleccionadas se traducirán y se añadirán al paywall, quedando marcadas en verde.
## Exportar archivos de localización para traductores externos \{#exporting-localization-files-for-external-translation\}
Aunque la localización con IA es cada vez más popular, puede que prefieras un método más fiable, como usar traductores profesionales o una agencia de traducción con experiencia contrastada. En ese caso, puedes exportar los archivos de localización para compartirlos con tus traductores e importar los resultados traducidos de vuelta a Adapty.
Al exportar con el botón **Export** se crean archivos `.json` individuales para cada idioma, agrupados en un único archivo comprimido. Si solo necesitas un archivo, puedes exportarlo directamente desde el menú específico del idioma.
Una vez que hayas recibido los archivos traducidos, usa el botón **Import** para subirlos todos a la vez o de forma individual. Adapty validará automáticamente los archivos para asegurarse de que tienen el formato correcto.
### Formato del archivo de importación \{#import-file-format\}
Para que la importación se realice correctamente, el archivo debe cumplir los siguientes requisitos:
- **Nombre y extensión del archivo:**
El nombre del archivo debe coincidir con la localización que representa y tener extensión `.json`. Puedes verificar y copiar el nombre de la localización en el Adapty Dashboard. Si el nombre no se reconoce, la importación fallará.
- **JSON válido:**
El archivo debe ser un JSON válido. Si no lo es, la importación fallará.
## Localización manual \{#manual-localization\}
A veces puede que quieras ajustar traducciones, añadir imágenes diferentes para localizaciones específicas o incluso modificar las configuraciones remotas directamente.
1. Elige el elemento que quieres traducir e introduce un nuevo valor. Puedes actualizar tanto valores de tipo **String** como **List**, o reemplazar imágenes por otras más adecuadas para la localización.
2. Aprovecha el menú contextual de la localización en inglés para resolver problemas de localización de forma eficiente:
- **Copy this value to all locales**: Sobreescribe los cambios realizados en localizaciones que no sean la inglesa para la fila seleccionada, reemplazándolos con el valor de la localización en inglés.
- **Revert all row changes to original values**: Descarta los cambios realizados durante la sesión actual y restaura los valores al último estado guardado.
Después de añadir localizaciones a un paywall, asegúrate de implementar correctamente los códigos de localización en el código de tu app. Consulta
3. ⚠️ Si eliges Stripe, asegúrate de usar las claves del entorno **Test Mode** aunque la interfaz diga **Sandbox**. De lo contrario, tu web paywall no funcionará. Los **Sandboxes** de Stripe aún no son compatibles.
### Configura la verificación de dominio de Apple Pay \{#set-up-apple-pay-domain-verification\}
En **Settings > Domains**, selecciona tu proveedor de pagos principal para usarlo en la verificación de dominio. Luego, verifica los dominios de tu paywall con el proveedor correspondiente:
**Stripe**:
1. Ve a [Payment method domain settings](https://dashboard.stripe.com/settings/payment_method_domains) y haz clic en **Add a new domain**.
2. Añade `app.funnelfox.com` y tu subdominio personal del paywall (tendrá un aspecto similar a `paywalls-....fnlfx.com`). Para encontrar tu subdominio, ve a **Settings > Domains** y copia el valor de **Hosted subdomain**.
**Paddle**:
1. En la consola de Paddle, ve a **Checkout > Website approval** y haz clic en **Add a new domain**.
2. Añade `app.funnelfox.com` y tu subdominio personal del paywall (tendrá un aspecto similar a `paywalls-....fnlfx.com`). Para encontrar tu subdominio, ve a **Settings > Domains** y copia el valor de **Hosted subdomain**.
El proceso de aprobación en Paddle es manual, por lo que tendrás que esperar hasta que los dominios pasen de `Pending` a `Approved`.
**FunnelFox Billing**:
Sigue las [instrucciones de integración de FunnelFox Billing](https://funnelfox.com/docs/billing/integration-billing-funnelfox).
**SolidGate**:
1. En tu Solidgate Dashboard, ve a **Developers > Apple Pay Domains**.
2. Haz clic en **+ Add new domain** y pega el dominio de tu proyecto (desde **Settings > Domains** en FunnelFox). Añade también tu dominio personalizado, si corresponde.
3. Para usar Apple Pay en modo de vista previa, añade también `http://app.funnelfox.com/`.
## Crea y configura un web paywall \{#create-and-configure-a-web-paywall\}
1. En la página de lista de web paywalls, haz clic en **Create a paywall**.
2. Introduce un nombre para el paywall y haz clic en **Create**.
3. Se te redirigirá a una plantilla básica con dos opciones de suscripción y el botón de compra de Apple Pay.
La primera pantalla muestra los planes de suscripción. La segunda y la tercera son pantallas de pago. Cada pantalla corresponde a un plan que ofreces. Si solo tienes un plan, elimina la pantalla extra. Si tienes más, debes duplicar las pantallas de pago.
La última pantalla que ven los usuarios tras una compra exitosa es donde debes indicar claramente que pueden volver a tu app.
4. Configura la lista de planes: añade o elimina planes y precios. Todos los precios y planes que ves en pantalla no se añaden de forma dinámica, por lo que debes configurarlos manualmente.
5. Añade o configura una pantalla de pago para cada plan que tengas. Te recomendamos añadir el importe total en cada pantalla de pago para que los usuarios sepan cuánto van a pagar antes de hacer clic en el botón de compra.
6. En las pantallas de pago, ya tienes el botón de Apple Pay. Para que funcione, configura en cada pantalla:
1. **Product type**: Selecciona si quieres añadir un período de prueba o un descuento.
2. **Trial period**: Introduce la duración del período de prueba.
3. **Product**: Selecciona tu producto de tu proveedor de pagos.
:::important
Asegúrate de que el producto esté añadido en Adapty. De lo contrario, el resultado de la compra se establecerá por defecto.
:::
4. **Subscription discount**: Opcionalmente, selecciona un cupón de tu proveedor de pagos.
7. Ahora necesitas asociar los planes con las pantallas de pago. En la pantalla de selección de plan, haz clic en el botón **Continue** y selecciona una pantalla de destino para cada plan.
Cuando tengas el paywall listo, necesitas obtener su enlace para activarlo en Adapty. La forma de obtenerlo depende de si lo estás probando o lanzando en el entorno de producción:
1. **Para pruebas en sandbox**: Haz clic en **Preview** en la parte superior derecha y copia el enlace.
2. **Para producción**: Haz clic en **Publish** en la parte superior derecha. Haz clic en **Home** y copia el enlace de la columna **URL**.
¡Listo! Usa este enlace para [continuar con la configuración](web-paywall#step-2-trigger-the-paywall).
---
# File: fallback-paywalls
---
---
title: "Fallback paywalls"
description: "Use fallback paywalls to ensure seamless user experience in Adapty."
---
To maintain a fluid user experience, it is important that you set up **fallback versions** for your [paywalls](paywalls) and [onboardings](onboardings).
When your application loads a paywall, the Adapty SDK requests paywall configuration data from our servers. But what if the device cannot connect to Adapty due to network issues or server outages?
* If the user accessed the paywall before, and the device cached its data, the application loads paywall data **from cache**.
* If the device did not cache the paywall, the application looks for a locally stored configuration file. It allows the application to display the paywall without an error.
Adapty automatically generates fallback configuration files for you to download and use. Each file contains platform-specific configurations for *all* your placements.
## Get started
1. [Download the fallback configuration file](/local-fallback-paywalls) from Adapty.
2. Use the Adapty SDK to configure your fallback paywalls:
* [iOS](ios-use-fallback-paywalls)
* [Android](android-use-fallback-paywalls)
* [React Native](react-native-use-fallback-paywalls)
* [Flutter](flutter-use-fallback-paywalls)
* [Unity](unity-use-fallback-paywalls)
* [Kotlin Multiplatform](kmp-use-fallback-paywalls)
* [Capacitor](capacitor-use-fallback-paywalls)
## Limitations
Fallback paywalls are hard-coded and locally stored, so they lack the dynamic capabilities of regular Adapty paywalls.
* Fallback paywalls don't support [internationalization](paywall-localization). When Adapty generates the configuration file, it uses the default `en` locale.
* Each placement can only have one fallback paywall. If your setup inlcudes different paywall configurations for different [audiences](audience), Adapty uses the configuration intended for "All users".
* Fallback paywalls don't support [A/B testing](ab-tests). If a paywall participates in an A/B test, its fallback configuration file will include the variation with the highest weight.
* Fallback paywalls cannot be [managed remotely](customize-paywall-with-remote-config). If you want to update the configuration file, you need to release a new version of the app on App Store / Google Play.
---
# File: local-fallback-paywalls
---
---
title: "Descargar paywalls de respaldo"
description: "Usa paywalls de respaldo locales en Adapty para garantizar flujos de suscripción sin interrupciones."
---
Adapty genera automáticamente archivos de configuración JSON para tus [paywalls de respaldo](/fallback-paywalls), uno por plataforma. Estos archivos también contienen los datos de respaldo para tus [onboardings](local-fallback-onboarding).
Si un placement tiene más de un paywall u onboarding, la versión de respaldo incluirá la variación con el mayor peso o la audiencia más amplia. Adapty actualiza estos archivos cada vez que modificas tus paywalls u onboardings.
Sigue estos pasos para descargar tus configuraciones de respaldo:
1. Abre la página **[Placements](https://app.adapty.io/placements)**.
2. Haz clic en el botón **Fallbacks**.
3. Selecciona tu plataforma de destino (*iOS* o *Android*) en el menú desplegable.
4. Selecciona tu versión del SDK para iniciar la descarga.
## Tras la descarga \{#after-the-download\}
Sigue la guía de configuración para tu plataforma:
* [iOS](ios-use-fallback-paywalls)
* [Android](android-use-fallback-paywalls)
* [React Native](react-native-use-fallback-paywalls)
* [Flutter](flutter-use-fallback-paywalls)
* [Unity](unity-use-fallback-paywalls)
* [Kotlin Multiplatform](kmp-use-fallback-paywalls)
* [Capacitor](capacitor-use-fallback-paywalls)
---
# File: paywall-metrics
---
---
title: "Métricas de paywall"
description: "Rastrea y analiza las métricas de rendimiento de tu paywall para mejorar los ingresos por suscripción."
---
Adapty recopila una serie de métricas para ayudarte a medir mejor el rendimiento de tus paywalls. Todas las métricas se actualizan en tiempo real, excepto las vistas, que se actualizan cada varios minutos. Todas las métricas, excepto las vistas, se atribuyen al producto dentro del paywall. Este documento describe las métricas disponibles, sus definiciones y cómo se calculan.
Las métricas de paywall están disponibles en la lista de paywalls, lo que te ofrece una visión general del rendimiento de todos tus paywalls. Esta vista consolidada presenta métricas agregadas para cada paywall, lo que te permite evaluar su efectividad e identificar áreas de mejora.
Para un análisis más detallado de cada paywall, puedes navegar a las métricas de detalle del paywall. En esta sección encontrarás métricas completas específicas del paywall seleccionado, con información más profunda sobre su rendimiento.
### Controles de métricas \{#metrics-controls\}
El sistema muestra las métricas según el período de tiempo seleccionado y las organiza de acuerdo con el parámetro de la columna izquierda con tres niveles de sangría.
Para un paywall activo (Live), las métricas cubren el período desde la fecha de inicio del paywall hasta la fecha actual. Para los paywalls inactivos, las métricas abarcan todo el período desde la fecha de inicio hasta el final del período de tiempo seleccionado. Los paywalls en borrador y archivados se incluyen en la tabla de métricas, pero si no hay datos disponibles para esos paywalls, aparecerán listados sin ninguna métrica.
#### Opciones de vista para los datos de métricas \{#view-options-for-metrics-data\}
La página de paywall ofrece dos opciones de vista para los datos de métricas: basada en placement y basada en audiencia.
En la vista basada en placement, las métricas se agrupan por los placements asociados al paywall. Esto permite analizar las métricas según los distintos placements.
En la vista basada en audiencia, las métricas se agrupan por la audiencia objetivo del paywall. Puedes evaluar las métricas específicas de los distintos segmentos de audiencia. Puedes seleccionar la vista preferida mediante el menú desplegable en la parte superior de la página de detalle del paywall.
#### Filtrado por fecha de instalación del perfil \{#profile-install-date-filtration\}
La casilla **Filter metrics by install date** permite filtrar las métricas según la fecha de instalación del perfil, en lugar de los filtros predeterminados que usan la fecha de prueba/compra para las transacciones o la fecha de vista para las vistas de paywall. Al seleccionar esta casilla, puedes centrarte en medir el rendimiento de la adquisición de usuarios para un período específico alineando las métricas con la fecha de instalación del perfil. Esta opción es útil para personalizar el análisis de métricas según tus necesidades concretas.
#### Rangos de tiempo \{#time-ranges\}
Puedes elegir entre varios períodos de tiempo para analizar los datos de métricas, lo que te permite centrarte en duraciones específicas como días, semanas, meses o rangos de fechas personalizados.
#### Filtros y agrupación disponibles \{#available-filters-and-grouping\}
:::link
Artículo principal: [Controles de analytics](controls-filters-grouping-compare-proceeds)
:::
Adapty ofrece herramientas potentes para filtrar y personalizar el análisis de métricas según tus necesidades. En la página de métricas de Adapty tienes acceso a varios rangos de tiempo, opciones de agrupación y posibilidades de filtrado.
- Filtrar por: Audiencia, país, paywall, estado del paywall, grupo de paywall, placement, país, store, producto y store del producto.
- Agrupar por: Producto y store.
#### Gráfico de métrica individual \{#single-metrics-chart\}
Uno de los componentes principales de la página de métricas de paywall es la sección del gráfico, que representa visualmente las métricas seleccionadas y facilita el análisis.
La sección del gráfico en la página de métricas de paywall incluye un gráfico de barras horizontales que representa visualmente los valores de la métrica elegida. Cada barra del gráfico corresponde a un valor de métrica y es proporcional en tamaño, lo que facilita comprender los datos de un vistazo. La línea horizontal indica el período de tiempo analizado, y la columna vertical muestra los valores numéricos de las métricas. El valor total de todos los valores de métrica se muestra junto al gráfico.
Además, al hacer clic en el icono de flecha en la esquina superior derecha de la sección del gráfico, la vista se amplía y muestra las métricas seleccionadas en toda la línea del gráfico.
#### Resumen total de métricas \{#total-metrics-summary\}
Junto al gráfico de métrica individual se muestra la sección de resumen total de métricas, que presenta los valores acumulados para las métricas seleccionadas en un momento específico, con la posibilidad de cambiar la métrica mostrada mediante un menú desplegable.
### Definiciones de métricas \{#metrics-definitions\}
#### Revenue \{#revenue\}
Esta métrica representa el importe total de dinero generado en USD por compras y renovaciones. Ten en cuenta que el cálculo de los ingresos no incluye la comisión de App Store / Play Store y se calcula antes de deducir ninguna tarifa.
#### Proceeds \{#proceeds\}
Esta métrica representa el importe real de dinero recibido por el propietario de la app en USD por compras y renovaciones, después de deducir la comisión aplicable de App Store / Play Store.
:::important
Notifica a Adapty si tu app está inscrita en un programa de comisión reducida. Para garantizar cálculos correctos, especifica tu estado en el [programa Small Business](app-store-small-business-program) y el [programa de tarifa de servicio reducida](google-reduced-service-fee) en la [configuración de tu app](general).
:::
Refleja los ingresos netos que contribuyen directamente a las ganancias de la app. Para más información sobre cómo se calculan los proceeds, puedes consultar la [documentación](analytics-cohorts#revenue-vs-proceeds) de Adapty.
#### ARPPU \{#arppu\}
ARPPU es el ingreso promedio por usuario de pago. Se calcula dividiendo los ingresos totales entre el número de usuarios de pago únicos. $15.000 de ingresos / 1.000 usuarios de pago = $15 de ARPPU.
#### ARPAS \{#arpas\}
El ingreso promedio por suscriptor activo te permite medir los ingresos promedio generados por cada suscriptor activo. Se calcula dividiendo los ingresos totales entre el número de suscriptores que han activado una prueba o suscripción. Por ejemplo, si los ingresos totales son $5.000 y hay 1.000 suscriptores, el ARPAS sería $5. Esta métrica ayuda a evaluar el potencial de monetización promedio por suscriptor.
#### Tasa de conversión única (CR) a compras \{#unique-conversion-rate-cr-to-purchases\}
La tasa de conversión única a compras se calcula dividiendo el número de compras entre el número de vistas únicas. Por ejemplo, si hay 10 compras y 100 vistas únicas, la tasa de conversión única a compras sería del 10%. Esta métrica se centra en la proporción de compras respecto al número único de vistas, lo que aporta información sobre la efectividad de convertir visitantes únicos en clientes de pago.
#### CR a compras \{#cr-to-purchases\}
La tasa de conversión a compras se calcula dividiendo el número de compras entre el número total de vistas. Por ejemplo, si hay 10 compras y 100 vistas, la tasa de conversión a compras sería del 10%. Esta métrica indica el porcentaje de vistas que resultan en compras, lo que aporta información sobre la efectividad de tu paywall para convertir usuarios en clientes de pago.
#### CR única a pruebas \{#unique-cr-to-trials\}
La tasa de conversión única a pruebas se calcula dividiendo el número de pruebas iniciadas entre el número de vistas únicas. Por ejemplo, si hay 30 pruebas iniciadas y 100 vistas únicas, la tasa de conversión única a pruebas sería del 30%. Esta métrica mide el porcentaje de vistas únicas que resultan en activaciones de prueba, lo que aporta información sobre la efectividad de tu paywall para convertir visitantes únicos en usuarios de prueba.
#### Compras \{#purchases\}
Las compras representan el total acumulado de las distintas transacciones realizadas en el paywall. Las siguientes transacciones se incluyen en esta métrica (las renovaciones no se incluyen):
- Compras nuevas realizadas directamente en el paywall.
- Conversiones de pruebas que se activaron inicialmente en el paywall.
- Downgrades, upgrades y cross-grades de suscripciones realizados en el paywall.
- Restauraciones de suscripciones en el paywall, como cuando una suscripción se reactiva tras su vencimiento sin renovación automática.
Al considerar estos diferentes tipos de transacciones, la métrica de compras ofrece una visión completa de la actividad global de adquisición y monetización en tu paywall.
#### Pruebas \{#trials\}
La métrica de pruebas representa el número total de pruebas que se han activado. Refleja el número de usuarios que han iniciado períodos de prueba a través de tu paywall. Esta métrica ayuda a rastrear la efectividad de tu oferta de prueba y puede aportar información sobre el engagement de los usuarios y la conversión de pruebas a suscripciones de pago.
#### Pruebas canceladas \{#trials-canceled\}
La métrica de pruebas canceladas representa el número de pruebas en las que se ha desactivado la renovación automática. Esto ocurre cuando los usuarios se dan de baja manualmente de la prueba, lo que indica su decisión de no continuar con la suscripción tras el período de prueba. El seguimiento de las pruebas canceladas proporciona información valiosa sobre el comportamiento de los usuarios y permite entender la tasa a la que estos abandonan la prueba.
#### Reembolsos \{#refunds\}
La métrica de reembolsos representa el número de compras y suscripciones reembolsadas. Esto incluye transacciones que han sido revertidas o reembolsadas por diversas razones, como solicitudes del cliente, problemas de pago u otras políticas de reembolso aplicables.
#### Tasa de reembolso \{#refund-rate\}
La tasa de reembolso se calcula dividiendo el número de reembolsos entre el número de primeras compras (las renovaciones no se incluyen). Por ejemplo, si hay 5 reembolsos y 1.000 primeras compras, la tasa de reembolso sería del 0,5%.
#### Vistas \{#views\}
La métrica de vistas representa el número total de veces que los usuarios han visto el paywall. Cada vez que un usuario visita el paywall, se cuenta como una vista independiente. Por ejemplo, si un usuario visita el paywall dos veces, se registrarán dos vistas. El seguimiento de las vistas te ayuda a entender el nivel de engagement e interacción de los usuarios con tu paywall, lo que aporta información sobre el comportamiento de los usuarios y la efectividad de la ubicación y el diseño de tu paywall.
#### Vistas únicas \{#unique-views\}
La métrica de vistas únicas representa el número de instancias únicas en las que los usuarios han visto el paywall. A diferencia de las vistas totales, que cuentan cada visita como una vista independiente, las vistas únicas cuentan la visita de cada usuario al paywall una sola vez, independientemente de cuántas veces acceda a él. Por ejemplo, si un usuario visita el paywall dos veces, se registrará como una vista única. El seguimiento de las vistas únicas proporciona una medida más precisa del engagement de los usuarios y el alcance de tu paywall, ya que se centra en los usuarios individuales en lugar del número total de visitas.
:::warning
Asegúrate de enviar las vistas del paywall a Adapty mediante el método `.logShowPaywall()`. De lo contrario, las vistas del paywall no se contabilizarán en las métricas y las conversiones no serán relevantes.
:::
---
# File: migrate-paywalls
---
---
title: "Migrar paywalls entre apps"
description: "Aprende cómo migrar paywalls de otras apps en Adapty."
---
Con Adapty no necesitas crear un paywall desde cero para cada app. Si gestionas varias apps, puedes migrar la configuración del Paywall Builder de cualquier paywall creado con el builder de una app a otra.
La migración copia toda la configuración visual:
- Ajustes de diseño del paywall y de todos sus elementos
- Contenido multimedia
- Localización
La migración solo aplica a la configuración del builder y no copia los productos ni el Remote Config.
:::note
Si migras una configuración del Paywall Builder que usa fuentes personalizadas, pruébalas en un dispositivo, ya que pueden mostrarse incorrectamente.
:::
## Migrar un paywall \{#migrate-paywall\}
:::important
Solo puedes migrar paywalls creados en el **nuevo** Paywall Builder de Adapty. Para migrar paywalls del builder **legacy**, primero debes migrarlos al nuevo Paywall Builder.
:::
Para migrar una configuración del Paywall Builder:
1. **Para un paywall nuevo**: Comienza la [creación del paywall](create-paywall) y añade productos. Luego haz clic en **Build no-code paywall** para abrir la biblioteca de plantillas.
**Para un paywall existente**: Ve a la sección **Layout settings** de la pestaña **Builder & Generator** y haz clic en **Change template**.
2. Haz clic en **Choose paywall** dentro del recuadro **Copy a design from your apps** al editar la plantilla del paywall.
3. Selecciona la app y el paywall del que quieres copiar la configuración.
4. Haz clic en **Copy Selected Paywall**.
Tras la migración, puedes hacer los cambios que necesites sin que afecten al paywall original.
---
# File: duplicate-paywalls
---
---
title: "Duplicar paywall"
description: "Aprende a gestionar paywalls duplicados y optimizar el rendimiento de los paywalls en Adapty."
---
Si necesitas hacer pequeños cambios en un paywall existente de Adapty, especialmente cuando ya se está usando en tu app y no quieres estropear tus analíticas, puedes simplemente duplicarlo. Luego puedes usar esos duplicados para reemplazar los paywalls originales en algunos o todos los placements según necesites.
Esto crea una copia del paywall con todos sus detalles, como su nombre, productos y cualquier promoción. Al nombre del nuevo paywall se le añadirá "Copy" para que puedas distinguirlo fácilmente del original.
Para duplicar un paywall en el Adapty Dashboard:
1. Abre la sección [**Paywalls**](https://app.adapty.io/paywalls) en el menú principal de Adapty. La página de lista de paywalls del Adapty Dashboard ofrece una vista general de todos los paywalls presentes en tu cuenta.
2. Haz clic en el botón de **3 puntos** junto al paywall y selecciona la opción **Duplicate**.
3. Ajusta el nuevo paywall y haz clic en el botón **Save**.
4. Adapty te pedirá que reemplaces los paywalls originales por sus duplicados en los placements si el paywall original se está usando actualmente en algún placement. Si eliges **Create and replace original**, los nuevos paywalls pasarán a estar **Live** inmediatamente. También puedes crearlos como nuevos paywalls en estado **Draft** y añadirlos a los placements más adelante.
---
# File: archive-paywalls
---
---
title: "Archivar paywall"
description: "Aprende cómo archivar paywalls obsoletos en Adapty sin perder datos."
---
A medida que trabajas con Adapty y ajustas la configuración de tus paywalls, puede que acumules paywalls que ya no encajan con tu estrategia o campañas actuales. Estos paywalls sin uso, dejados como `Inactive`, pueden desordenar tu espacio de trabajo y dificultar encontrar los que realmente importan. Para resolver esto, Adapty ofrece la opción de archivar estos paywalls innecesarios.
Archivarlos garantiza que se guarden de forma segura sin eliminarlos permanentemente, listos para consultarse si es necesario en el futuro. Además, los paywalls archivados se pueden filtrar de la vista predeterminada, despejando tu espacio de trabajo y simplificando la interfaz. En esta guía, te explicamos cómo archivar paywalls en Adapty de forma eficiente para que tengas mayor control sobre la gestión de tus paywalls.
Un recordatorio importante: los paywalls activos que estén en uso en al menos un placement no se pueden archivar. Si quieres archivar uno de esos paywalls, primero elimínalo de todos los placements.
:::note
No puedes archivar un paywall si está siendo utilizado en una prueba A/B no archivada. De este modo, el usuario puede ver las métricas detalladas de una prueba A/B completada, y el paywall vinculado forma parte de esos datos.
:::
**Para archivar un paywall:**
1. Abre la sección [**Paywalls**](https://app.adapty.io/paywalls) en el menú principal de Adapty.
2. Haz clic en el botón **3-dot** junto al paywall y selecciona la opción **Archive**.
3. Cuando estés en la ventana **Archive paywall**, escribe el nombre del paywall que deseas archivar y haz clic en el botón **Archive**.
---
# File: restore-paywall
---
---
title: "Restaurar paywall desde el archivo"
description: "Restaura paywalls en Adapty para garantizar servicios de suscripción ininterrumpidos para los usuarios."
---
La posibilidad de archivar paywalls es una funcionalidad muy útil para simplificar la gestión de tus paywalls. Te permite ocultar los paywalls que ya no necesitas, reduciendo el desorden en tu espacio de trabajo. Además, la opción de restaurar paywalls archivados te da flexibilidad para reincorporarlos a tu estrategia si vuelven a ser útiles.
Los paywalls archivados pueden estar excluidos de la vista predeterminada. Para verlos, selecciona **Archived** en el filtro **State**.
**Para devolver un paywall desde el archivo**
1. Abre la sección [**Paywalls**](https://app.adapty.io/paywalls) en el menú principal de Adapty.
2. Asegúrate de que los paywalls archivados se muestran en la lista. Si no es así, actualiza el filtro de la derecha.
3. Haz clic en el botón de **3 puntos** junto al paywall archivado y selecciona **Back to active**.
---
# File: choose-meaningful-placements
---
---
title: "Elige placements con sentido"
description: "Optimiza los placements de paywalls con Adapty para aumentar la participación de los usuarios y los ingresos."
---
Al [crear placements](create-placement), es fundamental tener en cuenta el flujo lógico de tu app y la experiencia de usuario que quieres generar. La mayoría de las apps no deberían tener más de 5 [placements](placements) sin sacrificar la capacidad de ejecutar experimentos. Aquí tienes un ejemplo de cómo puedes estructurar tus placements:
1. **Flujo de onboarding:** Esta etapa representa la primera interacción de tus usuarios con la app. Es una oportunidad excelente para presentarles la propuesta de valor de tu app mediante placements tanto de onboarding como de paywall. Más del 80 % de las suscripciones se activan durante el flujo de onboarding, por lo que conviene enfocarse en vender las suscripciones más rentables en este punto. Con Adapty, puedes tener fácilmente diferentes [onboardings](onboardings) y [paywalls](paywalls) para distintas audiencias, y ejecutar pruebas A/B para encontrar la mejor opción para tu app. Por ejemplo, puedes ejecutar una prueba A/B para usuarios de EE. UU., mostrando suscripciones más caras el 50 % del tiempo.
2. **Ajustes de la app:** Si el usuario no se ha suscrito durante el flujo de onboarding, puedes crear un placement de paywall dentro de la app. Puede estar en los ajustes de la app o tras haber completado una acción objetivo específica. Como los usuarios dentro de la app tienden a reflexionar más antes de suscribirse, los productos de este paywall podrían ser algo menos costosos que los de la etapa de onboarding.
3. **Promo:** Si el usuario no se ha suscrito tras ver el paywall varias veces, puede ser señal de que los precios son demasiado altos para él o de que duda sobre las suscripciones. En ese caso, puedes mostrarle una oferta especial con la suscripción más asequible o incluso un producto de acceso de por vida. Esto puede ayudar a convencer a los usuarios sensibles al precio o escépticos ante las suscripciones para que realicen una compra.
La mayoría de las apps tendrán una lógica y unos placements similares, siguiendo el recorrido del usuario y los momentos clave donde se pueden mostrar paywalls, onboardings o pruebas A/B para impulsar las conversiones y los ingresos. Puedes configurarlos en cada placement para experimentar y optimizar tus estrategias de monetización.
---
# File: create-placement
---
---
title: "Crear un placement"
description: "Crea y gestiona placements en Adapty para mejorar el rendimiento de los paywalls."
---
Un [placement](placements) es una ubicación concreta dentro de tu app móvil donde puedes mostrar un paywall, un onboarding o una prueba A/B. Por ejemplo, la selección de suscripción puede aparecer en el flujo de inicio, mientras que un producto consumible (como monedas de oro) podría mostrarse cuando al usuario se le acaban las monedas en un juego.
Puedes mostrar los mismos o diferentes paywalls, onboardings o pruebas A/B en distintos placements o a diferentes segmentos de usuarios — denominados "audiencias" en Adapty.
Consulta la sección [Elige placements con sentido](choose-meaningful-placements) para obtener consejos sobre cómo elegir el placement adecuado.
:::tip
También puedes crear placements de forma programática usando el [Developer CLI](developer-cli-reference#adapty-placements-create).
:::
:::info
Aunque el proceso de creación de placements es similar para paywalls y onboardings, no puedes crear un mismo placement para ambos, ya que procesan métricas distintas.
:::
## Crear y configurar un placement \{#create-and-configure-a-placement\}
1. Ve a **[Placements](https://app.adapty.io/placements)** desde el menú principal de Adapty.
2. Haz clic en **Create placement**.
3. Introduce un **Placement name**. Es un identificador interno en el Adapty Dashboard. Puedes editarlo más adelante si lo necesitas.
4. Introduce un **Placement ID**. Usarás este ID en el SDK de Adapty para llamar a los [paywalls](paywalls), [onboardings](onboardings) y [pruebas A/B](ab-tests) del placement. No podrás editarlo después, ya que es único para cada placement.
A continuación, asigna un paywall, onboarding o prueba A/B al placement. Adapty es compatible con [audiencias](audience) — segmentos de usuarios basados en [segmentos](segments) — para que puedas mostrar contenido diferente a distintos grupos de usuarios. Si no necesitas segmentación, la audiencia predeterminada *All users* cubre a todos los usuarios.
:::note
Para continuar, asegúrate de haber creado el paywall, onboarding o prueba A/B que quieres lanzar, así como la audiencia que deseas especificar.
:::
1. En la ventana **Placements/ Your placement**, añade un paywall, onboarding o prueba A/B para mostrar a la audiencia predeterminada *All users*. Para ello, haz clic en el botón **Run paywall** o **Run A/B test** y selecciona el paywall, onboarding o prueba A/B deseado en la lista desplegable.
2. Si quieres usar más de una audiencia en el placement para crear paywalls personalizados adaptados a diferentes grupos de usuarios, haz clic en el botón **Add audience** y elige el segmento de usuarios que desees de la lista.
El archivo CSV exportado contiene la siguiente información sobre tus placements:
- ID del placement
- Nombre del placement
- Nombre de la audiencia
- Nombre del segmento
- Nombre de la prueba A/B entre placements
- Nombre de la prueba A/B
- Nombre del paywall
---
# File: delete-placement
---
---
title: "Eliminar placement"
description: "Descubre cómo eliminar un placement en Adapty sin afectar el rendimiento de tu paywall."
---
Un [placement](placements) designa una ubicación específica dentro de tu app móvil donde se puede mostrar un paywall, onboarding o una prueba A/B.
:::danger
Aunque tienes la opción de eliminar cualquier placement, es fundamental asegurarte de no eliminar un placement que esté en uso activo en tu app móvil. Eliminar un placement de paywall activo hará que se muestre de forma permanente el paywall de respaldo local si lo has [configurado](fallback-paywalls), y no podrás reemplazarlo nunca con un paywall dinámico en las versiones de la app ya publicadas.
:::
Para eliminar un placement existente:
1. Ve a **[Placements](https://app.adapty.io/placements)** desde el menú principal de Adapty. Si quieres eliminar un placement de onboarding, cambia a la pestaña **Onboardings**.
2. Haz clic en el botón de **3 puntos** junto al placement y selecciona la opción **Delete**.
3. En la ventana **Delete placement** que se abre, escribe el nombre del producto que vas a eliminar.
4. Haz clic en el botón **Delete forever** para confirmar la eliminación.
---
# File: add-audience-paywall-ab-test
---
---
title: "Añadir audiencia y paywall o prueba A/B a un placement"
description: "Ejecuta pruebas A/B en paywalls para distintos segmentos de audiencia en Adapty."
---
Las **audiencias** en Adapty son grupos de usuarios definidos por [segmentos](segments). Te permiten mostrar paywalls, onboardings y pruebas A/B a los usuarios que deben verlos. Construye segmentos con filtros para asegurarte de que cada grupo recibe el contenido adecuado.
Cuando añades una audiencia a un [placement](placements), diriges paywalls, onboardings o pruebas A/B a un grupo de usuarios específico. Vincular una audiencia a un placement garantiza que los usuarios correctos vean el contenido correcto en el momento adecuado de su recorrido por la app.
Abre el placement donde quieres añadir un paywall, un onboarding o una prueba A/B, o crea uno nuevo en el menú [Placements](https://app.adapty.io/placements).
:::note
Para continuar, asegúrate de haber creado el paywall, onboarding o prueba A/B que quieres lanzar, así como la audiencia que deseas especificar.
:::
1. En la ventana **Placements/ Your placement**, añade un paywall, onboarding o prueba A/B para mostrar a la audiencia predeterminada *All users*. Para ello, haz clic en el botón **Run paywall** o **Run A/B test** y selecciona el paywall, onboarding o prueba A/B deseado en la lista desplegable.
2. Si quieres usar más de una audiencia en el placement para crear paywalls personalizados adaptados a diferentes grupos de usuarios, haz clic en el botón **Add audience** y elige el segmento de usuarios que desees de la lista.
En este caso, nos basamos en la prioridad de audiencia. La prioridad de audiencia es un orden numérico donde el n.º 1 es la más alta. Determina la secuencia en la que se comprueban las audiencias. En términos más sencillos, la prioridad de audiencia ayuda a Adapty a decidir qué audiencia aplicar primero al seleccionar el paywall, onboarding o prueba A/B que se mostrará. Si la prioridad de una audiencia es baja, los usuarios que potencialmente encajan pueden quedar excluidos y ser derivados a otra audiencia con mayor prioridad.
Las audiencias multiplacement, es decir, las creadas para [pruebas A/B multiplacement](ab-tests#ab-test-types), siempre tienen prioridad sobre las audiencias normales.
La audiencia "Todos los usuarios" siempre tiene la prioridad más baja, ya que es un fallback e incluye a todos los que no coinciden con ninguna otra audiencia.
Para ajustar las prioridades de audiencia en un placement:
1. Al crear un nuevo placement o editar uno existente, haz clic en **Edit priority**. El botón solo es visible si se han añadido al menos tres audiencias al placement ("Todos los usuarios" y otras dos). Si hay menos, el orden es obvio: la audiencia "Todos los usuarios" va siempre al final.
2. En la ventana **Edit audience priorities** que se abre, arrastra y suelta las audiencias para reordenarlas correctamente.
3. Haz clic en el botón **Save**.
---
# File: placement-metrics
---
---
title: "Métricas de placement"
description: "Analiza las métricas de placement en Adapty para mejorar el rendimiento de tus paywalls."
---
Con Adapty tienes la flexibilidad de crear y gestionar múltiples placements en tu app, cada uno asociado a paywalls o pruebas A/B distintas. Esta versatilidad te permite dirigirte a segmentos de usuarios específicos, experimentar con distintas ofertas o modelos de precios, y optimizar la estrategia de monetización de tu app.
Para obtener información valiosa sobre el rendimiento de tus placements y la interacción de los usuarios con tus ofertas, Adapty registra diversas interacciones y transacciones relacionadas con los paywalls mostrados. El sólido sistema de analíticas captura métricas como vistas, vistas únicas, compras, trials, reembolsos, tasas de conversión e ingresos.
Las métricas recopiladas se actualizan continuamente en tiempo real y puedes consultarlas y analizarlas cómodamente desde el dashboard de Adapty. Tienes libertad para personalizar el rango de tiempo para el análisis, aplicar filtros según distintos parámetros y comparar métricas entre varios placements, segmentos de usuarios o productos.
Las métricas de placement están disponibles en la lista de placements, donde puedes obtener una visión general del rendimiento de todos tus placements. Esta vista de alto nivel muestra métricas agregadas para cada placement, lo que te permite comparar su rendimiento e identificar tendencias.
Para un análisis más detallado de cada placement, puedes navegar a las métricas de detalle del placement. En esta página encontrarás métricas exhaustivas específicas del placement seleccionado. Estas métricas ofrecen información más profunda sobre cómo está funcionando un placement concreto, lo que te permite evaluar su efectividad y tomar decisiones basadas en datos.
### Controles de métricas \{#metrics-controls\}
El sistema muestra las métricas según el período de tiempo seleccionado y las organiza de acuerdo con el parámetro de la columna izquierda con cuatro niveles de sangría.
#### Opciones de vista para los datos de métricas \{#view-options-for-metrics-data\}
La página de métricas de placement ofrece dos opciones de vista: basada en paywall y basada en audiencia.
En la vista basada en paywall, las métricas se agrupan por los placements asociados al paywall. Esto permite analizar las métricas según los distintos placements.
En la vista basada en audiencia, las métricas se agrupan por la audiencia objetivo del paywall. Los usuarios pueden evaluar métricas específicas de los distintos segmentos de audiencia.
#### Filtrado por fecha de instalación del perfil \{#profile-install-date-filtration\}
#### Rangos de tiempo \{#time-ranges\}
Puedes elegir entre varios períodos de tiempo para analizar los datos de métricas, lo que te permite centrarte en duraciones específicas como días, semanas, meses o rangos de fechas personalizados.
#### Filtros y agrupación disponibles \{#available-filters-and-grouping\}
:::link
Artículo principal: [Controles de analíticas](controls-filters-grouping-compare-proceeds)
:::
Adapty ofrece potentes herramientas para filtrar y personalizar el análisis de métricas según tus necesidades. Desde la página de métricas de Adapty tienes acceso a distintos rangos de tiempo, opciones de agrupación y posibilidades de filtrado.
- ✅ Filtrar por: Audiencia, paywall, grupo de paywall, placement, país, store.
- ✅ Agrupar por: Segmento, store y producto
#### Gráfico de métrica única \{#single-metrics-chart\}
Uno de los componentes clave de la página de métricas de placement es la sección de gráficos, que representa visualmente las métricas seleccionadas y facilita el análisis.
La sección de gráficos de la página de métricas de placements incluye un gráfico de barras horizontales que representa visualmente los valores de la métrica elegida. Cada barra del gráfico corresponde a un valor de métrica y es proporcional en tamaño, lo que facilita entender los datos de un vistazo. La línea horizontal indica el período analizado y la columna vertical muestra los valores numéricos de las métricas. El valor total de todos los valores de métricas se muestra junto al gráfico.
Además, al hacer clic en el icono de flecha en la esquina superior derecha de la sección del gráfico, la vista se amplía y muestra las métricas seleccionadas en toda la línea del gráfico.
#### Resumen total de métricas \{#total-metrics-summary\}
Junto al gráfico de métrica única se muestra la sección de resumen total de métricas, que presenta los valores acumulados para las métricas seleccionadas en un momento concreto, con la posibilidad de cambiar la métrica mostrada mediante un menú desplegable.
### Definiciones de métricas \{#metrics-definitions\}
Descubre el potencial de las métricas de placement con nuestras definiciones completas. Desde los ingresos hasta las tasas de conversión, obtén información valiosa que impulsará tus estrategias de monetización y el éxito de tu app.
#### Ingresos \{#revenue\}
Esta métrica representa el importe total en USD generado por compras y renovaciones dentro de placements específicos. Ten en cuenta que el cálculo de ingresos no incluye la comisión de Apple App Store ni de Google Play Store y se calcula antes de deducir cualquier tarifa.
#### Proceeds \{#proceeds\}
Esta métrica representa el importe real en USD recibido por el propietario de la app procedente de compras y renovaciones dentro de placements específicos, tras deducir la comisión aplicable de Apple App Store o Google Play Store. Refleja los ingresos netos que contribuyen directamente a las ganancias de la app. Para más información sobre cómo se calculan los proceeds, puedes consultar la [documentación](analytics-cohorts#revenue-vs-proceeds) de Adapty.
#### ARPPU \{#arppu\}
ARPPU son las siglas de Average Revenue Per Paying User (ingreso medio por usuario de pago) y mide el ingreso promedio generado por cada usuario de pago dentro de placements específicos. Se calcula dividiendo los ingresos totales entre el número de usuarios de pago únicos. Por ejemplo, si los ingresos totales son 15.000 $ y hay 1.000 usuarios de pago, el ARPPU sería de 15 $.
#### ARPAS \{#arpas\}
El ARPAS, o Average Revenue Per Active Subscriber (ingreso medio por suscriptor activo), permite medir el ingreso promedio generado por cada suscriptor activo dentro de placements específicos. Se calcula dividiendo los ingresos totales entre el número de suscriptores que han activado un trial o una suscripción. Por ejemplo, si los ingresos totales son 5.000 $ y hay 1.000 suscriptores, el ARPAS sería de 5 $. Esta métrica ayuda a evaluar el potencial de monetización promedio por suscriptor.
#### ARPU \{#arpu\}
Solo para placements de onboarding. El ARPU es el ingreso medio por usuario que visualizó el onboarding. Se calcula dividiendo los ingresos totales entre el número de espectadores únicos.
#### CR único a compras \{#unique-cr-to-purchases\}
La tasa de conversión única a compras se calcula dividiendo el número de compras dentro de placements específicos entre el número de vistas únicas. Se centra en la proporción de compras respecto al número único de vistas, ofreciendo información sobre la efectividad de convertir visitantes únicos dentro de placements específicos en clientes de pago.
#### CR a compras \{#cr-to-purchases\}
La tasa de conversión a compras se calcula dividiendo el número de compras dentro de placements específicos entre el número total de vistas de paywalls. Indica el porcentaje de vistas dentro de placements específicos que resultan en compras, ofreciendo información sobre la efectividad de tu paywall para convertir usuarios en clientes de pago.
#### CR único a trials \{#unique-cr-to-trials\}
La tasa de conversión única a trials se calcula dividiendo el número de trials iniciados dentro de placements específicos entre el número de vistas únicas. Mide el porcentaje de vistas únicas dentro de placements específicos que resultan en activaciones de trial, ofreciendo información sobre la efectividad de tu paywall para convertir visitantes únicos en usuarios de trial.
#### Compras \{#purchases\}
Las compras representan el total acumulado de diversas transacciones realizadas en el paywall dentro de placements específicos. Las siguientes transacciones están incluidas en esta métrica (las renovaciones no están incluidas):
- Nuevas compras realizadas directamente dentro de placements específicos.
- Conversiones de trials que se activaron inicialmente dentro de placements específicos.
- Rebajas, mejoras y cambios de tipo de suscripciones realizados dentro de placements específicos.
- Restauraciones de suscripciones dentro de placements específicos, como cuando una suscripción se reactiva tras su vencimiento sin renovación automática.
Al considerar estos diferentes tipos de transacciones, la métrica de compras ofrece una visión completa de la actividad de adquisición y monetización dentro de placements específicos.
#### Trials \{#trials\}
La métrica de trials representa el número total de trials que se han activado dentro de placements específicos. Refleja el número de usuarios que han iniciado períodos de trial a través de tu paywall dentro de esos placements. Esta métrica ayuda a hacer un seguimiento de la efectividad de tu oferta de trial y puede ofrecer información sobre la participación de los usuarios y la conversión de trials a suscripciones de pago.
#### Trials cancelados \{#trials-canceled\}
La métrica de trials cancelados representa el número de trials dentro de placements específicos en los que se ha desactivado la función de renovación automática. Esto ocurre cuando los usuarios cancelan manualmente el trial, lo que indica su decisión de no continuar con la suscripción una vez finalizado el período de trial. Hacer un seguimiento de los trials cancelados proporciona información valiosa sobre el comportamiento de los usuarios y te permite entender la tasa a la que los usuarios optan por abandonar el trial dentro de placements específicos.
#### Reembolsos \{#refunds\}
La métrica de reembolsos representa el número de compras y suscripciones reembolsadas dentro de placements específicos. Esto incluye transacciones que han sido revertidas o reembolsadas por diversos motivos, como solicitudes de clientes, problemas de pago u otras políticas de reembolso aplicables.
#### Tasa de reembolso \{#refund-rate\}
La tasa de reembolso se calcula dividiendo el número de reembolsos dentro de placements específicos entre el número de primeras compras (las renovaciones no están incluidas). Por ejemplo, si hay 5 reembolsos y 1.000 primeras compras, la tasa de reembolso sería del 0,5 %.
#### Vistas \{#views\}
La métrica de vistas representa el número total de veces que el paywall dentro de placements específicos ha sido visualizado por los usuarios. Cada vez que un usuario visita el paywall dentro de esos placements, se cuenta como una vista independiente. Hacer un seguimiento de las vistas te ayuda a entender el nivel de participación e interacción de los usuarios con tu paywall, ofreciendo información sobre el comportamiento de los usuarios y la efectividad de la ubicación y el diseño de tu paywall dentro de áreas específicas de tu app.
#### Vistas únicas \{#unique-views\}
La métrica de vistas únicas representa el número de instancias únicas en las que el paywall dentro de placements específicos ha sido visualizado por los usuarios. A diferencia de las vistas totales, que cuentan cada visita como una vista independiente, las vistas únicas cuentan la visita de cada usuario al paywall dentro de esos placements solo una vez, independientemente de cuántas veces acceda a él. Hacer un seguimiento de las vistas únicas proporciona una medida más precisa de la participación de los usuarios y el alcance de tu paywall dentro de placements específicos, ya que se centra en usuarios individuales en lugar del número total de visitas.
#### Completaciones y completaciones únicas \{#completions--unique-completions\}
Solo para placements de onboarding. Las completaciones cuentan el número de veces que los usuarios completan tu placement de onboarding, es decir, que recorren desde la primera hasta la última pantalla. Si alguien lo completa dos veces, eso son dos **completaciones** pero una **completación única**.
#### Tasa de completaciones únicas \{#unique-completions-rate\}
Solo para placements de onboarding. El número de completaciones únicas dividido entre el número de vistas únicas. Esta métrica te ayuda a entender cómo interactúan los usuarios con el placement de onboarding y a realizar cambios si observas que los usuarios lo ignoran.
---
# File: create-access-level
---
---
title: "Crear nivel de acceso"
description: "Crea y asigna niveles de acceso en Adapty para una mejor segmentación de usuarios."
---
Los niveles de acceso te permiten controlar lo que los usuarios de tu app pueden hacer sin necesidad de codificar IDs de productos específicos. Cada producto define cuánto tiempo obtiene el usuario un determinado nivel de acceso. Así, cuando un usuario realiza una compra, Adapty concede acceso a la app durante un período específico (para suscripciones) o de forma permanente (para compras de por vida).
Cuando creas una app en el Adapty Dashboard, el nivel de acceso `premium` se genera automáticamente. Este es el nivel de acceso predeterminado y no se puede eliminar.
:::tip
También puedes crear niveles de acceso de forma programática usando el [Developer CLI](developer-cli-reference#adapty-access-levels-create).
:::
Para crear un nuevo nivel de acceso:
1. Ve a **[Products](https://app.adapty.io/access-levels)** desde el menú principal de Adapty y selecciona la pestaña **Access levels**.
2. Haz clic en **Create access level**.
3. En la ventana **Create access level**, asígnale un ID. Este ID servirá como identificador dentro de tu app, permitiendo el acceso a funciones adicionales cuando el usuario realice una compra. Además, este identificador ayuda a distinguir un nivel de acceso de otros dentro de la app. Asegúrate de que sea claro y fácil de entender para tu comodidad.
4. Haz clic en **Create access level** para confirmar la creación del nivel de acceso.
---
# File: assigning-access-level-to-a-product
---
---
title: "Asignar nivel de acceso a un producto"
description: "Asigna niveles de acceso a los productos para optimizar la gestión de suscripciones."
---
Cada [producto](product) necesita un nivel de acceso asociado para garantizar que los usuarios reciban el contenido restringido correspondiente tras la compra. Adapty determina automáticamente la duración de la suscripción, que sirve como fecha de expiración del nivel de acceso. En el caso de un producto de acceso de por vida, si un usuario lo compra, el nivel de acceso permanece activo indefinidamente sin fecha de expiración.
Para vincular un nivel de acceso a un producto:
1. Al [configurar un producto](create-product), selecciona el nivel de acceso en la lista **Access Level ID**.
2. Haz clic en **Save**.
---
# File: give-access-level-to-specific-customer
---
---
title: "Asignar nivel de acceso a un cliente específico"
description: "Asigna niveles de acceso específicos a clientes usando las herramientas avanzadas de Adapty."
---
Puedes ajustar manualmente el nivel de acceso de un cliente concreto directamente desde el Adapty Dashboard. Esto resulta muy útil en escenarios de soporte. Por ejemplo, si quieres ampliar el uso premium de un usuario una semana extra como agradecimiento por haber dejado una reseña estupenda.
## Asignar nivel de acceso a un cliente específico en el Adapty Dashboard \{#give-access-level-to-a-specific-customer-in-the-adapty-dashboard\}
1. Ve a **[Profiles and Segments](https://app.adapty.io/placements)** desde el menú principal de Adapty.
2. Haz clic en el cliente al que quieres conceder acceso.
3. Haz clic en **Add access level**.
4. Selecciona el nivel de acceso que quieres conceder y cuándo debe expirar para ese cliente.
5. Haz clic en **Apply**.
## Asignar nivel de acceso a un cliente específico mediante la API \{#give-access-level-to-a-specific-customer-via-api\}
También puedes conceder un nivel de acceso a un cliente desde tu servidor usando la API de Adapty. Esto es muy útil si tienes bonificaciones por referidos u otros eventos relacionados con tus productos. Consulta más detalles en la página [Conceder nivel de acceso con la API del servidor](api-adapty/operations/grantAccessLevel).
---
# File: local-access-levels
---
---
title: "Niveles de acceso locales"
description: "Gestiona los niveles de acceso en caso de interrupciones temporales."
---
:::important
Ten en cuenta lo siguiente:
- Los niveles de acceso locales son compatibles con el SDK de Adapty a partir de la versión 3.12.
- Por defecto, los niveles de acceso locales están desactivados en Android por seguridad adicional. Si los necesitas, actívalos durante la inicialización del SDK: [Android](sdk-installation-android#enable-local-access-levels), [React Native](sdk-installation-reactnative), [Flutter](sdk-installation-flutter#enable-local-access-levels-android).
:::
Cada producto que configuras tiene un [**nivel de acceso**](access-level) asociado. Cuando tus usuarios realizan una compra, el SDK de Adapty asigna el nivel de acceso al [perfil](profiles-crm) del usuario, por lo que debes usar este nivel de acceso para determinar si los usuarios pueden acceder al contenido de pago en la app.
El SDK de Adapty es muy fiable y es muy raro que sus servidores no estén disponibles. Sin embargo, incluso en ese caso excepcional, tus usuarios no lo notarán.
Si un usuario realiza una compra pero Adapty no puede recibir respuesta, el SDK pasa a verificar las compras directamente en el store. Por tanto, el nivel de acceso se concede de forma local en la app y no se necesita ninguna configuración adicional para activarlo. El SDK lo gestiona automáticamente en segundo plano, y los usuarios accederán a lo que han pagado con total normalidad.
Ten en cuenta lo siguiente sobre cómo funcionan los niveles de acceso locales:
- Cuando los usuarios vuelven a estar en línea, la información de las transacciones se envía automáticamente a los servidores de Adapty, que aplican las transacciones al perfil del usuario y devuelven el perfil actualizado al SDK.
- Los datos actualizados no aparecerán en los análisis de Adapty hasta que se envíen los datos.
- Los niveles de acceso locales solo funcionan cuando los servidores de Adapty están caídos. En caso contrario, el SDK utilizará los datos en caché.
- Los niveles de acceso locales no funcionan con productos consumibles, excepto cuando un producto consumible tiene asignado un tipo de suscripción (mensual, anual, semanal, etc.) en el dashboard de Adapty.
---
# File: create-onboarding
---
---
title: "Crear onboarding"
---
Los [onboardings](onboardings) presentan a los nuevos usuarios el valor, las funciones y los consejos de uso de tu aplicación móvil.
## Paso 1. Crear un onboarding \{#step-1-create-an-onboarding\}
Para crear un nuevo onboarding en el Adapty Dashboard:
1. Ve a **Onboardings** desde el menú principal de Adapty. Esta página muestra un resumen de todos los onboardings que has configurado, junto con sus métricas. Haz clic en **Create onboarding**.
2. Escribe un nombre descriptivo para tu onboarding y haz clic en **Proceed to build onboarding**.
3. Se te redirigirá al constructor de onboardings.
Contiene una plantilla de demo por defecto que puedes explorar para entender cómo los onboardings recopilan datos y cómo puedes [personalizarlos mediante variables y cuestionarios](onboarding-user-engagement). Siéntete libre de eliminar las pantallas que no necesites y [diseñar tu propia experiencia de onboarding](design-onboarding) allí.
4. Cuando esté listo, haz clic en el botón **Preview** en la parte superior derecha. Completa el flujo de onboarding tú mismo para asegurarte de que todo funciona como se espera.
5. Si todo funciona correctamente, haz clic en **Publish** en la parte superior derecha. Espera a que se publique antes de volver a Adapty. De lo contrario, perderás tu progreso.
:::danger
Si no haces clic en **Publish**, el SDK no podrá obtener el onboarding que has creado.
:::
Una vez publicado tu onboarding, haz clic en **Back to Adapty**. Tu onboarding está creado y puedes añadirlo a un placement para empezar a usarlo.
## Paso 2. Crear un placement para tu onboarding \{#step-2-create-a-placement-for-your-onboarding\}
1. Ve a **Placements** desde el menú principal y cambia a la pestaña **Onboardings**. Haz clic en **Create placement**.
2. Introduce el nombre y el ID del placement. Luego, haz clic en **Run onboarding** y selecciona el onboarding que se mostrará a todos los usuarios.
3. Si tienes un onboarding diferente preparado para un grupo de usuarios específico, [añade más audiencias](audience) y selecciona un onboarding distinto para ellas.
## Paso 3. Integrar el onboarding en tu app \{#step-3-integrate-the-onboarding-into-your-app\}
:::important
Los onboardings están disponibles para apps que usen el SDK de Adapty v3.8.0+ (iOS, Android, React Native, Flutter), v3.14.0+ (Unity) o v3.15.0+ (Kotlin Multiplatform, Capacitor).
:::
Para empezar a mostrar onboardings en tu app, intégralos con el SDK de Adapty:
- [iOS](ios-onboardings)
- [Android](android-onboardings)
- [React Native](react-native-onboardings)
- [Flutter](flutter-onboardings)
- [Unity](unity-onboardings)
- [Kotlin Multiplatform](kmp-onboardings)
- [Capacitor](capacitor-onboardings)
Para entender qué onboarding funciona mejor, también puedes ejecutar [pruebas A/B](ab-tests).
---
# File: onboarding-layout
---
---
title: "Diseño de onboarding"
description: "Constructor de onboarding de Adapty: contenedores para el diseño, ajuste del espaciado y estilo de los elementos."
---
El constructor de onboarding sin código para aplicaciones móviles ofrece dos capas de diseño:
- Diseño de pantalla: padding global y cuadrícula mediante contenedores.
- Diseño de elementos: espaciado, posición, bordes y sombras por elemento.
:::tip
Para reordenar pantallas o elementos, simplemente arrástralos y suéltalos en el panel izquierdo.
:::
## Diseño de pantalla \{#screen-layout\}
Puedes ajustar una pantalla de dos formas:
- [Usando los ajustes de estilo de pantalla](#screen-style-settings)
- [Usando contenedores](#containers)
### Ajustes de estilo de pantalla \{#screen-style-settings\}
Para reducir o aumentar la distancia entre los elementos y el borde de la pantalla:
1. Selecciona la pantalla en el panel izquierdo.
2. Ve a la pestaña **Styles** en la parte derecha.
3. Establece el padding superior, inferior y horizontal en la sección **Padding**.
### Contenedores \{#containers\}
Es posible que quieras añadir texto e imágenes en paralelo, galerías deslizables o ventanas emergentes modales. Los contenedores lo facilitan, ya que te permiten crear columnas, filas, carruseles y superposiciones centradas.
Para añadir un contenedor:
1. Haz clic en **Add** en la parte superior izquierda.
2. Ve a **Containers** y elige uno:
- **Columns**: Divide la pantalla en secciones verticales para contenido en paralelo (p. ej., diseños de dos columnas con texto o imagen más texto).
- **Rows**: Alinea los elementos en una banda horizontal con espaciado uniforme.
- **Carousel**: Permite a los usuarios deslizarse por una serie de tarjetas.
- **Popup**: Muestra contenido en una superposición centrada sobre la página.
3. Crea los elementos que quieras añadir y arrástralos al contenedor desde el menú izquierdo.
## Diseño de elementos \{#element-layout\}
Para ajustar cada elemento de forma individual:
1. Selecciona el elemento en el panel izquierdo.
2. Ve a **Styles** en el menú derecho.
3. En la sección **Container**, establece:
- **Offset**: Desplaza el elemento horizontalmente o verticalmente.
- **Position**: Define el punto de anclaje del elemento:
- **In content**: Flujo normal del documento.
- **Attached**: Posición fija: permanece visible en el viewport (p. ej., botón fijo en la parte inferior).
- **Attached on scroll**: Se fija después de desplazarse hasta él (comportamiento sticky).
- **Padding**: Define el espacio interior entre el contenido del elemento y su borde.
- **Background**: Aplica un color sólido detrás del elemento. Asegúrate de que el fondo del elemento coincida con el [fondo de la pantalla](#screen-background-customization) (p. ej., usa gris o negro para onboardings con pantallas mayoritariamente oscuras).
- **Roundness**: Determina el radio de las esquinas del elemento.
- **Border**: Añade un contorno alrededor del elemento y especifica su grosor.
- **Border Color**: Especifica el color del borde del elemento.
- **Add shadows**: Añade una sombra con offset, desenfoque/expansión y color configurables.
:::note
Además de estos ajustes básicos de diseño de elementos, puedes personalizar aún más la apariencia de elementos específicos como [multimedia](onboarding-media#media-customization), [texto](onboarding-text#text--list-customization), [botones](onboarding-buttons#button-customization), [cuestionarios](onboarding-quizzes#quiz-customization) y otros usando la pestaña **Styles** del elemento.
:::
## Personalización del fondo de pantalla \{#screen-background-customization\}
El fondo no solo afecta al diseño de tu onboarding, sino también a la pantalla de carga hasta que el onboarding se cargue por completo.
Puedes rellenar el fondo de tu onboarding con un color o subir una imagen o vídeo:
1. Selecciona la pantalla en el panel izquierdo.
2. Ve a la pestaña **Styles** en la parte derecha.
3. En la sección **Background**, selecciona un color de fondo o haz clic en el área de carga para subir una imagen o vídeo.
Para los archivos multimedia, sigue los requisitos de [formatos y tamaño compatibles](onboarding-media#supported-formats-and-size).
:::tip
Para que las transiciones entre pantallas sean suaves, elige un color de fondo que coincida con el diseño general de tu onboarding (p. ej., usa gris o negro para onboardings con pantallas mayoritariamente oscuras) o personaliza la [pantalla de inicio](ios-present-onboardings#add-smooth-transitions-between-the-splash-screen-and-onboarding).
:::
---
# File: onboarding-media
---
---
title: "Contenido multimedia del onboarding"
description: "Crea onboardings atractivos en Adapty con imágenes, vídeos, gráficos animados y fondos personalizados."
---
Los elementos multimedia te ayudan a crear onboardings atractivos que demuestran el valor de tu app y guían a los usuarios hacia la conversión. Usa imágenes y vídeos para mostrar funciones, gráficos animados para visualizar beneficios y fondos estratégicos para reforzar tu marca.
## Imágenes y vídeos \{#images-and-videos\}
Las imágenes y los vídeos son perfectos para previsualizar funciones y hacer recorridos por la app. Mostrar a los usuarios lo que van a desbloquear es más efectivo que describirlo.
Para subir contenido multimedia:
1. Haz clic en **Add** arriba a la izquierda.
2. Ve a **Media & Display** y elige **Image/Video**.
3. Haz clic en el área de carga de la derecha y selecciona la imagen o el vídeo que quieras subir.
### Formatos y tamaño admitidos \{#supported-formats-and-size\}
| Especificación | Detalles |
|-----------------------|---------------------------------|
| Extensiones | PNG, JPG, JPEG, WEBP, MP4, WEBM |
| Tamaño máximo | 15 MB |
| Resolución máxima | 1920x1920 |
Si quieres añadir un elemento animado no compatible (como Lottie), puedes convertirlo a vídeo (por ejemplo, con [esta herramienta](https://www.lottielab.com/lottie/lottie-to-video)) e incrustarlo como vídeo.
## Gráficos animados \{#animated-charts\}
Los gráficos son animaciones que visualizan resultados y personalizan la experiencia del usuario en tus onboardings. Para añadir un gráfico:
1. Haz clic en **Add** arriba a la izquierda.
2. Ve a **Media & Display** y elige **Chart**.
3. Personaliza tu gráfico en la parte derecha:
- **Type**: Elige un tipo de curva. Ten en cuenta que el tipo de curva no está directamente relacionado con los valores.
- Insignias **Left** y **Right**: Nombra los puntos inicial y final del gráfico.
- **X Labels** y **Date Range**: Por defecto, el eje X muestra fechas. Puedes personalizar el rango de fechas o especificar valores personalizados.
- **Animation Duration**: Establece la duración de la animación para que se adapte a tu diseño.
:::tip
Usa [variables](onboarding-variables) para la visualización dinámica de datos en los gráficos.
:::
## Personalización de multimedia \{#media-customization\}
Además del [diseño de elementos](onboarding-layout#element-layout) básico, puedes personalizar aún más la apariencia de imágenes, vídeos y gráficos:
1. Selecciona el elemento en la parte izquierda.
2. Ve a **Styles** en el menú de la derecha.
3. Según el tipo de elemento, puedes ajustar las siguientes opciones:
- **Image/video**: Anchura, altura, redondez, opacidad, alineación.
- **Chart**: Color y grosor de línea, relleno de insignia, redondez, fuente y color, fuente y color del eje X.
## Eliminar multimedia \{#delete-media\}
Puedes eliminar todo el elemento multimedia o solo el archivo para subir uno nuevo:
- **Eliminar el elemento multimedia**: Haz clic derecho sobre el elemento multimedia en la parte izquierda y selecciona **Delete**.
- **Eliminar el archivo multimedia**: Haz clic en la vista previa del multimedia en la derecha. Aparecerá el área de carga para el nuevo archivo.
---
# File: onboarding-text
---
---
title: "Texto en onboarding"
description: "Añade y estiliza títulos, subtítulos, párrafos y listas en el constructor de onboarding de Adapty, y personaliza el texto para experiencias de usuario acordes a tu marca."
---
Los elementos de texto te ayudan a crear conversaciones claras y personalizadas con tus usuarios. Añade títulos, párrafos o listas con un solo clic, dales estilo para que se adapten a tu marca y usa [variables dinámicas](onboarding-variables) para personalizar el contenido para cada usuario.
## Añadir texto \{#add-text\}
Puedes añadir varios elementos de texto a las pantallas de tu onboarding. Para añadir elementos de texto:
1. Haz clic en **Add** en la parte superior izquierda.
2. Ve a **Typography** y elige uno:
- **Title**: titulares principales o títulos de pantalla que captan la atención al instante.
- **Subtitle**: una línea de apoyo breve que amplía el título.
- **Text**: texto de cuerpo para descripciones de funciones, avisos legales o frases inspiradoras.
- **Rich text**: formato mixto para preguntas frecuentes, términos de servicio o cualquier texto que necesite enlaces y énfasis.
3. Haz clic en el nuevo elemento para editar su contenido.
4. (Opcional) Selecciona cualquier parte del texto para abrir un tooltip de personalización rápida: negrita, cursiva, enlaces, color de texto o restablecer estilos.
Para editar un elemento de texto existente, simplemente haz clic en él y realiza los cambios en modo WYSIWYG.
:::tip
Si necesitas usar el mismo elemento de texto en varias pantallas, puedes copiarlo y pegarlo: selecciona el elemento y pulsa Ctrl+C (o ⌘+C en Mac), navega a otra pantalla, selecciona el elemento después del cual quieres pegar y pulsa Ctrl+V (o ⌘+V en Mac).
:::
## Añadir listas \{#add-lists\}
Puedes añadir listas numeradas y con viñetas:
1. Haz clic en **Add** en la parte superior izquierda.
2. Ve a **Typography** y elige uno:
- **Numbered list**: perfecta para guías paso a paso.
- **Bullet list**: destaca beneficios o características clave sin implicar un orden.
3. Ve a la pestaña **Element** de la derecha para editar los elementos de la lista o subir una imagen como marcador de elemento.
Para editar un elemento de lista existente, haz clic en él y realiza los cambios en la pestaña **Element**.
## Añadir enlaces externos \{#add-external-links\}
Para añadir un enlace externo:
1. Haz clic en **Add** en la parte superior izquierda.
2. En la sección **Typography**, selecciona **Title**, **Subtitle**, **Text** o **Rich text**.
3. Introduce tu texto.
4. Selecciona el texto que quieres convertir en enlace.
5. Haz clic en el icono **Link** en el menú de personalización rápida que aparece sobre el texto.
6. Pega la URL externa.
7. Haz clic en **✓** para aplicar el enlace.
:::info
En versiones del SDK de Adapty anteriores a la 3.15.1, los enlaces externos en los onboardings se abren en el navegador predeterminado del dispositivo.
A partir del SDK de Adapty v3.15.1, los enlaces externos se abren de forma predeterminada en un navegador dentro de la app, lo que permite a los usuarios permanecer en tu app sin cambiar a otra aplicación. Si lo necesitas, puedes [personalizar este comportamiento](ios-present-onboardings#customize-how-links-open-in-onboardings).
:::
## Personalización de texto y listas \{#text--list-customization\}
Además del [diseño de elemento](onboarding-layout#element-layout) básico, puedes personalizar la apariencia del texto y las listas:
1. Selecciona el elemento en la parte izquierda.
2. Ve a **Styles** en el menú de la derecha.
3. Según el tipo de elemento, puedes ajustar las siguientes opciones:
- **Text**: color del párrafo, fuente, alineación y altura de línea, color de los enlaces, fuente y decoración.
- **List**: color del texto y del marcador de texto, fuente, ancho, alto y redondez de la imagen del marcador.
:::tip
Para ir más rápido:
- Después de personalizar un elemento de texto, puedes hacer clic en **Apply styles to all paragraphs** para aplicar los mismos estilos en todas las pantallas del onboarding de una sola vez.
- Para cambiar la fuente de todos los elementos de texto de una pantalla concreta, selecciona la pantalla y ve a **Styles > Text** en el menú de la derecha.
:::
## Fuentes \{#fonts\}
En el constructor de onboarding puedes elegir entre una gran variedad de fuentes.
:::info
La carga de fuentes personalizadas aún no está disponible.
:::
Puedes configurar las fuentes de forma global para todo el onboarding o de forma individual para cada elemento:
- Para establecer la fuente principal que se usará en el onboarding:
1. Selecciona cualquier pantalla en la parte izquierda.
2. Cambia a la pestaña **Styles** y selecciona una **Font**.
3. Todos los elementos de todas las pantallas heredarán la fuente que hayas seleccionado.
- Para establecer una fuente para un único elemento:
1. Selecciona el elemento.
2. Cambia a la pestaña **Styles** y selecciona una **Font**.
3. La fuente seleccionada se usará para ese elemento aunque cambies la fuente principal.
:::note
No puedes usar SF Pro porque no es adecuada para aplicaciones multiplataforma, pero te recomendamos usar Inter en su lugar, ya que son bastante similares.
:::
---
# File: onboarding-buttons
---
---
title: "Botones de onboarding"
description: "Añade botones para navegar entre pantallas, cerrar el onboarding o ir al paywall."
---
Aprende a añadir y configurar botones estándar, animados, glossy y de cuenta atrás en el editor de onboarding sin código de Adapty. Guía a los usuarios, aumenta las conversiones y cierra tu flujo, todo sin escribir una sola línea de código.
## Añadir botones \{#add-buttons\}
Usa un Pulse Button para captar la atención y aumentar el porcentaje de clics. O añade un Countdown Button en las pantallas de expiración de prueba para generar urgencia e impulsar las actualizaciones.
Para añadir un botón:
1. Haz clic en **Add** en la parte superior izquierda.
2. Selecciona **Buttons** y elige uno:
- **Button**
- **Pulse Button**
- **Glossy Button**
- **Pulse Glossy Button**
- **Countdown Button**
3. Elige la [acción del botón](onboarding-actions) en el desplegable **On Press** de la derecha:
- **Navigate**: Lleva al usuario a una pantalla de onboarding concreta.
- **Show/Hide element**: Muestra u oculta un elemento de destino.
- **Open paywall**: Abre la pantalla del paywall para realizar compras. Aprende a gestionar la apertura del paywall en [iOS](ios-handling-onboarding-events#opening-a-paywall), [Android](android-handle-onboarding-events#opening-a-paywall), [React Native](react-native-handling-onboarding-events#opening-a-paywall) y [Flutter](flutter-handling-onboarding-events#opening-a-paywall).
- **Scroll to**: Desplaza la página hasta un elemento específico.
- **Custom**: Ejecuta la lógica de tu evento personalizado. Por ejemplo, puede usarse para abrir una ventana de inicio de sesión o solicitar permisos de la app. Aprende a gestionar acciones personalizadas en [iOS](ios-handling-onboarding-events#custom-actions), [Android](android-handle-onboarding-events#custom-actions), [React Native](react-native-handling-onboarding-events#handle-custom-actions) y [Flutter](flutter-handling-onboarding-events#handle-custom-actions).
- **Close onboarding**: Cierra el flujo de onboarding. Aprende a gestionar el cierre del onboarding en [iOS](ios-handling-onboarding-events#closing-onboarding), [Android](android-handle-onboarding-events#closing-onboarding), [React Native](react-native-handling-onboarding-events#closing-onboarding) y [Flutter](flutter-handling-onboarding-events#closing-onboarding).
Para editar el texto de un botón, haz clic en la vista previa del botón y realiza los cambios en modo WYSIWYG.
:::tip
[Anida un popup](onboarding-layout#containers) con un Pulse Glossy Button para hacer upsell de funciones premium a mitad del flujo.
:::
## Personalización de botones \{#button-customization\}
Además del [diseño de elementos](onboarding-layout#element-layout) básico, puedes personalizar el aspecto de los botones:
1. Selecciona el elemento de botón en la parte izquierda.
2. Ve a **Styles** en el menú de la derecha.
3. Según el tipo de botón, puedes ajustar estas opciones:
- **Todos los botones**: Anchura, relleno, fondo, redondez, borde, color de borde, sombras, flecha siguiente y tamaño de flecha, desplazamiento derecho, color del texto o de la cuenta atrás, fuente y altura de línea.
- **Pulse Button**: Duración de la animación y easing, color y tamaño de la sombra, crecimiento del botón.
- **Glossy Button**: Color, anchura, ángulo y duración de la animación de la línea glossy.
- **Pulse Glossy Button**: Duración de la animación y easing, color y tamaño de la sombra, crecimiento del botón, color, anchura, ángulo y duración de la animación de la línea glossy.
---
# File: onboarding-html
---
---
title: "HTML personalizado"
description: "Inserta fragmentos de HTML pequeños y ligeros en el editor de onboarding sin código de Adapty para crear widgets interactivos e integraciones de terceros."
---
El HTML personalizado te permite crear interacciones únicas, incrustar widgets de terceros o probar elementos experimentales rápidamente sin actualizar la app.
:::note
Los elementos de HTML personalizado no se precargan ni se almacenan en caché, por lo que recomendamos usar HTML sin procesar solo para elementos pequeños y ligeros.
:::
Para insertar código HTML personalizado:
1. Haz clic en **Add** en la parte superior izquierda.
2. Ve a **Media & Display** y elige **Raw HTML**.
3. Inserta o edita tu código HTML en el panel derecho.
---
# File: onboarding-navigation-branching
---
---
title: "Navegación en el onboarding"
description: "Configura la navegación estática y dinámica en el constructor de onboarding sin código de Adapty para guiar a los usuarios a través de los flujos."
---
La navegación y ramificación te permite guiar a los usuarios por cada paso del onboarding: usa rutas estáticas para llevar a todos a las pantallas principales, y navegación dinámica para adaptar el flujo según las elecciones de cada usuario. Todo sin escribir una sola línea de código.
## Configurar la navegación \{#set-up-navigation\}
Puedes configurar la navegación estática y dinámica, así como el cierre del onboarding, usando [botones](onboarding-buttons) y [cuestionarios](onboarding-quizzes).
:::info
En los cuestionarios, solo los de respuesta única son compatibles con la navegación. Los cuestionarios de respuesta múltiple pueden usarse para configurar la [visibilidad condicional de elementos](onboarding-element-visibility).
:::
### Navegación estática \{#static-navigation\}
La navegación estática dirige a todos los usuarios a la misma pantalla de destino. Para configurarla:
1. Añade un botón o un cuestionario de respuesta única.
2. Selecciona el botón o el cuestionario y ve a la pestaña **Element** de la derecha.
3. Configura la sección **On Press** del botón o el apartado **Behaviour** del cuestionario:
- **Action on** (solo para cuestionarios): Selecciona **Option** para desbloquear los ajustes de navegación del cuestionario.
- **Action**: Selecciona **Navigate**.
- **Data**: Selecciona **Static** para dirigir a todos los usuarios a la misma pantalla de destino.
- **Destination**: Elige la pantalla de destino.
:::note
Con la navegación estática, el cuestionario lleva a los usuarios a la misma pantalla independientemente de la respuesta que seleccionen.
:::
### Navegación dinámica \{#dynamic-navigation\}
La navegación dinámica dirige a los usuarios según sus respuestas en los cuestionarios:
- **Respuestas a cuestionarios en pantallas anteriores**: tanto los botones como los cuestionarios de respuesta única pueden activar la navegación.
- **Respuestas a cuestionarios en la pantalla actual**: solo los cuestionarios de respuesta única pueden activar la navegación.
Para configurarla:
1. Añade un botón o un cuestionario de respuesta única que navegará a los usuarios.
2. Selecciona el botón o el cuestionario y ve a la pestaña **Element** de la derecha.
3. Configura la sección **On Press** del botón o el apartado **Behaviour** del cuestionario:
- **Action on** (solo para cuestionarios): Selecciona **Option** para desbloquear los ajustes de navegación del cuestionario.
- **Action**: Selecciona **Navigate**.
- **Data**: Selecciona **Dynamic** para dirigir a los usuarios según sus respuestas anteriores en los cuestionarios.
- **State**: Elige el cuestionario cuyas respuestas determinan el destino del usuario.
4. Selecciona la pantalla de destino para cada opción del cuestionario.
El botón o cuestionario dirigirá dinámicamente a los usuarios a los destinos que hayas configurado.
### Cierre del onboarding \{#onboarding-closure\}
Si el recorrido del usuario requiere cerrar el flujo de onboarding, puedes configurarlo con botones o cuestionarios de respuesta única:
1. Añade un botón o un cuestionario de respuesta única.
2. Selecciona el botón o el cuestionario y ve a la pestaña **Element** de la derecha.
3. Configura la sección **On Press** del botón o el apartado **Behaviour** del cuestionario:
- **Action on** (solo para cuestionarios): Selecciona **Option** para desbloquear los ajustes de navegación del cuestionario.
- **Action**: Selecciona **Close onboarding**.
Aprende a gestionar el cierre del onboarding en [iOS](ios-handling-onboarding-events#closing-onboarding), [Android](android-handle-onboarding-events#closing-onboarding), [React Native](react-native-handling-onboarding-events#closing-onboarding) y [Flutter](flutter-handling-onboarding-events#closing-onboarding).
---
# File: onboarding-quizzes
---
---
title: "Cuestionarios de onboarding"
description: "Añade cuestionarios interactivos a tus onboardings de Adapty para recopilar preferencias de usuario y crear flujos personalizados, sin necesidad de código."
---
Convierte tu onboarding en una conversación bidireccional: añade cuestionarios en el editor sin código de Adapty para recopilar preferencias, segmentar usuarios y [ramificar flujos](onboarding-user-engagement#onboarding-flow-branching) según las respuestas en tiempo real. Empezarás a obtener información en minutos, sin escribir una sola línea de código.
## Añadir cuestionarios \{#add-quizzes\}
Puedes añadir distintos tipos de cuestionario —texto, emojis u opciones con imagen— para recopilar información del usuario:
1. Haz clic en **Add** en la parte superior izquierda.
2. Selecciona **Quiz** y elige uno:
- **Simple**: Lista de selección única con opciones de texto. Úsala para segmentar usuarios por un atributo principal (p. ej., "¿Cuál es tu rol?").
- **Multiple choice**: Permite seleccionar más de una opción de texto. Ideal para conocer todos los intereses del usuario (p. ej., funciones favoritas).
- **Emoji**: Opciones representadas con emojis para respuestas rápidas. Perfecto para verificaciones de opinión rápidas (p. ej., "¿Cuánto te entusiasma esto?").
- **Media picker**: Sube imágenes o vídeos como opciones seleccionables. Ideal para elecciones que dependen de lo visual (p. ej., elige tu tema favorito).
- **Rating**: Los usuarios valoran en una escala numérica o de estrellas. Úsalo para medir satisfacción o confianza (p. ej., valora esta función del 1 al 5).
- **Popup question**: Muestra una pregunta en forma de modal. Excelente para preguntas que requieren respuesta inmediata.
3. Configura el cuestionario en el panel derecho:
- **Required**: Hace que responder sea obligatorio antes de continuar.
- **Layout**: Elige entre lista o cuadrícula de imágenes.
- **Multiple answers**: Permite selección múltiple (desactiva las opciones de navegación del cuestionario).
- **Show checkboxes**: Muestra casillas de verificación cuando la selección múltiple está activada.
4. Configura las opciones del cuestionario en el panel derecho:
- **Label**: Texto que se muestra para cada opción.
- **Value**: El valor que se envía a los análisis y a los payloads de webhooks.
- **Image type**: Sube contenido multimedia o usa emojis.
5. Configura las [acciones](onboarding-actions) que se dispararán cuando el usuario seleccione una opción.
Consulta más información en la [guía para diseñar cuestionarios](#how-to-design-quizzes) a continuación.
### Cómo diseñar cuestionarios \{#how-to-design-quizzes\}
A continuación se muestra un ejemplo sencillo de configuración de un cuestionario.
Supongamos que tienes una app de recetas y quieres saber si tus usuarios son veganos o vegetarianos, y luego conocer más sobre sus preferencias según su respuesta.
#### Paso 1. Añadir pantallas \{#step-1-add-screens\}
1. Añade una nueva pantalla e inserta un elemento **Quiz** en ella.
2. Añade pantallas para los distintos grupos de usuarios. En nuestro ejemplo, estas pantallas recopilarán información adicional, por lo que también contendrán cuestionarios.
3. Añade una pantalla final para indicar que el onboarding ha terminado y que los usuarios pueden ir directamente a la app.
#### Paso 2. Configurar la navegación \{#step-2-configure-navigation\}
1. Para configurar la navegación dinámica, selecciona el elemento **Options** en la primera pantalla del cuestionario. En la sección **Behavior**, añade **Action on Option**.
Como queremos redirigir a los usuarios a distintas pantallas según sus respuestas, selecciona **Navigate** como acción, elige **Dynamic** en **Data** y selecciona tu elemento **Options** en **State**. Luego asocia cada opción con una pantalla.
2. En ambas pantallas condicionales, configura el botón de navegación. Como necesitamos omitir la segunda pantalla condicional, apunta el botón de navegación directamente a la pantalla que quieres mostrar a continuación.
:::tip
Si quieres personalizar el propio onboarding según las respuestas del cuestionario, consulta la guía de [navegación](onboarding-navigation-branching#dynamic-navigation) o la de [uso de variables](onboarding-variables).
:::
## Personalización del cuestionario \{#quiz-customization\}
Más allá del [diseño básico de elementos](onboarding-layout#element-layout), puedes personalizar la apariencia del cuestionario:
1. Selecciona el elemento del cuestionario en el panel izquierdo.
2. Ve a **Styles** en el menú derecho.
3. Ajusta estos parámetros:
- **Options**: Altura, relleno, fondo, redondez, borde y color del borde.
- **Text**: Color, fuente y alineación.
- **Pressed State**: Fondo, color del texto y color del borde.
:::tip
Tras personalizar un elemento del cuestionario, puedes hacer clic en **Apply styles to all options** en la parte inferior para aplicar los mismos estilos en todas las pantallas del onboarding de una sola vez.
:::
## Guardar respuestas del cuestionario \{#save-quiz-answers\}
También puedes procesar las respuestas del cuestionario en el código de tu app para almacenarlas o utilizarlas en tu aplicación.
Para ello, debes gestionar el evento de respuesta del cuestionario en el código de la app. Consulta la guía de tu plataforma:
- [iOS](ios-handling-onboarding-events)
- [Android](android-handle-onboarding-events)
- [React Native](react-native-handling-onboarding-events)
- [Flutter](flutter-handling-onboarding-events)
---
# File: onboarding-actions
---
---
title: "Acciones de onboarding"
description: "Configura acciones—navegar, abrir paywalls, disparar eventos y cerrar flujos—en el editor de onboarding sin código de Adapty."
---
Las acciones son los comportamientos interactivos que asignas a los elementos del onboarding, permitiéndoles responder a la interacción del usuario o gestionar eventos. Al definir un disparador (como pulsar un botón o completar un loader) y seleccionar un tipo de acción, controlas cómo los usuarios se mueven e interactúan con tu flujo de onboarding.
:::tip
Aprende más sobre los flujos de onboarding con ramificaciones en el artículo detallado.
:::
## Añadir acciones \{#add-actions\}
El proceso de configuración depende del elemento al que adjuntes la acción. Puedes añadir acciones a los siguientes elementos:
- **Botones**: Configura las acciones en el [desplegable **On Press** de la pestaña **Element**](onboarding-buttons#add-buttons).
- **Quizzes**: Configura las acciones en la [sección **Behaviour** de la pestaña **Element**](onboarding-quizzes#step-2-configure-navigation).
- **Loaders**: Configura las acciones en la sección **Complete action** de la pestaña **Element**.
Por ejemplo, aquí puedes ver dónde encontrarlo para los quizzes:
## Tipos de acción \{#action-types\}
Al configurar acciones, elige uno de los siguientes tipos:
#### Navegar \{#navigate\}
Lleva al usuario a otra pantalla del onboarding, permitiéndote controlar el flujo según las acciones o selecciones del usuario. Ideal para encadenar múltiples acciones con lógica de varios pasos usando quizzes.
#### Mostrar/Ocultar elemento \{#showhide-element\}
Activa o desactiva la visibilidad de un elemento determinado para mostrar contenido condicional dentro de una pantalla. Úsalo para mostrar contenido adicional solo cuando el usuario lo necesite.
#### Abrir paywall \{#open-paywall\}
Lanza el paywall de tu app para mostrar compras o suscripciones. Aprende cómo gestionar la apertura del paywall en [iOS](ios-handling-onboarding-events#opening-a-paywall), [Android](android-handle-onboarding-events#opening-a-paywall), [React Native](react-native-handling-onboarding-events#opening-a-paywall) y [Flutter](flutter-handling-onboarding-events#opening-a-paywall).
#### Desplazar a \{#scroll-to\}
Desplaza la vista de forma programática hasta un elemento destino en la pantalla actual. Útil en pantallas largas cuando se pulsa un botón "Ver detalles".
#### Personalizada \{#custom\}
Te permite definir y ejecutar tu propia lógica basada en el [ID de acción](#action-id). Usa esta acción para disparar comportamientos que no estén cubiertos por los tipos de acción estándar.
Aprende cómo gestionar acciones personalizadas en [iOS](ios-handling-onboarding-events#custom-actions), [Android](android-handle-onboarding-events#custom-actions), [React Native](react-native-handling-onboarding-events#handle-custom-actions) y [Flutter](flutter-handling-onboarding-events#handle-custom-actions).
#### Cerrar onboarding \{#close-onboarding\}
Finaliza el flujo de onboarding y cierra la interfaz. Úsalo cuando los usuarios terminen la configuración para volver directamente a la app principal.
Aprende cómo gestionar el cierre del onboarding en [iOS](ios-handling-onboarding-events#closing-onboarding), [Android](android-handle-onboarding-events#closing-onboarding), [React Native](react-native-handling-onboarding-events#closing-onboarding) y [Flutter](flutter-handling-onboarding-events#closing-onboarding).
## Disparadores de acción \{#action-triggers\}
Las acciones se ejecutan según el elemento al que están asociadas:
- **Botón**: Se ejecuta cuando el usuario pulsa un botón o cuando un temporizador finaliza.
- **Quiz**: Se ejecuta cuando se selecciona una opción.
- **Loader**: Se activa cuando un Loader o un Processing termina.
## ID de acción \{#action-id\}
:::important
El ID de acción no es lo mismo que el [ID de elemento](onboarding-variables) usado para insertar datos dinámicos con variables. Asegúrate de no confundirlos.
:::
Al configurar acciones personalizadas para botones, puede que quieras gestionar distintos botones de la misma manera usando IDs de acción:
1. Al [añadir un botón](onboarding-buttons#add-buttons), asígnale un ID en la sección **On Press** de la pestaña **Element**.
2. [Usa el ID de acción asignado en tu código fuente](ios-handling-onboarding-events#custom-actions).
::::note
En dispositivos iOS, los onboardings solo admiten acciones en la sección **On Press**. La sección **On Press Extra** no funcionará porque solo se puede mostrar una vista a la vez: si una acción abre una vista (como un paywall), la otra acción no puede ejecutarse simultáneamente.
:::
---
# File: onboarding-variables
---
---
title: "Variables de onboarding"
description: "Usa variables dinámicas en el editor de onboarding sin código de Adapty para personalizar contenido, capturar datos de usuario y crear flujos adaptados."
---
Las variables son valores que se establecen a partir de la entrada del usuario o datos del entorno. Son esenciales para crear experiencias de onboarding personalizadas y atractivas.
## Para qué sirven las variables \{#what-variables-are-for\}
Las variables te permiten insertar datos dinámicos —como respuestas de cuestionarios o texto introducido por el usuario— directamente en las pantallas de tu onboarding. Cada usuario ve contenido personalizado sin necesidad de programar. Por ejemplo, puedes saludar a los usuarios por su nombre usando campos de texto, o redirigir a quienes respondan un cuestionario a pantallas de seguimiento personalizadas.
Para usar variables, coloca el ID del elemento de la fuente de datos entre dobles llaves, así: `{{element_id}}`.
Como variables puedes utilizar los datos recopilados en pantallas anteriores:
- **Inputs**: La variable contiene los datos introducidos por el usuario.
- [**Quizzes**](onboarding-quizzes): La variable contiene el texto de las opciones seleccionadas. Si se permiten varias respuestas, la variable incluirá todas las opciones seleccionadas separadas por una coma y un espacio.
:::note
El ID del elemento no es lo mismo que el [ID de acción](onboarding-actions#action-id) usado para la lógica de acciones personalizadas. Asegúrate de no confundirlos.
:::
## Usar variables \{#use-variables\}
Así se usan las variables:
1. Crea un elemento Input o una opción de quiz y asígnale un ID.
2. Usa el ID del elemento en los textos del onboarding con el formato `{{element-id}}`. Por ejemplo, puedes personalizar el texto con el nombre del usuario.
3. Cuando los usuarios introduzcan sus datos durante el onboarding, aparecerán de forma dinámica en todos los lugares donde hayas colocado variables.
---
# File: onboarding-element-visibility
---
---
title: "Visibilidad de elementos del onboarding"
description: "Configura la navegación estática y dinámica en el editor de onboarding sin código de Adapty para guiar a los usuarios a través de los flujos."
---
También puedes añadir visibilidad condicional a elementos específicos. Los elementos condicionales solo son visibles para los usuarios que han dado respuestas concretas en el cuestionario.
Por ejemplo, los usuarios que respondieron "Principiante" a la pregunta "¿Cuál es tu nivel de experiencia?" verán información adicional en el siguiente paso.
Para hacer que un elemento sea condicional:
1. Ve a la pestaña **Element** en la parte derecha.
2. Selecciona **Conditional** en la sección **Visible**.
3. Configura la condición eligiendo:
- ID del cuestionario
- operador
- respuesta del cuestionario
4. (Opcional) Haz clic en **Advanced condition** para añadir varias condiciones.
Por ejemplo, si seleccionaste 'goal' como ID del cuestionario, 'Has' como operador y 'Education' como respuesta del cuestionario, el elemento solo será visible para los usuarios cuyas respuestas a ese cuestionario incluyan la opción 'Education'.
---
# File: onboarding-metrics
---
---
title: "Métricas de onboarding"
description: "Sigue y analiza las métricas de rendimiento del onboarding para mejorar los ingresos por suscripción."
---
Adapty recopila una serie de métricas para ayudarte a medir mejor el rendimiento de los onboardings. Todas las métricas se actualizan en tiempo real, excepto las vistas, que se actualizan cada varios minutos. Este documento describe las métricas disponibles, sus definiciones y cómo se calculan.
:::important
Los ingresos del onboarding se calculan a partir de todas las transacciones que ocurrieron después de que el onboarding fue mostrado.
:::
Las métricas de onboarding están disponibles en la lista de onboardings, ofreciéndote una visión general del rendimiento de todos tus onboardings. Esta vista consolidada presenta métricas agregadas para cada onboarding, lo que te permite evaluar su efectividad e identificar áreas de mejora.
Para un análisis más detallado de cada onboarding, puedes navegar a las métricas de detalle del onboarding. En esta sección encontrarás métricas exhaustivas específicas del onboarding seleccionado, con información más profunda sobre su rendimiento.
## Controles de métricas \{#metrics-controls\}
El sistema muestra las métricas según el período de tiempo seleccionado y las organiza conforme al parámetro de la columna izquierda con tres niveles de sangría.
Para los onboardings activos, las métricas cubren el período desde la fecha de inicio del onboarding hasta la fecha actual. Para los onboardings inactivos, las métricas abarcan todo el período desde la fecha de inicio hasta el final del período de tiempo seleccionado. Los onboardings en borrador y archivados se incluyen en la tabla de métricas, pero si no hay datos disponibles, se mostrarán sin métricas.
### Opciones de visualización para los datos de métricas \{#view-options-for-metrics-data\}
La página de onboarding ofrece dos opciones de visualización para los datos de métricas:
- Vista por placement: Las métricas se agrupan por los placements asociados al onboarding. Esto permite analizar las métricas según los distintos placements.
- Vista por audiencia: Las métricas se agrupan por la audiencia objetivo del onboarding. Puedes evaluar las métricas específicas de los distintos segmentos de audiencia.
El menú desplegable en la parte superior de la página de onboarding te permite seleccionar la vista preferida.
### Filtrar métricas por fecha de instalación \{#filter-metrics-by-install-date\}
La casilla **Filter metrics by install date** te permite analizar los datos según cuándo los usuarios instalaron tu app. Esto te ayuda a medir con qué eficacia estás captando nuevos usuarios durante períodos de tiempo concretos. Es una opción práctica cuando quieres personalizar tu análisis.
### Rangos de tiempo \{#time-ranges\}
Puedes analizar los datos de métricas usando un rango de tiempo, lo que te permite centrarte en duraciones específicas como días, semanas, meses o rangos de fechas personalizados.
### Filtros y grupos \{#filters-and-groups\}
Adapty ofrece herramientas potentes para filtrar y personalizar el análisis de métricas según tus necesidades. La página de métricas de Adapty te da acceso a distintos rangos de tiempo, opciones de agrupación y posibilidades de filtrado.
- Filtrar por: Attribution, Country, Onboarding audience, Onboarding A/B tests, Onboarding placement, Paywall, Store, State.
- Agrupar por: Product o Store.
### Gráfico de métrica individual \{#single-metric-chart\}
La sección del gráfico muestra tus datos en un sencillo gráfico de barras.
El gráfico te ayuda a ver rápidamente:
- Los valores exactos de cada métrica.
- Datos por período.
Aparece una suma total junto al gráfico, dándote el panorama completo de un vistazo.
Haz clic en el icono de flecha para expandir el gráfico.
### Resumen de métricas totales \{#total-metrics-summary\}
Junto al gráfico de métrica individual hay una sección de resumen de métricas totales. Esta sección muestra los valores acumulados de las métricas seleccionadas en un momento concreto. Puedes cambiar la métrica mostrada usando un menú desplegable.
## Definiciones de métricas \{#metrics-definitions\}
### Vistas y vistas únicas \{#views--unique-views\}
Las vistas cuentan el número de veces que los usuarios ven tu onboarding. Si alguien lo visita dos veces, eso son dos **vistas** pero una sola **vista única**. Esta métrica te ayuda a entender con qué frecuencia se ha mostrado tu onboarding.
### Completaciones y completaciones únicas \{#completions--unique-completions\}
Las completaciones cuentan el número de veces que los usuarios completan tu onboarding, es decir, que pasan de la primera a la última pantalla. Si alguien lo completa dos veces, eso son dos **completaciones** pero una sola **completación única**.
### Tasa de completaciones únicas \{#unique-completions-rate\}
El número de completaciones únicas dividido entre el número de vistas únicas. Esta métrica te ayuda a entender cómo interactúa la gente con el onboarding y a hacer cambios si notas que lo están ignorando.
### Ingresos \{#revenue\}
**Revenue** muestra tus ganancias totales en USD por compras y renovaciones. Es el importe antes de cualquier deducción.
### Ganancias netas de la tienda \{#proceeds\}
[**Proceeds**](analytics-cohorts#revenue-vs-proceeds) muestra lo que recibes después de que App Store/Play Store aplica su comisión, pero antes de impuestos.
:::important
Notifica a Adapty si tu app está inscrita en un programa de comisión reducida. Para garantizar cálculos correctos, especifica tu estado en el [Small Business Program](app-store-small-business-program) y el [Reduced Service Fee program](google-reduced-service-fee) en los [ajustes de tu app](general).
:::
### Ganancias netas finales \{#net-proceeds\}
Tus ganancias finales después de deducir tanto las comisiones de la tienda como los impuestos.
### ARPPU \{#arppu\}
El ARPPU es el ingreso medio por usuario de pago. Se calcula dividiendo los ingresos totales entre el número de usuarios de pago únicos. 15 000 $ de ingresos / 1000 usuarios de pago = 15 $ de ARPPU.
### ARPU \{#arpu\}
El ARPU es el ingreso medio por usuario que ha visto el onboarding. Se calcula dividiendo los ingresos totales entre el número de espectadores únicos.
### ARPAS \{#arpas\}
El ARPAS muestra cuánto genera de media cada suscriptor activo. Simplemente divide tus ingresos totales entre el número de suscriptores activos. Por ejemplo: 5000 $ de ingresos ÷ 1000 suscriptores = 5 $ de ARPAS.
### CR de compras y CR único de compras \{#cr-purchases--unique-cr-purchases\}
La **tasa de conversión a compras** muestra qué porcentaje de las vistas del onboarding llevan a una compra. Por ejemplo, 10 compras de 100 vistas es una tasa de conversión del 10%.
El **CR único de compras** mide qué porcentaje de usuarios únicos que ven tu onboarding acaban realizando una compra, contando a cada usuario solo una vez, independientemente de cuántas veces lo vean.
### CR de trials y CR único de trials \{#cr-trials--unique-cr-trials\}
La **tasa de conversión a trials** muestra qué porcentaje de las vistas del onboarding llevan a iniciar un trial. Por ejemplo, 10 trials de 100 vistas es una tasa de conversión del 10%.
El **CR único de trials** mide qué porcentaje de usuarios únicos que ven tu onboarding inician un trial, contando a cada usuario solo una vez, independientemente de cuántas veces lo vean.
### Compras \{#purchases\}
**Purchases** cuenta todas las transacciones de tu onboarding, excepto las renovaciones. Esto incluye:
- Compras directas nuevas
- Conversiones de trial
- Cambios de plan (actualizaciones, degradaciones, cambios de categoría)
- Restauraciones de suscripción
Esta métrica te da una imagen completa de la nueva actividad relacionada con transacciones de tu onboarding.
### Trials \{#trials\}
**Trials** cuenta el número de usuarios que iniciaron períodos de prueba gratuitos a través de tu onboarding. Esto te ayuda a seguir con qué eficacia tus ofertas de trial atraen a usuarios antes de que decidan pagar.
### Trials cancelados \{#trials-cancelled\}
**Trials cancelled** muestra cuántos usuarios desactivaron la renovación automática durante su período de trial. Esto te indica cuántas personas decidieron no continuar con una suscripción de pago después de probar tu servicio.
### Reembolsos \{#refunds\}
**Refunds** cuenta cuántas compras y suscripciones fueron devueltas para un reembolso, independientemente del motivo.
### Tasa de reembolso \{#refund-rate\}
La **tasa de reembolso** muestra el porcentaje de primeras compras reembolsadas. Ejemplo: 5 reembolsos de 1000 compras = 0,5 % de tasa de reembolso. Las renovaciones no se contabilizan en este cálculo.
---
# File: get-paid-in-onboardings
---
---
title: "Conectar paywalls con onboardings"
---
Puedes conectar un paywall a un onboarding para que los usuarios vean una oferta de suscripción durante el flujo de onboarding o justo al terminarlo.
Hay dos formas de hacerlo:
- **Mostrar un paywall después del onboarding**: El paywall se abre automáticamente cuando el usuario cierra el onboarding. Elige esta opción si quieres que todos los usuarios vean el paywall al final del flujo, sin que tengan que hacer nada.
- **Mostrar un paywall dentro del onboarding**: Un botón dentro del onboarding activa el paywall. Elige esta opción si quieres que los usuarios puedan suscribirse en un momento concreto del flujo — por ejemplo, después de ver la propuesta de valor en una pantalla específica.
Antes de empezar, crea un [paywall](paywalls) y un [onboarding](onboardings) y añádelos a placements.
:::important
Necesitas dos placements distintos: uno para el paywall y otro para el onboarding. Asegúrate de usar los IDs de placement correctos cuando obtengas el onboarding y el paywall en tu código.
:::
## Mostrar el paywall después del onboarding \{#show-paywall-after-onboarding\}
Para mostrar un paywall después del onboarding, solo tienes que gestionar el evento que se genera cada vez que los usuarios cierran el onboarding.
En cuanto los usuarios cierran el onboarding, se dispara el [evento](ios-handling-onboarding-events#closing-onboarding). Por tanto, si quieres mostrar un paywall inmediatamente después del onboarding, puedes implementar
3. Ahora, con este botón, cada vez que tus usuarios lo pulsen se generará una acción con el ID de acción correspondiente.
Para gestionar esta acción en el código de tu app, tendrás que [obtener el paywall](fetch-paywalls-and-products) y luego [mostrarlo](ios-quickstart-paywalls).
---
# File: target-onboardings-to-different-user-groups
---
---
title: "Segmentar onboardings a distintos grupos de usuarios"
description: "Muestra diferentes onboardings según la fuente de adquisición u otros atributos del usuario."
---
Puedes mostrar distintos flujos de onboarding según los atributos del usuario: fuente de adquisición, campaña, geografía, tipo de dispositivo, estado en el ciclo de vida o intención de uso. Adaptar el contenido del onboarding a grupos específicos de usuarios mejora las tasas de activación y el engagement inicial. La configuración requiere trabajo tanto del equipo de desarrollo como en el dashboard.
## Antes de empezar \{#before-you-start\}
- **Versión del SDK**: Tu app debe usar Adapty SDK v3.8.0+ (iOS, Android, React Native, Flutter), v3.14.0+ (Unity) o v3.15.0+ (Kotlin Multiplatform, Capacitor). Consulta [Onboardings](onboardings) para más detalles.
- **Onboardings**: Crea al menos dos onboardings en Adapty antes de empezar — uno por defecto y uno por segmento. Consulta [Crear onboarding](create-onboarding).
- **Herramientas de atribución**: Si tu app usa AppsFlyer, Adjust, Branch u otra [integración de atribución](attribution-integration), es posible que los datos de campaña y fuente ya estén disponibles como atributos de usuario en Adapty. Puedes usar estos datos directamente en los segmentos — salta al Paso 2.
## Paso 1. Asignar atributos personalizados a los usuarios *(Desarrollador)* \{#step-1-assign-custom-attributes-to-users-developer\}
Llama a `updateProfile` al inicio de la sesión del usuario, antes de que se muestre el onboarding. El atributo debe estar disponible cuando Adapty evalúe qué onboarding mostrar.
2. Elige el **Language**.
3. **Opcional**: Activa **Translate with AI** para traducir automáticamente todo el contenido del onboarding original al idioma seleccionado.
4. Haz clic en **Create**.
Ahora puedes traducir el contenido manualmente, usar IA o exportar el archivo de localización para traductores externos. Adapty creará una copia de tu onboarding donde podrás modificar tanto el contenido de texto como los elementos visuales para adaptarlos a tu audiencia objetivo.
:::tip
Puedes personalizar el diseño de cada idioma (imágenes, colores, diseños) para dirigirte mejor a distintas audiencias. Sin embargo, los cambios estructurales (añadir o eliminar pantallas y elementos) solo se pueden realizar en el idioma predeterminado.
:::
## Traducir onboardings con IA \{#translate-onboardings-using-ai\}
La traducción con IA ofrece una forma rápida y eficiente de localizar tu onboarding. La traducción suele tardar entre 1 y 2 minutos según el tamaño del onboarding.
Puedes usar la traducción con IA en dos momentos distintos:
- **Al añadir un nuevo idioma:** Marca **Translate with AI** durante la creación del idioma para obtener una versión pretraducida.
- **Después de crear un idioma:** Ve al icono de globo → **Manage locales** y haz clic en **Translate with AI** junto al idioma que desees.
:::important
Los cambios manuales que hayas hecho en la versión localizada se sobreescribirán. Además, los cambios realizados en el idioma predeterminado después de la traducción con IA no se reflejarán automáticamente en las versiones traducidas; tendrás que volver a ejecutar la traducción.
:::
## Exportar archivos de localización para traductores externos \{#export-localization-files-for-external-translation\}
Puedes exportar archivos de localización para compartirlos con tus traductores e importar después los resultados traducidos de vuelta en Adapty.
Al hacer clic en el botón **Export** se crea un único archivo `.tsv` con todos los idiomas.
## Importar archivos \{#import-files\}
Una vez recibido el archivo traducido, usa el botón **Import** para subirlo. Adapty validará automáticamente los archivos para asegurarse de que coinciden con el formato correcto y la estructura de configuración del paywall.
:::tip
Si envías este archivo a varios traductores al mismo tiempo, recuerda eliminar las columnas extra del archivo al importarlo. De lo contrario, algunas traducciones serán sobreescritas por columnas sin cambios.
:::
### Formato del archivo de importación \{#import-file-format\}
Para que la importación sea correcta, el archivo debe cumplir los siguientes requisitos:
- **Extensión del archivo:**
El archivo debe tener extensión `.tsv`.
- **Solo tabulaciones como separadores**:
Usa tabulaciones como separadores. Otros separadores causarán errores.
- **Línea de encabezado**:
El archivo debe incluir una línea de encabezado.
- **Nombres de columnas correctos:**
Los nombres de columnas deben ser **Key** y los nombres completos de las localizaciones.
- **Nombres de clave correctos**: Los valores de la columna **Key** deben permanecer sin cambios, ya que corresponden a identificadores de pantallas y elementos.
- **Sin entidades adicionales:**
Asegúrate de que el archivo no incluya entidades que no estén presentes en la configuración actual del onboarding. Las entidades extra causarán errores.
- **Importación parcial:**
El archivo puede incluir todas o solo algunas entidades de la configuración actual del paywall.
## Limitaciones existentes \{#existing-limitations\}
Una vez que un usuario abre un onboarding, el idioma mostrado queda bloqueado durante aproximadamente 24 horas. Si el usuario cambia el idioma del dispositivo o de la app durante ese tiempo, el onboarding seguirá mostrándose en el idioma original. Transcurridas las 24 horas, se aplicará el nuevo idioma.
Esto afecta a dos situaciones:
- El usuario abre el onboarding en el idioma A, cierra la app, cambia el idioma del dispositivo al idioma B y vuelve a abrir la app → el onboarding sigue mostrándose en el idioma A
- El usuario abre el onboarding en el idioma A, lo cierra, cambia el idioma de la app al idioma B y vuelve a abrir el onboarding → el onboarding sigue mostrándose en el idioma A
---
# File: onboarding-version-control
---
---
title: "Control de versiones de onboarding"
description: "Restaura versiones anteriores de tus onboardings."
---
Cada vez que haces **Save**, **Preview** o **Publish** en tu onboarding, Adapty añade la versión actual a tu **historial de versiones**. Puedes consultar el historial y cambiar a cualquiera de las versiones guardadas.
:::warning
Adapty no guarda automáticamente tus onboardings durante el [proceso de edición](design-onboarding). Haz **Publish** en tu onboarding si quieres añadirlo al historial de versiones.
:::
Abre el menú "versions" en la esquina superior derecha de la página para ver tu historial de versiones. Cada versión incluye una marca de tiempo para que sepas cuándo se guardó. Haz clic en el botón de flechas de una de las entradas para revertir a ese estado.
:::important
Recuerda hacer **Publish** con los cambios después de revertir a una versión anterior.
:::
---
# File: onboarding-offline
---
---
title: "Modo sin conexión"
description: "Gestiona la apertura de un onboarding sin conexión a internet."
---
Se necesita conexión a internet para obtener el flujo de onboarding desde el servidor. Esto es fundamental para recuperar los datos del onboarding y mostrar la secuencia de onboarding junto con el paywall con los productos que siguen. Tanto el contenido del onboarding como el del paywall se cargan dinámicamente desde el servidor, lo que garantiza que siempre estén actualizados.
## Modo sin conexión \{#offline-mode\}
Para optimizar la experiencia del usuario, la secuencia de onboarding se carga de la siguiente manera:
- **Carga de la primera pantalla**: Solo se requiere cargar la primera pantalla del flujo de onboarding al inicio. Esto permite minimizar los tiempos de carga, incluso en conexiones móviles lentas como 3G o 4G.
- **Precarga**: Una vez que la primera pantalla está cargada y visible, se comienza a precargar en segundo plano las pantallas siguientes (incluidos fuentes, vídeos e imágenes).
Si un usuario pierde la conexión a internet durante el proceso de onboarding, verá una pantalla de error con dos opciones:
- **Intentar de nuevo**: Al pulsar **Try again**, el sistema intentará cargar de nuevo el flujo de onboarding. Si la conexión se restablece y el contenido se carga correctamente, el onboarding se reanudará desde donde el usuario lo dejó, conservando todo el progreso.
- **Cerrar**: Si el usuario decide cerrar el onboarding, se activará el evento [close](ios-handling-onboarding-events#closing-onboarding) con `"action_id": "error"`.
---
# File: local-fallback-onboarding
---
---
title: "Descargar onboardings de respaldo"
description: "Usa onboardings de respaldo locales en Adapty para garantizar flujos de suscripción sin interrupciones."
---
Para cargar un [onboarding](onboardings), tu aplicación solicita los datos de configuración a Adapty. Las configuraciones de onboarding almacenan las URLs de tus flujos de onboarding. Si un problema de red interrumpe la conexión entre tu aplicación y los servidores de Adapty, no podrás configurar ni mostrar correctamente tus onboardings.
Para acceder a los datos de configuración de onboarding sin conexión, guarda un archivo de configuración de respaldo dentro del código de tu app. Puedes descargar archivos de respaldo ya preparados con los datos de configuración de tus onboardings y [paywalls](fallback-paywalls) directamente desde Adapty.
Sigue las instrucciones a continuación para descargar el archivo y añadirlo al código de tu aplicación.
:::important
Los onboardings de respaldo **requieren conexión a internet**, ya que el contenido del onboarding siempre se almacena en línea. El archivo de respaldo solo guarda la configuración de los onboardings.
Lee el artículo sobre el [modo sin conexión de onboarding](onboarding-offline) para entender qué ocurre cuando la aplicación no puede cargar el onboarding.
:::
2. Cambia a la pestaña **Remote config**.
El Remote Config tiene dos vistas:
- [Tabla](customize-paywall-with-remote-config#table-view-of-the-remote-config)
- [JSON](customize-paywall-with-remote-config#json-view-of-the-remote-config)
Tanto la vista **Table** como la vista **JSON** incluyen los mismos elementos de configuración. La única diferencia es una cuestión de preferencia: la vista de tabla ofrece un menú contextual que puede resultar útil para corregir errores de localización.
Puedes cambiar entre vistas haciendo clic en la pestaña **Table** o **JSON** cuando lo necesites.
Independientemente de la vista que hayas elegido para personalizar tu onboarding, podrás acceder a estos datos desde el SDK usando la propiedad `remoteConfig` de `AdaptyOnboarding` y hacer los ajustes necesarios en tu onboarding.
Puedes combinar distintas opciones y crear las tuyas propias.
## Vista JSON del Remote Config \{#json-view-of-the-remote-config\}
En la vista **JSON** del Remote Config puedes introducir cualquier dato con formato JSON:
## Vista de tabla del Remote Config \{#table-view-of-the-remote-config\}
Si no trabajas habitualmente con código y necesitas corregir algunos valores JSON, Adapty tiene la vista **Table** para ti.
Es una copia de tu JSON en formato de tabla, fácil de leer y entender. El código de colores ayuda a identificar los distintos tipos de datos.
Para añadir una clave, haz clic en **Add row**. Verificamos automáticamente la correspondencia entre valores y tipos, y mostramos una alerta si tus correcciones pueden generar un JSON no válido.
---
# File: profiles-crm
---
---
title: "Profiles/CRM"
description: "Manage user profiles and CRM data in Adapty to enhance audience segmentation."
---
Profiles is a CRM for your users. With Profiles, you can:
1. Find specific users by profile ID, customer user ID, email, or transaction ID.
2. View the user's event timeline, including billing issues, grace periods, and other [events](events).
3. Analyze user's properties such as subscription state, total revenue/proceeds, and more.
4. Grant the user a subscription.
:::link
To understand how Adapty creates and links user profiles, see [How profiles work](how-profiles-work).
:::
## Finding users
In the Profiles list, you can search for a specific user by:
- **Profile ID**: Adapty's internal identifier for the user (also called Adapty ID).
- **Customer user ID**: Your app's identifier for the user, if you've set one.
- **Email**: The user's email, if sent as a custom attribute.
- **Transaction ID**: The store transaction ID from a purchase.
Click any row to open the user's full profile.
## Subscription state
In the Profiles list, you can filter and sort users by subscription state. The state values are:
| **Estado** del usuario | Descripción |
| :--------------------- | :----------------------------------------------------------- |
| Subscribed | El usuario tiene una suscripción activa con la renovación automática habilitada. |
| Auto-renew off | El usuario desactivó la renovación automática, pero sigue teniendo acceso a las funciones premium hasta que finalice el período de suscripción. |
| Subscription cancelled | El usuario canceló su suscripción y esta ha finalizado por completo. |
| Billing issue | No se pudo cobrar al usuario debido a un problema de facturación, ya sea tras el vencimiento de su suscripción o del período de prueba. |
| Grace period | El usuario se encuentra actualmente en un período de gracia debido a un problema de facturación que ocurrió al intentar cobrarle tras el vencimiento de su suscripción o del período de prueba. |
| Active trial | El usuario tiene una suscripción activa que se encuentra actualmente en su período de prueba. |
| Trial cancelled | El usuario canceló el período de prueba y no tiene una suscripción activa. |
| Never subscribed | El usuario nunca se ha suscrito ni ha iniciado un período de prueba, y sigue siendo un usuario freemium. |
## User attributes
You can send additional user properties to Adapty using the SDK.
By default, Adapty sets:
| Property | Description |
| ---------------- | ------------------------------------------------------------ |
| Customer user ID | An identifier of your end user in your system. |
| Adapty ID | Internal Adapty identifier of your end user, called Profile ID. |
| IDFA | The Identifier for Advertisers, assigned by Apple to a user's device. Requires App Tracking Transparency (ATT) permission on iOS 14+. Not available on Android. |
| Country | Country of your end user. |
| OS | The operating system used by the end user. |
| Device | The end-user-visible device model name. |
| Install date | The date when the user was first recorded in Adapty:
## Granting a subscription
In a profile, you can extend an active subscription or grant a user lifetime access to an access level — without requiring them to make a purchase.
This is most useful for:
- Compensating a user after a billing or support issue.
- Running manual promotions or beta programs.
- Testing subscription flows without a real purchase.
To grant access, open the user's profile, go to the **Access levels** section, and click **Edit**. Set the expiration date and save. The expiration date must be in the future and cannot be decreased once set. Adjusting it for active subscriptions does not affect ongoing payments.
:::note
Granting access does not create App Store or Google Play purchase events. The user's event feed and analytics will differ from a real purchase flow.
:::
You can also grant access programmatically using the [Grant access level](api-adapty/operations/grantAccessLevel) API method.
## Sharing paid access between user accounts
:::link
Main article: [Sharing paid access between user accounts](sharing-paid-access-between-user-accounts)
:::
### Access sharing history
When access levels are shared or transferred, the user’s profile shows a link to the connected profile — the profile that shared access, or the profile that received it. To view the connected profile, in the user’s **Profile**, click the link next to the access level.
## Next steps
- To understand how Adapty creates and links profiles, see [How profiles work](how-profiles-work).
- To configure the access sharing policy, see [Sharing paid access between user accounts](sharing-paid-access-between-user-accounts).
- To grant access programmatically, see the [Grant access level](api-adapty/operations/grantAccessLevel) API method.
---
# File: how-profiles-work
---
---
title: "Cómo funcionan los perfiles"
description: "Entiende cómo Adapty crea, rastrea y vincula perfiles de usuario, incluyendo perfiles anónimos, usuarios identificados y relaciones padre/heredero."
---
Cada usuario de tu app tiene un perfil de Adapty que registra sus compras, eventos y estado de suscripción. Entender cómo se crean y vinculan los perfiles te ayuda a prevenir errores de integración, evitar la fragmentación de datos e interpretar correctamente la información en la sección [Perfiles](profiles-crm).
## Creación de perfil \{#profile-creation\}
Adapty crea automáticamente un perfil la primera vez que un usuario abre tu app.
**Sin un Customer User ID**, el perfil es anónimo. Se crea un nuevo perfil anónimo cada vez que:
- Un usuario reinstala la app
- Un usuario cierra sesión en tu app (cuando tu app llama a `Adapty.logout()`)
Las compras están vinculadas a la instalación de la app, no a una identidad de usuario persistente.
**Con un Customer User ID**, el perfil persiste entre reinstalaciones y dispositivos. Usar un Customer User ID te permite:
1. Rastrea a un usuario en reinstalaciones y múltiples dispositivos.
2. Busca usuarios por su customer user ID en la sección [**Profiles**](profiles-crm).
3. Usa el customer user ID en la [API server-side](getting-started-with-server-side-api).
4. Adapty envía el customer user ID a todas las integraciones.
El comportamiento del perfil con un customer user ID depende de cuándo lo configures:
- **Al activar el SDK**: Adapty usa el perfil existente con ese customer user ID (para usuarios que regresan) o crea un nuevo perfil (para usuarios nuevos).
- **Después de activar el SDK**: Adapty crea un perfil anónimo al activarse. Cuando identificas al usuario más adelante, Adapty vincula el customer user ID al perfil anónimo (para usuarios nuevos) o cambia al perfil existente con ese ID (para usuarios que regresan).
**Qué enfoque usar:**
- **ID de usuario disponible al iniciar la app** (por ejemplo, guardado de una sesión anterior): pásalo a `activate()` al inicializar el SDK.
- **Los usuarios inician sesión después de abrir la app**: llama a `identify()` tras la autenticación. Adapty vincula el ID al perfil actual (si el ID es nuevo) o cambia al perfil existente (si el ID ya existe).
- **Los usuarios pueden comprar antes de iniciar sesión**: llama a `identify()` después del login. Si el customer user ID ya existe en Adapty, recupera el perfil a continuación para sincronizar el nivel de acceso actual.
Para más detalles de implementación, consulta la guía del SDK sobre [identificación de usuarios](identifying-users).
:::note
Si un usuario que regresa usaba tu app anteriormente sin un customer user ID, esos perfiles anónimos no se fusionan automáticamente cuando empiezas a identificar en la activación del SDK. Para mantener el historial completo de esos usuarios, usa `identify()` después del inicio de sesión.
:::
## Perfiles padre e hijo \{#parent-and-inheritor-profiles\}
Cuando la misma suscripción de la store está asociada a más de un perfil de Adapty, Adapty trata esos perfiles como una cadena: un perfil **padre** y uno o más perfiles **herederos** que comparten el acceso de la misma compra.
Esto ocurre cuando:
- [El acceso de pago compartido entre cuentas de usuario](sharing-paid-access-between-user-accounts) está habilitado y un usuario inicia sesión en un dispositivo donde un perfil diferente realizó previamente la compra.
- Un usuario reinstala la app sin `customer_user_id`, y el nuevo perfil recoge la compra de la instalación anterior.
- Diferentes usuarios identificados restauran compras en el mismo dispositivo.
- Una app se transfiere entre Team IDs de Apple y la nueva app recoge las compras realizadas con el antiguo Team ID.
**Cómo se selecciona el perfil principal.**
El perfil padre es el **primer perfil en registrar la compra** — determinado por el orden de los recibos de compra en Adapty, no por el orden de creación del perfil. Por ejemplo: instalas la app y no realizas ninguna compra, luego la reinstales y compras una suscripción. El segundo perfil se convierte en el padre porque realizó la compra. El primer perfil se convierte en el heredero y obtiene acceso a través del uso compartido.
**Cómo se distribuyen los eventos:**
- **Eventos transaccionales** (compras, renovaciones, cancelaciones, problemas de facturación, períodos de gracia, reembolsos): Aparecen únicamente en el **perfil principal** que realizó la compra. Todas las renovaciones y actualizaciones de suscripción siguen apareciendo en ese perfil.
- **Eventos `access_level_updated`**: Aparecen en **el perfil principal y en los perfiles herederos** cada vez que cambia el estado del nivel de acceso. Esto mantiene todos los perfiles vinculados al día sobre su estado de acceso actual.
El perfil padre muestra el historial completo de transacciones. Los perfiles herederos solo muestran sus actualizaciones de nivel de acceso y un enlace al perfil padre en la sección **Access level**.
**Seguimiento de la misma suscripción en varios perfiles.**
Cada perfil heredero tiene su propio `profile_id`, por lo que este no es estable a lo largo de una cadena. Para identificar la misma suscripción en varios perfiles —por ejemplo, al reconciliar eventos de webhook o relacionar perfiles del dashboard con un mismo usuario subyacente— utiliza el identificador del lado del store.
| Campo | Usar para |
| --- | --- |
| `store_original_transaction_id` | Identificar una cadena de suscripciones entre perfiles. Único por suscripción de Apple. |
| `profiles_sharing_access_level` (campo de webhook) | Todos los perfiles con nivel de acceso activo gracias a la suscripción, cuando el uso compartido está habilitado. |
| `profile_id` | **No** es adecuado para el seguimiento entre perfiles: cada heredero tiene el suyo propio. |
## Compartir acceso de pago entre cuentas de usuario \{#sharing-paid-access-between-user-accounts\}
:::link
Artículo principal: [Compartir acceso de pago entre cuentas de usuario](sharing-paid-access-between-user-accounts)
:::
Para configurar tu política de compartición de nivel de acceso, en la página de configuración [**General**](general), selecciona una opción de sharing. Puedes establecer una política separada para el [entorno sandbox](test-purchases-in-sandbox).
---
no_index: true
---
**Habilitado (predeterminado)**
Los usuarios identificados (aquellos con un [Customer User ID](identifying-users#set-customer-user-id-on-configuration)) pueden compartir el mismo [nivel de acceso](access-level) proporcionado por Adapty si su dispositivo está vinculado al mismo Apple/Google ID. Esto es útil cuando un usuario reinstala la app e inicia sesión con un correo diferente: seguirá teniendo acceso a su compra anterior. Con esta opción, varios usuarios identificados pueden compartir el mismo nivel de acceso.
Aunque el nivel de acceso se comparte, todas las transacciones pasadas y futuras se registran como eventos en el Customer User ID original para mantener análisis coherentes y conservar un historial completo de transacciones, incluyendo períodos de prueba, compras de suscripción, renovaciones y más, vinculados al mismo perfil.
**Transferir acceso al nuevo usuario**
Los usuarios identificados pueden seguir accediendo al [nivel de acceso](access-level) proporcionado por Adapty, incluso si inician sesión con un [Customer User ID](identifying-users#set-customer-user-id-on-configuration) diferente o reinstalan la app, siempre que el dispositivo esté vinculado al mismo Apple/Google ID.
A diferencia de la opción anterior, Adapty transfiere la compra entre usuarios identificados. Esto garantiza que el contenido adquirido esté disponible, pero solo un usuario puede tener acceso a la vez. Por ejemplo, si UserA compra una suscripción y UserB inicia sesión en el mismo dispositivo y restaura las transacciones, UserB obtendrá acceso a la suscripción y se le revocará a UserA.
Si uno de los usuarios (ya sea el nuevo o el anterior) no está identificado, el nivel de acceso seguirá compartiéndose entre esos perfiles en Adapty.
Aunque el nivel de acceso se transfiere, todas las transacciones pasadas y futuras se registran como eventos en el Customer User ID original para mantener análisis coherentes y conservar un historial completo de transacciones, incluyendo períodos de prueba, compras de suscripción, renovaciones y más, vinculados al mismo perfil.
Después de cambiar a **Transferir acceso al nuevo usuario**, los niveles de acceso no se transferirán entre perfiles de inmediato. El proceso de transferencia para cada nivel de acceso específico se activa solo cuando Adapty recibe un evento del store, como la renovación de una suscripción, una restauración o al validar una transacción.
**Deshabilitado**
El primer perfil de usuario identificado que obtenga un nivel de acceso lo conservará para siempre. Esta es la mejor opción si la lógica de negocio de tu app requiere que las compras estén vinculadas a un único Customer User ID.
Ten en cuenta que los niveles de acceso siguen compartiéndose entre usuarios anónimos.
Puedes "desvincular" una compra [eliminando el perfil del usuario propietario](ss-delete-profile). Tras la eliminación, el nivel de acceso queda disponible para el primer perfil de usuario que lo reclame, ya sea anónimo o identificado.
Deshabilitar el uso compartido solo afecta a los nuevos usuarios. Las suscripciones que ya se comparten entre usuarios seguirán compartiéndose incluso después de deshabilitar esta opción.
:::warning
Apple y Google exigen que las compras in-app se compartan o transfieran entre usuarios porque se basan en el Apple/Google ID para asociar la compra. Sin el uso compartido, restaurar compras podría no funcionar tras reinstalaciones posteriores.
Deshabilitar el uso compartido puede impedir que los usuarios recuperen el acceso al iniciar sesión.
Recomendamos deshabilitar el uso compartido solo si tus usuarios **deben iniciar sesión** antes de realizar una compra. De lo contrario, un usuario identificado podría comprar una suscripción, iniciar sesión en otra cuenta y perder el acceso de forma permanente.
:::
### ¿Qué opción debo elegir? \{#which-setting-should-i-choose\}
| Mi app... | Opción a elegir |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| No tiene sistema de inicio de sesión y solo usa los IDs de perfil anónimos de Adapty. | Usa la opción predeterminada, ya que los niveles de acceso siempre se comparten entre IDs de perfil anónimos en las tres opciones. |
| Tiene un sistema de inicio de sesión opcional y permite a los clientes realizar compras antes de crear una cuenta. | Elige **Transferir acceso al nuevo usuario** para garantizar que los clientes que compren sin una cuenta puedan restaurar sus transacciones más adelante. |
| Requiere que los clientes creen una cuenta antes de comprar, pero permite que las compras estén vinculadas a varios Customer User IDs. | Elige **Transferir acceso al nuevo usuario** para garantizar que solo un Customer User ID tenga acceso a la vez, permitiendo a los usuarios iniciar sesión con un Customer User ID diferente sin perder su acceso de pago. |
| Requiere que los clientes creen una cuenta antes de comprar, con reglas estrictas que vinculan las compras a un único Customer User ID. | Elige **Deshabilitado** para garantizar que las transacciones nunca se transfieran entre cuentas. |
## Marcas de tiempo de eventos con fechas futuras (Apple/iOS) \{#event-timestamps-with-future-dates-appleios\}
Este comportamiento es exclusivo de la App Store de Apple. El sistema de notificaciones de Google Play no envía eventos con antelación.
Las marcas de tiempo de eventos en los perfiles e integraciones pueden mostrar fechas futuras porque Apple envía los eventos de renovación por adelantado.
- **Por qué ocurre**: Apple hace esto para garantizar que las suscripciones se renueven automáticamente antes de que expiren, evitando interrupciones en el servicio del usuario. Para más detalles, consulta el Apple Developer Forum: [Server Notifications for Subscriptions](https://developer.apple.com/forums/tags/app-store-server-notifications).
- **Tipos de eventos afectados**: Por lo general, esto aplica a las renovaciones de suscripción y las conversiones de prueba a pago. Estos eventos pueden tener marcas de tiempo futuras porque Apple notifica a los sistemas con antelación.
- **Otros tipos de eventos**: Las compras in-app adicionales y los cambios de plan de suscripción se registran con sus marcas de tiempo reales, ya que estos eventos no se pueden predecir con antelación.
- **Impacto en Analytics y el Event Feed**: Estos eventos solo aparecerán en **Analytics** y el **Event Feed** una vez que sus marcas de tiempo hayan pasado. Los eventos con marcas de tiempo futuras no se muestran en ninguna de las dos secciones.
- **Impacto en las integraciones**: Adapty envía los eventos a las integraciones en cuanto los recibe. Si un evento tiene una marca de tiempo futura, Adapty lo envía a tu integración con esa marca de tiempo futura sin modificar.
## Pasos siguientes \{#next-steps\}
- Para usar el dashboard de Profiles para encontrar y gestionar usuarios, consulta [Profiles](profiles-crm).
- Para configurar la identificación de usuarios en tu app, consulta la guía de SDK para [identificar usuarios](identifying-users).
- Para configurar la política de compartición de acceso, consulta [Compartir acceso de pago entre cuentas de usuario](sharing-paid-access-between-user-accounts).
---
# File: sharing-paid-access-between-user-accounts
---
---
title: "Compartir acceso de pago entre cuentas de usuario"
description: "Cómo compartir el acceso de pago entre diferentes cuentas de usuario para usuarios con varios dispositivos o múltiples perfiles en la app"
---
Cuando un usuario realiza una compra, Adapty asigna un nuevo [nivel de acceso](access-level) a su [perfil](identifying-users) activo. Este nivel de acceso autoriza al comprador a acceder al contenido de pago.
El perfil del comprador puede cambiar involuntariamente si reinstala la app o inicia sesión en una nueva cuenta dentro de la app. Para garantizar un acceso ininterrumpido, Adapty comparte automáticamente el nivel de acceso del usuario entre el perfil original y los que le siguen.
Este enfoque funciona bien para la mayoría de las aplicaciones. Sin embargo, si tu lógica de negocio lo requiere, puedes seleccionar una política de compartición de acceso de pago más restrictiva.
Abre la página de [General Settings](https://app.adapty.io/settings/general) para configurar una política de compartir niveles de acceso. Para facilitar las pruebas, puedes cambiar esta configuración solo para el [entorno sandbox](#sharing-paid-access-on-sandbox).
## Habilitado (por defecto) \{#enabled-default\}
Esta configuración funciona mejor para aplicaciones **sin autenticación integrada**. Tras la compra, todos los perfiles asociados a la misma cuenta del store heredan automáticamente el nivel de acceso.
* Si un usuario inicia sesión en tu app con un nuevo conjunto de credenciales, conserva el acceso al contenido de pago.
* Si un usuario reinstala tu aplicación tras un restablecimiento de fábrica, conserva el acceso al contenido de pago.
* Si un usuario instala la aplicación en otros dispositivos con la misma cuenta de la store, la compra estará disponible en todos los dispositivos, incluso si cada instancia de la aplicación tiene su propio perfil de cliente.
## Transferir el acceso a un nuevo usuario \{#transfer-access-to-new-user\}
Esta configuración es ideal para aplicaciones que permiten compras **con o sin autenticación**, o que quieren aplicar una política de **un dispositivo por usuario**.
Adapty limita el acceso a las compras a 1 customer ID a la vez. El propietario del dispositivo puede reinstalar la app, iniciar y cerrar sesión, pero no puede acceder al mismo producto desde más de un customer ID al mismo tiempo.
Con esta opción activada, los perfiles anónimos (por ejemplo, un perfil que se activa cuando el usuario cierra sesión) siempre heredan el nivel de acceso del último ID de cliente activo. Esto es necesario para evitar que se pierda el acceso más adelante.
:::warning
Cuando desactivas la configuración predeterminada y activas **Transfer access to new user**, Adapty no actualiza inmediatamente los niveles de acceso de los perfiles de cliente existentes.
El cambio se produce cuando el usuario genera un nuevo evento en el store: por ejemplo, renueva la suscripción o restaura sus compras.
:::
## Desactivar el acceso compartido de pago \{#disable-paid-access-sharing\}
Esta configuración **solo es adecuada** para aplicaciones con **autenticación obligatoria** o una implementación propia de gestión de accesos. En cualquier otro caso, los usuarios podrían no poder acceder a sus compras, y tu aplicación corre el riesgo de **no superar la revisión obligatoria del store**.
Si deshabilitas el acceso compartido de pago, Adapty vincula el producto al [ID de cliente](identifying-users#set-customer-user-id-on-configuration) activo en el momento de la compra y no comparte el nivel de acceso con ningún otro perfil. Esta política permite una distribución estricta de productos en proporción 1 a 1.
:::warning
Al deshabilitar el acceso compartido de pago, impides que los IDs de cliente hereden el acceso de pago. Si un ID de cliente ya heredó acceso de pago en el pasado, ese acceso no se puede revocar automáticamente.
:::
:::important
En situaciones de emergencia, puede que necesites [eliminar un perfil de usuario](api-adapty/operations/deleteProfile) para que el siguiente perfil disponible (ya sea identificado o anónimo) pueda reclamar su nivel de acceso.
:::
## Compartir acceso de pago en sandbox \{#sharing-paid-access-on-sandbox\}
Puedes establecer una política de compartición de acceso de pago específicamente para el entorno sandbox. Al probar compras en sandbox, ten en cuenta el siguiente comportamiento:
* Apple almacena información sobre tus compras anteriores en el historial de compras de la cuenta. El SDK de Adapty también puede acceder a él.
* Si reinstalaas la aplicación y Adapty detecta que el producto ya fue comprado, el perfil activo heredará el nivel de acceso.
* Si Apple detecta una compra existente para el producto, no permitirá realizar la misma compra dos veces, aunque el perfil activo no tenga el nivel de acceso necesario.
Este comportamiento se produce **independientemente de la configuración de acceso de pago compartido**. Si tu app no muestra el paywall, no puedes comprar el producto. La única solución es **borrar el historial de compras de tu cuenta**. Consulta la [guía de pruebas en sandbox](test-purchases-in-sandbox) para obtener instrucciones detalladas.
## Compartición de acceso de pago en los análisis \{#paid-access-sharing-in-analytics\}
* Adapty registra las transacciones a medida que se producen. Una misma transacción puede estar asociada a más de un perfil, pero no se contabiliza más de una vez.
* Si dos o más perfiles comparten el mismo nivel de acceso, la compra se atribuye al [perfil principal](how-profiles-work#parent-and-inheritor-profiles).
* La herencia del nivel de acceso no afecta a las estadísticas de instalación. Para saber cómo Adapty contabiliza las instalaciones, puedes seleccionar una de las dos [definiciones de instalación](installs#calculation) disponibles en la página de configuración.
---
# File: segments
---
---
title: "Segmentos"
description: "Crea y gestiona segmentos de usuarios para una mejor segmentación en Adapty."
---
Un **segmento** es un conjunto de filtros que agrupa usuarios con características comunes. Usa segmentos para dirigir paywalls y pruebas A/B de forma más precisa.
Una vez creado un segmento, puedes [usarlo como **audiencia** en Placements y pruebas A/B](audience) para controlar qué paywall ve cada usuario (uno o varios). Algunos ejemplos:
- Muestra un paywall estándar a los no suscriptores y ofrece un descuento a los usuarios que hayan cancelado previamente una suscripción o prueba.
- Muestra paywalls diferentes a usuarios de distintos países.
- Segmenta usuarios basándote en datos de atribución de Apple Search Ads.
- Asegúrate de que los usuarios en versiones antiguas de la app sigan viendo el paywall actual, mientras que las versiones más recientes reciban el actualizado.
- [En Analytics](controls-filters-grouping-compare-proceeds#filter-and-group-data), filtra por segmentos para ver el rendimiento de grupos de usuarios específicos. Agrupa por segmento para comparar el rendimiento o la contribución dentro de **All users**.
## Creación \{#creation\}
Para crear un segmento, introduce un nombre y selecciona los atributos que definen sus filtros. Si seleccionas varios atributos, los usuarios deben cumplir todas las condiciones. Adapty aplica lógica AND entre atributos.
## Atributos disponibles \{#available-attributes\}
:::note
Aunque muchos atributos de usuario se establecen automáticamente (como **Country** o **Calculated total revenue USD**), los atributos **Age**, **App user ID**, **Attribution**, **Gender** y **Custom attributes** no se definen automáticamente. Debes [establecer los atributos de usuario](setting-user-attributes) o [pasar los datos de atribución](attribution-integration) si quieres usarlos para segmentación.
:::
:::tip
Para los atributos basados en fechas, puedes filtrar usando:
- **Fecha fija**: Selecciona fechas concretas en un calendario (por ejemplo, mostrar una oferta especial a usuarios que instalaron la app entre el Black Friday y el Cyber Monday)
- **Rango relativo**: Define ventanas de tiempo dinámicas como "Últimos 7 días" o "Últimos 3 meses" (por ejemplo, volver a captar usuarios que no se han visto en más de 30 días, o apuntar a instalaciones recientes)
Los rangos relativos se actualizan automáticamente, lo que los hace ideales para campañas continuas. Las fechas fijas funcionan mejor para promociones acotadas en el tiempo.
:::
| Atributo | Filtrar por |
|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Age** | La edad del usuario. Ten en cuenta que la edad se calcula cuando Adapty la recibe por primera vez y no se actualiza después. |
| **App User ID** | El identificador del usuario en tu app ([customer_user_id](profiles-crm#user-attributes)). Puedes filtrar por su presencia o ausencia; por ejemplo, para mostrar un paywall solo a usuarios que no han iniciado sesión. |
| **App version (current)** | La versión actual de la app instalada en el dispositivo del usuario donde Adapty recibió datos de eventos por última vez — **se actualiza a medida que el usuario actualiza la app**, por lo que siempre refleja la versión que están ejecutando en ese momento. Úsala para dirigirte a todos los usuarios que ejecutan una versión específica, incluidos quienes actualizaron a ella desde una versión anterior. Al crear un segmento, selecciona el icono de lápiz junto a **App version** y añade una nueva versión para poder usarla de inmediato.
| Campo | Descripción |
| ------ |--------------------------------------------------------------------------------------------------------------------------------------|
| **Name** | Una etiqueta para el atributo personalizado, usada solo en el Adapty Dashboard. |
| **Key** | Un identificador único para el atributo. Debe coincidir con la clave utilizada en el SDK. |
| **Type** | Elige entre:
## Duplicar segmentos \{#duplicate-segments\}
Si necesitas un segmento similar a uno existente, duplícalo en lugar de crearlo desde cero. Esto ahorra tiempo a los equipos que gestionan varias campañas o pruebas A/B con grupos de usuarios que se solapan.
Duplicar un segmento crea una copia con todos sus filtros y descripción. Al nombre del nuevo segmento se le añade "(copy)" para que puedas distinguirlo del original. El nuevo segmento es independiente del original: los cambios en uno no afectan al otro.
Para duplicar un segmento en el Adapty Dashboard:
1. Abre la sección **Profiles & Segments** en el menú principal de Adapty y cambia a la pestaña [**Segments**](https://app.adapty.io/segments).
2. Haz clic en el botón de **3 puntos** junto al segmento y selecciona **Duplicate**.
3. Abre el nuevo segmento y ajusta sus filtros según sea necesario.
## Eliminar segmentos \{#delete-segments\}
Cuando ya no necesites un segmento, puedes eliminarlo de forma permanente.
Adapty bloquea la eliminación si el segmento se está usando como audiencia en alguno de los siguientes casos:
- **Un placement**: Al menos un placement no eliminado usa el segmento como audiencia.
- **Una prueba A/B (activa o completada)**: Al menos una prueba A/B no eliminada usa el segmento como audiencia.
Para eliminar segmentos, Adapty considera como activas tanto las pruebas A/B **Live** como las **Completed**. Una prueba completada sigue utilizando la audiencia para mostrar el paywall o onboarding posterior a la prueba a los usuarios que coincidan, y las métricas históricas de la prueba están vinculadas a ese segmento. El segmento solo se libera cuando se elimina la propia prueba A/B.
:::warning
La eliminación de un segmento es permanente. El segmento no se puede restaurar.
:::
Para eliminar un segmento en el Adapty Dashboard:
1. Ve a **Profiles & Segments** en el menú principal de Adapty y cambia a la pestaña [**Segments**](https://app.adapty.io/segments).
2. Haz clic en el botón de **3 puntos** junto al segmento y selecciona **Delete**.
3. Escribe el nombre del segmento en el campo de confirmación y haz clic en **Delete forever**.
:::info
Si el segmento está en uso, el cuadro de diálogo muestra los placements y las pruebas A/B que lo referencian.
Para desbloquear la eliminación, abre cada placement o prueba A/B de la lista y elimina el segmento de su audiencia, o elimina el placement o la prueba A/B por completo. Una vez que nada haga referencia al segmento, podrás eliminarlo.
:::
---
# File: event-feed
---
---
title: "Feed de eventos"
description: "Supervisa y analiza la actividad de los usuarios con el feed de eventos de Adapty."
---
El feed de eventos te permite rastrear visualmente los [Eventos](events) generados por Adapty y comprobar el estado de su exportación a integraciones de terceros, incluido el webhook.
:::warning
Ten en cuenta que las transacciones creadas mediante la [API del servidor (versión 1)](server-side-api-specs-legacy#requests) no aparecen en el **Event Feed**. Para asegurarte de que se incluyan, usa la [API del servidor (versión 2)](api-adapty/operations/setTransaction).
:::
:::note El estado de envío de AppsFlyer, Facebook Ads y Branch puede ser inexacto, ya que no siempre devuelven errores cuando se producen. ::: Para ver el perfil del usuario que ha iniciado la transacción, haz clic en el botón **View Profile** en los detalles del evento. --- # File: ab-tests --- --- title: "Prueba A/B" description: "Optimiza los precios de suscripción con pruebas A/B en Adapty para mejorar las tasas de conversión." --- :::tip Puedes obtener un plan de prueba A/B accionable sin hacer la investigación tú mismo. [Growth Autopilot](autopilot) audita tu paywall, compara a tus competidores y genera sugerencias a partir de datos anonimizados de más de 20.000 aplicaciones de suscripción rastreadas por Adapty. ::: Aumenta los ingresos de tu app ejecutando pruebas A/B en Adapty. Compara diferentes paywalls y onboardings para encontrar lo que mejor convierte, sin necesidad de cambios en el código. Por ejemplo, puedes probar: - Precios de suscripción - Diseño, textos y estructura del paywall - Períodos de prueba y duraciones de suscripción - Diseños de onboarding ## Requisitos previos \{#prerequisites\} Antes de configurar una prueba A/B, necesitas tener: - **Paywalls**: Un [paywall](paywalls) es una pantalla que se muestra a los usuarios para presentar tus ofertas de suscripción. Debes crear al menos dos paywalls antes de configurar una prueba A/B. - **Placements**: Un [placement](placements) es un espacio con nombre en tu app donde se muestra un paywall u onboarding. Tu prueba A/B se ejecuta dentro de uno o más placements. - **Onboardings**: Para las pruebas A/B de onboarding, también debes crear al menos dos [onboardings](onboardings). :::warning Si no usas el [Adapty Paywall Builder](adapty-paywall-builder), [envía las vistas del paywall a Adapty](present-remote-config-paywalls#track-paywall-view-events) con `.logShowPaywall()`. Sin este método, Adapty no puede calcular las vistas del paywall en la prueba y las estadísticas de conversión serán inexactas. ::: ## Tipos de prueba A/B \{#ab-test-types\} Adapty admite tres tipos de prueba A/B: - **Regular**: Se ejecuta en un único placement de paywall. - **Onboarding**: Se ejecuta en un único placement de onboarding. - **Crossplacement**: Se ejecuta en múltiples placements de paywall, mostrando la misma variante al usuario en todos ellos. Para una comparación completa de tipos, casos de uso y reglas de prioridad, consulta [Tipos de prueba A/B](ab-test-types). ## Próximos pasos \{#next-steps\} - [Growth Autopilot](autopilot) — Analiza tu paywall, obtén información de mercado y genera un plan de prueba A/B - [Tipos de prueba A/B](ab-test-types) — Aprende sobre los tipos de prueba y cuándo usar cada uno - [Crear, ejecutar y detener una prueba A/B](run_stop_ab_tests) — Configura y ejecuta tu primera prueba - [Resultados y métricas de la prueba A/B](results-and-metrics) — Entiende los datos de tu prueba A/B y elige un ganador --- # File: ab-test-types --- --- title: "Tipos de pruebas A/B" description: "Aprende sobre los tres tipos de pruebas A/B en Adapty: regular, onboarding y crossplacement." --- Adapty ofrece tres tipos de pruebas A/B, cada uno adecuado para diferentes escenarios de prueba: - **Prueba A/B regular:** Una prueba A/B creada para un único placement de [paywall](paywalls). - **Prueba A/B de onboarding:** Una prueba A/B creada para un único placement de [onboarding](onboardings). - **Prueba A/B crossplacement:** Una prueba A/B creada para múltiples placements de paywall en tu app. Una vez que la prueba A/B asigna una
## Diferencias clave \{#key-differences\}
| Característica | Prueba A/B regular | Prueba A/B crossplacement |
| ------------------------------------ |---------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
| **Qué se prueba** | Un paywall/onboarding | Conjunto de paywalls pertenecientes a una variante |
| **Consistencia de la variante** | La variante se determina de forma independiente para cada placement | La misma variante se usa en todos los placements de paywall |
| **Segmentación de audiencia** | Definida por placement de paywall/onboarding | Compartida en todos los placements de paywall |
| **Analítica** | Analizas un placement de paywall/onboarding | Analizas toda la app en los placements que forman parte de la prueba |
| **Distribución del peso de variante**| Por paywall/onboarding | Por conjunto de paywalls |
| **Usuarios** | Para todos los usuarios | Solo usuarios nuevos (los que no han visto ningún paywall de Adapty) |
| **Versión de Adapty SDK** | Cualquiera para paywalls. Para onboardings: v3.8.0+ (iOS, Android, React Native, Flutter), v3.14.0+ (Unity), v3.15.0+ (KMP, Capacitor) | 3.5.0+ |
| **Ideal para** | Probar cambios independientes en un único placement de paywall/onboarding sin considerar la economía global de la app | Evaluar estrategias de monetización globales en toda la app |
## Lógica de selección de pruebas A/B \{#ab-test-selection-logic\}
**Las pruebas A/B crossplacement tienen prioridad sobre las pruebas A/B regulares.** Sin embargo, las pruebas crossplacement solo se muestran a **usuarios nuevos**: aquellos que nunca han visto ningún paywall de Adapty (el método `getPaywall` del SDK nunca ha sido llamado para ellos). Esto garantiza la consistencia de los resultados entre placements.
El siguiente diagrama muestra la lógica que usa Adapty para seleccionar una prueba A/B para un placement:
En la página **A/B Tests**, las pruebas regulares, de onboarding y crossplacement aparecen en pestañas separadas.
## Limitaciones de las pruebas A/B crossplacement \{#crossplacement-ab-test-limitations\}
Las pruebas A/B crossplacement no pueden incluir placements de onboarding.
Las pruebas A/B crossplacement garantizan que cada usuario vea la misma variante en todos los placements de la prueba. Esto implica las siguientes limitaciones:
* Solo pueden participar usuarios nuevos. Un usuario nuevo es aquel que no ha visto ningún paywall de Adapty y cuya app nunca ha llamado a `getPaywall`. Adapty no puede garantizar una cadena de paywalls consistente para otros usuarios.
* El primer placement que encuentra el usuario determina qué paywall muestra Adapty. No puedes cambiar la asignación de un usuario ni inscribir al mismo usuario en más de una prueba A/B crossplacement.
:::warning
Una vez que un usuario recibe un paywall crossplacement, lo verá durante 90 días, incluso después de detener la prueba. Para cambiar esta duración, en los ajustes **General**, modifica **[Cross-placement variation stickiness](general#9-cross-placement-variation-stickiness)**.
:::
## Prioridad de las pruebas A/B crossplacement \{#crossplacement-ab-test-priority\}
* Las pruebas A/B crossplacement siempre tienen prioridad sobre las pruebas A/B regulares y de onboarding. Si un usuario nuevo cumple los requisitos tanto para una prueba crossplacement como para una prueba regular en el mismo placement, se muestra la prueba crossplacement.
* Cuando varias pruebas A/B crossplacement con la misma audiencia comparten el mismo placement, Adapty asigna automáticamente la prioridad de las pruebas según el orden en que se añadieron. La primera prueba tiene la prioridad más alta. No puedes cambiarla manualmente.
* Las pruebas que se dirigen a segmentos más pequeños de tu audiencia tienen automáticamente prioridad sobre las que se dirigen al segmento de todos los usuarios.
:::note
En Analytics, una prueba A/B crossplacement aparece como varias pruebas secundarias, una por placement. Las pruebas secundarias siguen el patrón de nomenclatura `
2. En la parte superior derecha, haz clic en **Create A/B test**.
3. En la ventana **Create the A/B test**, escribe un **Test name**. Este campo es obligatorio. Elige un nombre que describa claramente de qué trata la prueba para poder identificarla al revisar los resultados.
4. Rellena el **Test goal** para describir lo que quieres lograr (por ejemplo, aumentar las suscripciones o reducir la tasa de abandono).
5. Haz clic en **Select placement** y elige un placement de paywall para una prueba A/B normal o un placement de onboarding para una prueba A/B de onboarding.
6. Configura el contenido de la prueba en la tabla **Variants**. Cada fila es una variante y cada columna es un placement. Añade un paywall en cada intersección.
Por defecto, la tabla tiene 2 variantes y 1 placement. Puedes añadir hasta 20 variantes y varios placements. En cuanto añadas un segundo placement, la prueba se convierte en una prueba A/B Crossplacement.
Referencia:
| 1 | Renombra la variante para hacerla más descriptiva. |
| 2 | Cambia el peso de la variante. La suma de todas las variantes debe ser igual al 100%. |
| 3 | Añade más variantes si es necesario. |
| 4 | Añade más placements si es necesario. |
| 5 | Añade paywalls u onboardings para mostrar en los placements de cada variante. |
3. Cambia a la pestaña **Drafts**. Solo se pueden iniciar las pruebas en borrador.
4. Junto a la prueba que quieres lanzar, haz clic en **Run A/B test**.
5. Se abre la ventana **Edit A/B test**. Revisa la configuración y haz los cambios finales que necesites. Si falta el placement o la audiencia, agrégalos ahora.
6. Después de revisar la configuración, haz clic en **Run A/B test** para iniciarla.
Tras lanzar la prueba, puedes hacer seguimiento de su progreso y ver los datos de rendimiento en la página [Resultados y métricas de la prueba A/B](results-and-metrics).
## Detener una prueba A/B \{#stop-an-ab-test\}
Cuando detienes una prueba A/B, esta finaliza y puedes revisar los resultados. También decides qué mostrar a los usuarios en los placements afectados una vez que la prueba concluya.
1. Abre la sección [A/B tests](https://app.adapty.io/ab-tests) y ve a la pestaña **Live**.
2. Junto a la prueba que quieres detener, haz clic en el menú de tres puntos y elige **Stop A/B test**.
3. En la ventana **Stop the A/B test**, decide qué debe ocurrir una vez que finalice la prueba. Tienes tres opciones:
| Opción | Descripción |
|--------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Mostrar uno de los paywalls/onboardings probados | Elige el paywall o onboarding ganador según los resultados de la prueba, como ingresos, probabilidad de ser el mejor (**P2BB**) e ingresos por cada 1.000 usuarios. Este paywall u onboarding se mostrará para el placement y la audiencia seleccionados. |
| Seleccionar paywalls/onboardings que no participen en la prueba A/B | Elige cualquier paywall u onboarding que no forme parte de la prueba A/B actual. Úsalo cuando ninguna de las variantes probadas haya cumplido tus objetivos. |
| No mostrar ningún paywall/onboarding específico | Para el placement y la audiencia seleccionados, no se seleccionará ningún paywall u onboarding específico al finalizar la prueba A/B. En cambio, se mostrará el siguiente paywall u onboarding disponible según la prioridad de audiencia. Es una buena opción si prefieres que tu configuración actual decida qué paywall u onboarding mostrar, sin seleccionar uno manualmente. |
:::note
Detener una prueba A/B es irreversible — la prueba no puede reiniciarse. Asegúrate de haber recopilado suficientes datos antes de decidir detenerla.
:::
4. Haz clic en el botón **Stop and complete this A/B test**.
Una vez finalizada la prueba A/B, dejará de estar activa y los paywalls u onboardings de ella ya no se mostrarán a los nuevos usuarios.
Puedes seguir accediendo a los resultados y métricas de la prueba A/B en la [página de métricas de prueba A/B](results-and-metrics#metrics-controls) para revisar el rendimiento de los usuarios que participaron mientras la prueba estaba activa. Las métricas pueden seguir actualizándose a medida que se atribuyen nuevos eventos de compra o ingresos a esos usuarios.
---
# File: ab-test-no-paywall-variants
---
---
title: "Añadir variantes de prueba A/B sin paywalls"
description: "Ejecuta una prueba A/B donde una variante omite el paywall, usando una bandera de Remote Config para controlar si el paywall se muestra."
---
Puedes medir el impacto de tu paywall ejecutando una prueba A/B contra una variante vacía. Una variante muestra tu paywall; la otra no muestra nada. Tu app lee una bandera del Remote Config del paywall para decidir si renderizarlo.
## Cómo funciona \{#how-it-works\}
La configuración usa dos paywalls en el mismo placement:
- **Paywall A**: El paywall que quieres probar, con `show_paywall` establecido en `true` en su Remote Config.
- **Paywall B**: Un paywall vacío con `show_paywall` establecido en `false` en su Remote Config.
Cuando `getPaywall` devuelve un paywall, tu app lee la bandera `show_paywall`. Si la bandera es `true`, la app renderiza el paywall. Si la bandera es `false`, la app omite el renderizado y el usuario continúa sin ver un paywall.
## 1. Añade la bandera show_paywall en el Remote Config \{#1-add-the-show_paywall-flag-in-remote-config\}
Necesitas dos paywalls en el mismo placement: el Paywall A (el que quieres probar) y el Paywall B (un paywall vacío). Añade un campo `show_paywall` a cada uno para que tu app pueda ramificarse usando la misma clave en ambas variantes.
Para añadir la bandera al Paywall A:
1. Abre la sección [**Paywalls**](https://app.adapty.io/paywalls) en el menú principal de Adapty y selecciona el Paywall A.
2. Cambia a la pestaña **Remote config**.
3. En la vista **Table**, haz clic en **Add row** y crea un campo con el nombre `show_paywall` y el valor `true`. En la vista **JSON**, la entrada tiene este aspecto:
```json showLineNumbers
{
"show_paywall": true
}
```
4. Guarda los cambios.
Repite los mismos pasos para el Paywall B, pero establece `show_paywall` en `false`.
Para más detalles sobre el Remote Config, consulta [Diseña un paywall con Remote Config](customize-paywall-with-remote-config).
:::tip
Establecer `show_paywall` en ambas variantes hace que la ruta de código sea idéntica para los dos grupos y facilita ampliar el test con más variantes más adelante.
:::
## 2. Configura la prueba A/B \{#2-set-up-the-ab-test\}
1. [Crea una prueba A/B](run_stop_ab_tests) en el placement y añade ambos paywalls como variantes.
2. Establece los pesos de las variantes para distribuir el tráfico entre los usuarios que ven el paywall y los que no.
## 3. Comprueba la bandera en tu app \{#3-check-the-flag-in-your-app\}
Lee `show_paywall` del Remote Config del paywall devuelto por `getPaywall`. Si la bandera es `false`, omite el renderizado y deja que el usuario continúe.
**Revenue**: Esta métrica muestra el importe total en USD generado por compras y renovaciones, menos los reembolsos realizados a los usuarios. Incluye tanto la compra inicial como las renovaciones posteriores de la suscripción. Revenue te ayuda a entender el rendimiento financiero de cada variante de la prueba A/B e identificar cuál genera más dinero.
Consulta más información sobre las métricas de [paywall](paywall-metrics) y [onboarding](onboarding-metrics).
**Probability to be best**: Adapty utiliza un sólido marco de análisis matemático para analizar los resultados de las pruebas A/B y ofrece una métrica denominada Probability to be best. Esta métrica evalúa la probabilidad de que una variante concreta sea la opción de mejor rendimiento (en términos de ingresos a largo plazo) entre todas las variantes probadas. Se expresa como un porcentaje que va del 1% al 100%. Para más información sobre cómo Adapty calcula esta métrica, consulta la [documentación.](maths-behind-it) La opción de mejor rendimiento, determinada por Revenue per 1K user, se resalta en verde y se selecciona automáticamente como opción predeterminada.
**Revenue per 1K users**: La métrica de ingresos por cada 1.000 usuarios calcula el promedio de ingresos generados por cada 1.000 usuarios para cada variante de la prueba A/B. Esta métrica te ayuda a entender la eficiencia de ingresos de tus variantes, independientemente del número total de usuarios. Permite comparar el rendimiento de las distintas variantes en una escala estandarizada y tomar decisiones informadas basadas en la eficiencia de generación de ingresos.
**Prediction intervals for revenue 1K users**: La métrica de ingresos por cada 1.000 usuarios también incluye intervalos de predicción. Estos intervalos representan el rango dentro del cual se predice que caerán los ingresos reales por cada 1.000 usuarios de una variante determinada, basándose en los datos disponibles y el análisis estadístico.
En el contexto de las pruebas A/B, al analizar los ingresos generados por diferentes variantes, calculamos el promedio de ingresos por cada 1.000 usuarios para cada variante. Dado que los ingresos pueden variar entre usuarios, los intervalos de predicción ofrecen una indicación clara de los valores plausibles para los ingresos por cada 1.000 usuarios, teniendo en cuenta la variabilidad e incertidumbre asociadas al proceso de predicción.
Al incorporar los intervalos de predicción a la métrica de ingresos por cada 1.000 usuarios, Adapty te permite evaluar la eficiencia de ingresos de las variantes de tu prueba A/B considerando el rango de posibles resultados. Esta información te ayuda a tomar decisiones basadas en datos y a optimizar tu estrategia de suscripción de forma eficaz, teniendo en cuenta la incertidumbre del proceso de predicción y los valores plausibles para los ingresos por cada 1.000 usuarios.
Al analizar estas métricas de Adapty, puedes obtener información sobre el rendimiento financiero, la significancia estadística y la eficiencia de ingresos de las variantes de tus pruebas A/B, lo que te permite tomar decisiones basadas en datos y optimizar tu estrategia de suscripción de manera efectiva.
## Métricas de las pruebas A/B \{#ab-test-metrics\}
Adapty proporciona un conjunto completo de métricas para ayudarte a medir de forma efectiva el rendimiento de tus pruebas A/B realizadas en las variaciones de tu paywall u onboarding. Estas métricas se actualizan continuamente en tiempo real, excepto las vistas, que se actualizan de forma periódica. Entender estas métricas te ayudará a evaluar la efectividad de las distintas variaciones y a tomar decisiones basadas en datos para optimizar tu estrategia de paywall u onboarding.
Las métricas de las pruebas A/B están disponibles en la lista de pruebas A/B, donde puedes obtener una visión general del rendimiento de todas tus pruebas A/B. Esta vista completa ofrece métricas agregadas para cada variación de la prueba, lo que te permite comparar su rendimiento e identificar diferencias significativas. Para un análisis más detallado de cada prueba A/B, puedes acceder a las métricas de detalle de la prueba A/B. Esta sección proporciona métricas detalladas específicas para la prueba A/B seleccionada, lo que te permite profundizar en el rendimiento de las variaciones individuales.
Todas las métricas, excepto las vistas, se atribuyen al producto dentro del paywall o del onboarding.
## Controles de métricas \{#metrics-controls\}
El sistema muestra las métricas según el período de tiempo seleccionado y las organiza de acuerdo con el parámetro de la columna izquierda con tres niveles de sangría.
### Filtrado por fecha de instalación del perfil \{#profile-install-date-filtration\}
La casilla **Filter metrics by install date** permite filtrar las métricas según la fecha de instalación del perfil, en lugar de los filtros predeterminados que usan la fecha de prueba/compra para las transacciones o la fecha de visualización para las vistas de paywall u onboarding. Al marcar esta casilla, puedes centrarte en medir el rendimiento de adquisición de usuarios para un período específico, alineando las métricas con la fecha de instalación del perfil. Esta opción es útil para personalizar el análisis de métricas según tus necesidades concretas.
### Rangos de tiempo \{#time-ranges\}
Puedes elegir entre un rango de períodos de tiempo para analizar los datos de métricas, lo que te permite centrarte en duraciones específicas como días, semanas, meses o rangos de fechas personalizados.
### Filtros y agrupaciones disponibles \{#available-filters-and-grouping\}
:::link
Artículo principal: [Controles de Analytics](controls-filters-grouping-compare-proceeds)
:::
Adapty ofrece herramientas potentes para filtrar y personalizar el análisis de métricas según tus necesidades. Con la página de métricas de Adapty, tienes acceso a distintos rangos de tiempo, opciones de agrupación y posibilidades de filtrado.
- ✅ Filtrar por: Audiencia, atribución, país, paywall, estado del paywall, grupo de paywalls, onboarding, placement, país, store, producto y store del producto.
- ✅ Agrupar por: Producto y store.
:::note
Cuando filtras por prueba A/B, las pruebas A/B entre placements aparecen como pruebas secundarias independientes (por ejemplo, `My test child-0`, `My test child-1`), una por placement. Consulta [Limitaciones de las pruebas A/B entre placements](ab-test-types#crossplacement-ab-test-limitations) para más detalles.
:::
## Gráfico de métrica individual \{#single-metrics-chart\}
Uno de los componentes clave de la página de métricas de paywall u onboarding es la sección de gráficos, que representa visualmente las métricas seleccionadas y facilita su análisis.
La sección de gráficos de la página de métricas de la prueba A/B incluye un gráfico de barras horizontales que representa visualmente los valores de la métrica seleccionada. Cada barra del gráfico corresponde a un valor de métrica y su tamaño es proporcional, lo que facilita entender los datos de un vistazo. La línea horizontal indica el período de tiempo analizado, y la columna vertical muestra los valores numéricos de las métricas. El valor total de todos los valores de las métricas se muestra junto al gráfico.
Además, al hacer clic en el icono de flecha en la esquina superior derecha de la sección del gráfico, se expande la vista y se muestran las métricas seleccionadas en la línea completa del gráfico.
## Resumen de la prueba A/B \{#ab-test-summary\}
Junto al gráfico de métrica individual, se muestra la sección de resumen de detalles de la prueba A/B, que incluye información sobre el estado, la duración, los placements y otros detalles relacionados con la prueba A/B.
## Definiciones de métricas \{#metrics-definitions\}
Estas son las métricas clave disponibles para las pruebas A/B:
### Revenue \{#revenue\}
Revenue representa el importe total en USD generado por compras y renovaciones resultantes de la prueba A/B. Incluye la compra inicial y las renovaciones de suscripción posteriores. La métrica de ingresos se calcula antes de deducir la comisión de App Store o Play Store.
Consulta más información sobre las métricas de ingresos de [paywall](paywall-metrics#revenue) y [onboarding](onboarding-metrics#revenue).
### CR to purchases \{#cr-to-purchases\}
La tasa de conversión a compras mide la efectividad de tu prueba A/B para convertir vistas en compras reales. Se calcula dividiendo el número de compras por el número de vistas. Por ejemplo, si tuviste 10 compras y 100 vistas, la tasa de conversión a compras sería del 10%.
### CR trials \{#cr-trials\}
La tasa de conversión (CR) a trials es el número de trials iniciados desde la prueba A/B dividido por el número de vistas. La tasa de conversión a trials mide la efectividad de tu prueba A/B para convertir vistas en activaciones de trial. Se calcula dividiendo el número de trials iniciados por el número de vistas.
### Purchases \{#purchases\}
La métrica de compras representa el número total de transacciones realizadas dentro del paywall o el onboarding como resultado de la prueba A/B. Incluye los siguientes tipos de compras:
- Nuevas compras realizadas.
- Conversiones de trials activados.
- Cambios de nivel inferior, superior y cruzados de suscripciones.
- Restauraciones de suscripciones (por ejemplo, cuando una suscripción expira sin renovación automática y se restaura posteriormente).
Ten en cuenta que las renovaciones no están incluidas en la métrica de compras.
### Trials \{#trials\}
La métrica de trials indica el número total de trials activados como resultado de la prueba A/B.
### Trials cancelled \{#trials-cancelled\}
La métrica de trials cancelados representa el número de trials en los que se ha desactivado la renovación automática. Esto ocurre cuando los usuarios cancelan manualmente su suscripción al trial.
### Refunds \{#refunds\}
Los reembolsos de la prueba A/B representan el número de compras y suscripciones reembolsadas específicamente relacionadas con las variaciones probadas.
### Views \{#views\}
Las vistas son el número de visualizaciones de los paywalls o los onboardings que componen la prueba A/B. Si el usuario visita dos veces, se contarán como dos visitas.
### Unique views \{#unique-views\}
Las vistas únicas son el número de visualizaciones únicas del paywall o del onboarding. Si el usuario lo visita dos veces, se contará como una única vista.
### Probability to be the best \{#probability-to-be-the-best\}
La métrica Probability to be the best cuantifica la probabilidad de que una variante específica dentro de una prueba A/B sea la opción de mejor rendimiento entre todos los paywalls u onboardings probados. Proporciona una probabilidad numérica que indica el rendimiento relativo de cada paywall u onboarding. Se expresa como un porcentaje que va del 1% al 100%.
### ARPU (Average revenue per user) \{#arpu-average-revenue-per-user\}
Solo para pruebas A/B de onboarding. Mide el promedio de ingresos generados por cada usuario en un período específico. Se calcula dividiendo los ingresos totales por el número de usuarios únicos.
### ARPPU (Average revenue per paying user) \{#arppu-average-revenue-per-paying-user\}
ARPPU son las siglas de Average Revenue Per Paying User (ingresos medios por usuario de pago) resultantes de la prueba A/B. Se calcula como los ingresos totales divididos por el número de usuarios de pago únicos. Por ejemplo, si has generado 15.000 $ en ingresos de 1.000 usuarios de pago, el ARPPU sería de 15 $.
### ARPAS (Average revenue per active subscriber) \{#arpas-average-revenue-per-active-subscriber\}
ARPAS es una métrica que permite medir el promedio de ingresos generados por suscriptor activo en la ejecución de la prueba A/B. Se calcula dividiendo los ingresos totales por el número de suscriptores que han activado un trial o una suscripción. Por ejemplo, si los ingresos totales son 5.000 $ y tienes 1.000 suscriptores, el ARPAS sería de 5 $. Esta métrica ayuda a evaluar el potencial de monetización promedio por suscriptor.
### Proceeds \{#proceeds\}
La métrica de proceeds para la prueba A/B representa el importe real en USD recibido por el propietario de la app por compras y renovaciones, tras deducir la comisión aplicable de App Store o Play Store. Refleja los ingresos netos específicamente asociados a las variaciones probadas en la prueba A/B, contribuyendo directamente a las ganancias de la app. Para más información sobre cómo se calculan los proceeds, puedes consultar la [documentación](analytics-cohorts#revenue-vs-proceeds) de Adapty.
### Unique subscribers \{#unique-subscribers\}
La métrica de suscriptores únicos representa el recuento de personas distintas que se han suscrito o activado un trial a través de las variaciones de la prueba A/B. Cada suscriptor se contabiliza una sola vez, independientemente del número de suscripciones o trials que inicie.
### Unique paid subscribers \{#unique-paid-subscribers\}
La métrica de suscriptores de pago únicos representa el número de personas únicas que han completado con éxito una compra y se han convertido en suscriptores de pago a través de las variaciones de la prueba A/B.
### Refund rate \{#refund-rate\}
La tasa de reembolso para la prueba A/B se calcula dividiendo el número de reembolsos específicamente asociados a las variaciones de la prueba por el número de primeras compras (las renovaciones quedan excluidas). Por ejemplo, si hay 5 reembolsos y 1.000 primeras compras, la tasa de reembolso sería del 0,5%.
### Unique CR purchases \{#unique-cr-purchases\}
La tasa de conversión única a compras para la prueba A/B se calcula dividiendo el número de compras específicamente asociadas a las variaciones de la prueba por el número de vistas únicas. Por ejemplo, si hay 10 compras y 100 vistas únicas, la tasa de conversión única a compras sería del 10%.
### Unique CR trials \{#unique-cr-trials\}
La tasa de conversión única a trials para la prueba A/B se calcula dividiendo el número de trials iniciados específicamente asociados a las variaciones de la prueba por el número de vistas únicas. Por ejemplo, si hay 30 trials iniciados y 100 vistas únicas, la tasa de conversión única a trials sería del 30%.
### Completions y completions únicos \{#completions--unique-completions\}
Solo para pruebas A/B de onboarding. Los completions cuentan el número de veces que los usuarios completan tu onboarding a través de las variaciones de la prueba A/B, es decir, que pasan de la primera a la última pantalla. Si alguien lo completa dos veces, eso cuenta como dos **completions** pero un único **unique completion**.
### Unique completions rate \{#unique-completions-rate\}
Solo para pruebas A/B de onboarding. El número de completions únicos dividido por el número de vistas únicas. Esta métrica te ayuda a entender cómo interactúan los usuarios con el onboarding a través de las variaciones de la prueba A/B y a realizar cambios si detectas que los usuarios lo ignoran.
---
# File: maths-behind-it
---
---
title: "Matemáticas detrás de las pruebas A/B"
description: "Comprende las matemáticas detrás del análisis de suscripciones para obtener mejores insights sobre ingresos."
---
Las pruebas A/B son una técnica muy eficaz para comparar el rendimiento de dos versiones diferentes de un paywall u onboarding. El objetivo final es determinar qué versión resulta más efectiva en función de los ingresos medios por usuario a lo largo de 12 meses. Sin embargo, esperar un año completo para recopilar datos y tomar decisiones no es viable. Por eso se utiliza el ingreso por usuario en 2 semanas como métrica proxy, elegida a partir del análisis de datos históricos para aproximarse a la métrica objetivo. Para obtener resultados precisos y fiables, es fundamental emplear un método estadístico robusto capaz de manejar distintos tipos de datos. La estadística bayesiana, un enfoque muy extendido en el análisis de datos moderno, ofrece un marco flexible e intuitivo para las pruebas A/B. Al incorporar conocimiento previo y actualizarlo con nuevos datos, los métodos bayesianos permiten tomar mejores decisiones en condiciones de incertidumbre. Este documento es una guía completa del análisis matemático que utiliza Adapty para evaluar los resultados de las pruebas A/B y aportar insights valiosos para la toma de decisiones basada en datos.
## Enfoque de Adapty para el análisis estadístico \{#adaptys-approach-to-statistical-analysis\}
Adapty aplica un enfoque exhaustivo de análisis estadístico para evaluar el rendimiento de las pruebas A/B y ofrecer resultados precisos y fiables. Nuestra metodología consta de los siguientes pasos clave:
1. **Definición de la métrica:** Para llevar a cabo una prueba A/B con éxito, hay que identificar y definir la métrica clave que se alinee con los objetivos específicos del análisis. Adapty aprovechó una gran cantidad de datos históricos de aplicaciones de suscripción para determinar cuál encaja mejor como métrica proxy para el objetivo a largo plazo de ingresos medios al cabo de 1 año, y esa métrica es el ARPU a los 14 días.
2. **Formulación de hipótesis:** Creamos dos hipótesis para la prueba A/B. La hipótesis nula (H0) asume que no existe una diferencia significativa entre el grupo de control (A) y el grupo de prueba (B). La hipótesis alternativa (H1) sugiere que sí existe una diferencia significativa entre los dos o más grupos.
3. **Selección de distribución:** Elegimos la familia de distribución más adecuada en función de las características de los datos y la métrica observada. La opción más habitual es la distribución log-normal (teniendo en cuenta los valores cero).
4. **Cálculo de la probabilidad de ser el mejor:** Utilizando el enfoque bayesiano para las pruebas A/B, calculamos la probabilidad de que cada variante de paywall u onboarding que participa en el test sea la mejor opción. Este valor está relacionado con los p-valores que usábamos antes, pero es esencialmente un enfoque diferente, más robusto y más fácil de interpretar.
5. **Interpretación de resultados:** La probabilidad de ser el mejor es exactamente lo que sugiere su nombre. Cuanto mayor sea la probabilidad, mayor es la verosimilitud de que una opción concreta sea la mejor para el objetivo planteado. Tú mismo debes establecer el umbral para la toma de decisiones; dependerá de muchos otros factores propios de tu situación, pero un valor de probabilidad habitual es el 95%.
6. **Intervalos de predicción:** Adapty calcula intervalos de predicción para las métricas de rendimiento de cada grupo, ofreciendo un rango de valores dentro del cual es probable que se encuentre el parámetro real de la población. Esto ayuda a cuantificar la incertidumbre asociada a las métricas de rendimiento estimadas.
## Determinación del tamaño de la muestra \{#sample-size-determination\}
Determinar un tamaño de muestra adecuado es fundamental para obtener resultados de pruebas A/B fiables y concluyentes. Adapty tiene en cuenta factores como la potencia estadística y el tamaño del efecto esperado, que siguen siendo importantes incluso bajo el enfoque bayesiano, para garantizar un tamaño de muestra suficiente. Los métodos para estimar el tamaño de muestra requerido, específicos del enfoque bayesiano que empleamos actualmente, garantizan la fiabilidad del análisis.
Para saber más sobre el funcionamiento de las pruebas A/B, te recomendamos consultar nuestra documentación sobre [cómo crear](ab-tests) y [ejecutar pruebas A/B](run_stop_ab_tests), así como comprender las distintas [métricas y resultados de las pruebas A/B](results-and-metrics).
El marco analítico de Adapty para las pruebas A/B emplea ahora un enfoque bayesiano, aunque el foco sigue estando en la definición de métricas, la formulación de hipótesis y la selección de distribuciones. Sin embargo, en lugar de calcular p-valores, ahora computamos las distribuciones posteriores y calculamos la probabilidad de que cada variante sea la mejor. También determinamos los intervalos de predicción. Este enfoque revisado, que sigue siendo exhaustivo e incluso más robusto, está diseñado para ofrecer insights más intuitivos y fáciles de interpretar. El objetivo sigue siendo capacitar a las empresas para que optimicen sus estrategias, mejoren su rendimiento e impulsen el crecimiento a partir de un análisis estadístico sólido de sus pruebas A/B.
---
# File: autopilot-how-it-works
---
---
title: "Growth Autopilot: Cómo funciona"
description: "Entiende la lógica detrás del Growth Autopilot y confía en nosotros para hacer crecer tus ingresos."
---
[Growth Autopilot](autopilot) te ayuda a descubrir qué experimentos ejecutar basándose en tus datos de rendimiento reales y en cómo están funcionando apps similares en tu mercado. En lugar de adivinar qué podría funcionar, recibes recomendaciones concretas para pruebas con mayor probabilidad de mejorar tus resultados.
Este artículo ofrece una visión transparente de cómo funciona Autopilot: qué datos utiliza, cómo evalúa las oportunidades y por qué aparecen ciertas recomendaciones. El objetivo es que puedas usarlo con confianza como parte de tu flujo de trabajo de crecimiento.
## Qué hace realmente Autopilot \{#what-autopilot-actually-does\}
Autopilot analiza las métricas de tu app y tus paywalls para identificar los experimentos con mayor probabilidad de aumentar tus ingresos. Para ello, tiene en cuenta:
- **Tu configuración actual**: precios, pruebas, productos y cómo convierten
- **Patrones del mercado**: cómo estructuran sus ofertas apps similares y qué cobran
- **Tu historial de pruebas**: qué experimentos ya has realizado y qué revelaron
- **Potencial de crecimiento**: qué cambios tienen más probabilidades de marcar la diferencia
Autopilot utiliza IA para evaluar todos estos factores conjuntamente y convertirlos en pruebas A/B que puedes lanzar de inmediato. Obtienes un plan listo para usar sin necesidad de investigar a la competencia ni adivinar qué probar a continuación.
## Los datos detrás de Autopilot \{#the-data-behind-autopilot\}
Cada recomendación se construye a partir de tres fuentes de datos principales que trabajan juntas.
#### Los datos propios de tu app \{#your-apps-own-data\}
Autopilot analiza el rendimiento actual de tu app:
- Métricas de conversión en tus paywalls
- Estructura de precios y productos
Esto le da a Autopilot una base de partida antes de sugerir cualquier cambio.
:::note
No usamos los datos de rendimiento de tu app para entrenar recomendaciones de otras apps. Tus datos son privados.
:::
#### Análisis de paywall \{#paywall-analysis\}
Autopilot analiza la captura de pantalla de tu paywall y compara su diseño con los patrones establecidos por las apps de mayor rendimiento en tu categoría. Evalúa las decisiones de maquetación, los textos, el desglose de suscripciones y los elementos orientados a la conversión, como las insignias de ahorro o las secciones de reseñas.
Este análisis genera dos tipos de recomendaciones:
- **Recomendaciones basadas en benchmarks** fundamentadas en lo que hacen de manera diferente las apps con mejor rendimiento — cada una respaldada por una estadística concreta (por ejemplo, "Utilizada por el 72% de las apps de Educación con mejor rendimiento").
- **Recomendaciones de análisis visual** generadas por IA a partir de tu captura de pantalla, que incluyen mejoras de copy, cambios de diseño y otros ajustes visuales.
Estas recomendaciones se integran directamente en tu [plan de crecimiento](autopilot-growth-plan#view-the-growth-plan) como rondas de pruebas A/B.
#### Datos de la competencia \{#competitor-data\}
Autopilot compara tu configuración con aplicaciones similares en tu mercado usando información pública como precios, estructuras de suscripción y patrones comunes en tu categoría. Estas comparaciones son específicas por país, ya que los precios y estructuras de la competencia varían según el mercado. Los precios de la competencia proceden de fuentes externas y públicas como el App Store, lo que los diferencia de los datos anonimizados de la red de Adapty que utiliza el análisis de métricas.
De este modo, estás probando estrategias que ya funcionan en apps similares a la tuya, no simples ideas al azar. Al ver el análisis, puedes comparar tus benchmarks y los precios de la competencia en paralelo. Si apps similares obtienen mejores resultados con una estructura o un precio diferente, es una buena señal de que ese mismo enfoque podría funcionarte a ti también.
:::tip
Autopilot selecciona competidores relevantes automáticamente en función de con quién puedes competir de forma realista. En general, te recomendamos mantener esas sugerencias en lugar de añadir apps que estén muy por delante o muy por detrás. Si tu app pertenece a varias categorías, puede que quieras ajustar la lista para centrarte en el segmento de mercado más relevante.
:::
#### Puntos de referencia del sector \{#industry-benchmarks\}
Autopilot utiliza datos anonimizados de 20 000 apps de suscripción rastreadas por Adapty para mostrarte cómo te comparas con la media de tu categoría en un país concreto. Los datos se agregan a nivel de red y nunca se vinculan a una app específica.
Por ejemplo, tu embudo de conversión puede compararse con la media de apps de tu categoría y país. Así puedes ver si estás por debajo de la media, en la media o ya por delante.
#### Datos de mercado geográfico \{#geographic-market-data\}
Autopilot analiza mercados geográficos individuales —basándose en patrones de la red de 20.000 aplicaciones de Adapty— para identificar dónde los ajustes de precios regionales podrían generar más ingresos. Para cada país, evalúa:
- **Tasa de conversión**: cómo se compara la tasa de instalación a pago con la media global. Una tasa más alta puede indicar margen para subir precios; una más baja puede señalar sensibilidad al precio.
- **Índice de precios**: la posición del país en el [Índice de Precios de Adapty](https://uploads.adapty.io/adapty_pricing_index.pdf), que refleja el poder adquisitivo de sus habitantes.
Puedes actuar sobre estas recomendaciones creando pruebas A/B a partir de las [sugerencias de precios por región](autopilot-growth-plan#geo-pricing-hypotheses) de tu plan de crecimiento.
## Cómo decide Autopilot qué recomendar \{#how-autopilot-decides-what-to-recommend\}
Autopilot genera un conjunto de sugerencias para mejorar la conversión de tu paywall. Estas sugerencias están diseñadas para probarse una a una y así medir de forma fiable el impacto de cada cambio.
Así es como Autopilot elabora sus sugerencias:
1. **Encontrar las mayores oportunidades**
Autopilot revisa tus precios, productos y el rendimiento del embudo de conversión, y los compara con patrones del sector y aplicaciones similares. El análisis se ejecuta en la moneda de tu mercado principal —no solo en USD—, por lo que las recomendaciones de precio se ajustan a lo que realmente pagan tus suscriptores. Busca dónde tienes más margen de mejora, ya sea ajustando el precio, añadiendo un período de prueba o cambiando la estructura de tu oferta.
2. **Selecciona el siguiente experimento**
Cada hipótesis se genera a partir del historial de pruebas existente. Autopilot sabe qué experimentos ya has ejecutado, cuáles ganaron y qué direcciones aún vale la pena explorar. La siguiente sugerencia se basa en lo que reveló la anterior, en lugar de seguir una secuencia fija.
3. **Rondas de ganador contra retador**
Tras cada experimento, el ganador se convierte en tu nueva línea base. Ese resultado da forma a la siguiente recomendación en tu plan de crecimiento: Autopilot conserva lo que funcionó, descarta lo que no, y elige el siguiente test a partir de ahí.
4. **Mantenlo práctico**
Autopilot solo sugiere pruebas que puedes lanzar con tus productos y configuración actuales, o con pequeños cambios como crear un nuevo producto o ajustar un precio. El objetivo es que las pruebas sean rápidas y manejables.
5. **Mostrarte el razonamiento**
Para cada recomendación, Autopilot proporciona una hipótesis clara que explica exactamente por qué vale la pena ejecutar esta prueba. Verás cómo se comparan tus métricas actuales con las de la competencia y los promedios del sector, cuál es la oportunidad y qué métricas clave esperamos mejorar.
Esto convierte la experimentación en un proceso repetible donde cada prueba te enseña algo y te acerca a un paywall más efectivo.
## Qué ocurre después de cada experimento \{#what-happens-after-each-experiment\}
Las recomendaciones no se agotan. Cada prueba completada se convierte en la base para nuevos experimentos. Mientras sigas probando, Autopilot seguirá sugiriendo qué probar a continuación.
Para actualizar los datos de mercado subyacentes, también puedes volver a ejecutar el análisis completo. Esto incorpora los últimos datos de precios de competidores, referencias de conversión y tendencias de categoría. Una vez que hayas optimizado tu línea base, puede que también quieras competir con rivales más avanzados. Este enfoque iterativo te ayuda a seguir maximizando tus ingresos a medida que tu app crece y el mercado evoluciona.
:::tip
¿Listo para probarlo? Accede a [Growth Autopilot](autopilot-analysis) para analizar tus paywalls y generar un plan de crecimiento con pruebas A/B. Usa el asistente integrado para lanzar pruebas complejas sin complicaciones: te guiará paso a paso en la creación de productos, la duplicación de paywalls y la configuración de segmentos.
:::
---
# File: autopilot-analysis
---
---
title: "Análisis de Paywall y Mercado"
description: "Genera un plan de crecimiento basado en datos adaptado a tu app."
---
Sigue los pasos de este artículo para ejecutar el análisis de Growth Autopilot y generar un plan de crecimiento.
Si ya generaste un plan de crecimiento, haz clic en la pestaña [Resultados del análisis](#next-steps) para ver los informes.
## Análisis del paywall \{#paywall-analysis\}
### Selecciona un paywall para análisis \{#select-a-paywall-for-analysis\}
1. Abre la página **Growth Autopilot** y haz clic en el botón [Get Growth plan](https://app.adapty.io/ab-tests/analysis/start).
2. En la página **Paywall Diagnostic**, selecciona un **Placement** y un **Paywall** en los desplegables. Adapty preselecciona el placement con más ingresos y su paywall principal. Para analizar otro paywall, cambia primero el placement.
3. Sube una captura de pantalla. Growth Autopilot necesita una captura de pantalla para analizar el diseño y el contenido de tu paywall.
4. Revisa los productos activos del paywall. Las tarjetas de producto a la derecha muestran la duración de la suscripción, el precio y el período de prueba de cada producto.
5. Haz clic en **Confirm & Analyze** para continuar. Adapty analiza tu paywall y muestra el informe de diagnóstico.
### Informe de análisis de paywall \{#paywall-analysis-report\}
Cuando seleccionas un paywall y subes una captura de pantalla, Adapty analiza tu paywall en busca de patrones de diseño consolidados, destacando tanto los aciertos como las oportunidades de mejora.
#### Qué está funcionando bien \{#whats-working-well\}
Esta sección destaca el uso de patrones establecidos que maximizan la conversión. Por ejemplo: un badge de ahorro visible, una sección de reseñas de usuarios destacada o desgloses de suscripción claros.
#### Qué corregir en tu paywall \{#what-to-fix-on-your-paywall\}
Adapty agrupa sus recomendaciones en dos categorías:
- **Recomendaciones basadas en benchmarks**: Sugerencias respaldadas por datos de las apps con mejor rendimiento en tu categoría. Cada recomendación incluye una estadística de referencia (por ejemplo, "Usada por el 72% de las apps de Educación con mejor rendimiento") y una descripción del cambio propuesto.
- **Recomendaciones de análisis visual**: Sugerencias generadas por IA a partir de la captura de pantalla de tu paywall. Incluyen: mejoras en el copy, cambios de diseño y más.
:::tip
Tu [plan de crecimiento](autopilot-growth-plan#view-the-growth-plan) incluirá rondas de pruebas A/B basadas en las recomendaciones de referencia. Puedes añadir sugerencias de análisis visual al plan manualmente.
:::
Haz clic en **Get Market Insights** para continuar.
## Análisis de mercado y competencia \{#market-and-competitor-analysis\}
:::note
El análisis de mercado y competencia requiere completar primero el [análisis de paywall](#paywall-analysis).
:::
El análisis de Market Insights compara los precios y métricas de conversión de tu app con los de sus competidores y la media del sector. Las comparaciones son específicas por país. Para ofrecer un punto de referencia, Adapty agrega y analiza datos de apps de la App Store en tu subcategoría y país; información que no está disponible públicamente en ningún otro lugar.
### Seleccionar competidores \{#select-competitors\}
Selecciona hasta 5 competidores para la comparación.
Adapty elegirá 5 automáticamente y sugerirá 5 más. También puedes añadir apps manualmente con un enlace de App Store. Para obtener mejores resultados, selecciona apps con un MRR mayor que el tuyo.
Haz clic en **Generate report** para confirmar la lista y espera a que finalice el análisis.
### Seleccionar un país \{#select-a-country\}
Usa el desplegable **Country** para seleccionar uno de tus principales países y obtener un análisis detallado.
### Distribución de ingresos \{#revenue-distribution\}
Este gráfico de distribución de ingresos muestra de qué países provienen tus ingresos, con desglose por porcentajes. Destaca tus 5 países principales, que son el foco del resto del análisis.
### Precios de la competencia \{#competitor-pricing\}
La tabla de precios de la competencia compara los precios de suscripción de tu paywall con los de tus competidores en el [país seleccionado](#select-a-country). Incluye columnas separadas para cada duración de suscripción.
### Embudo de conversión \{#conversion-funnel\}
El gráfico muestra tus tasas de conversión — Vistas a prueba, Prueba a pago y Vistas a pago — junto a los promedios de aplicaciones similares.
### Distribución de ingresos por duración \{#revenue-distribution-by-duration\}
Este gráfico muestra qué duraciones de suscripción contribuyen más a tus ingresos, en comparación con la media del sector. Si tus ingresos están muy concentrados en una sola duración, puede ser una señal de oportunidad para optimizar tu estrategia de precios.
### ARPU de Activación
El gráfico **Activation ARPU: your app vs. category** compara el ingreso promedio por instalación nueva de tu app con el promedio de la categoría.
Úsalo junto con el [embudo de conversión](#conversion-funnel):
- La conversión muestra cuántos usuarios pagan.
- El ARPU de Activación muestra el ingreso promedio por usuario.
Una tasa de conversión alta con un ARPU de Activación bajo puede indicar que las ofertas tienen un precio demasiado bajo.
La métrica es **basada en cohortes**. Adapty toma los usuarios que instalaron la app en los últimos 90 días y divide los ingresos que generaron entre su número.
#### Comparación con otras métricas \{#comparison-to-other-metrics\}
El ARPU de activación no coincidirá con los valores de ARPU que ves en otras partes del dashboard — cada métrica mide algo diferente.
- **[El gráfico de análisis de ARPU](arpu)**: incluye renovaciones de cohortes anteriores, por lo que el valor es varias veces mayor que el ARPU de activación.
- **[Gráfico de ingresos](revenue), filtro de período establecido en "Activation"**: solo cuenta el primer pago de cada usuario. No cuenta las renovaciones realizadas por la cohorte en la ventana de 90 días.
- **[Ingresos por cohorte](analytics-cohorts) (90 días)**: el equivalente más cercano — usa esta métrica como referencia.
## Próximos pasos \{#next-steps\}
Lee el artículo [Gestionar y ejecutar tu plan de crecimiento](autopilot-growth-plan) para aprender a ejecutar pruebas A/B basadas en los resultados del análisis.
Siempre puedes ver los resultados de tu análisis desde la página del Plan de crecimiento. Solo tienes que hacer clic en la pestaña Analysis Results.
---
# File: autopilot-growth-plan
---
---
title: "Gestionar y ejecutar tu plan de crecimiento"
description: "Ejecuta pruebas A/B, archiva hipótesis y amplía el plan de crecimiento."
---
Tras completar [el análisis](autopilot-analysis), Adapty te presenta tu plan de crecimiento: una lista de hipótesis de mejora accionables.
Cada elemento del plan de crecimiento sugiere un nuevo precio, una mejora de diseño o un ajuste de precio por país. Abre una hipótesis para probarlo con una prueba A/B.
## Ver el plan de crecimiento \{#view-the-growth-plan\}
Cambia entre las distintas pestañas de la pantalla para filtrar las sugerencias por tipo:
- Las **hipótesis de precios** exploran nuevos puntos de precio o configuraciones de prueba. Cada ronda se basa en una recomendación concreta del diagnóstico del paywall o del informe de insights de mercado.
- Las **hipótesis visuales** son sugerencias de mejora de diseño. Pueden implicar cambios en el texto, el layout u otros elementos visuales.
- Las [hipótesis de geo-precios](#geo-pricing-hypotheses) prueban ajustes de precio específicos por país.
Puedes [añadir tus propias hipótesis](#add-your-own-hypothesis) de precios y visuales.
Las pruebas basadas en estas sugerencias pueden ejecutarse en cualquier orden, pero solo una a la vez. Como las audiencias de las rondas de precios geográficos no se solapan, estas pruebas pueden ejecutarse en paralelo entre sí.
### Hipótesis de precios geográficos \{#geo-pricing-hypotheses\}
:::important
Las compras únicas no son elegibles para la optimización de precios regionales.
:::
Abre la pestaña **Geo-pricing** para ver la lista de recomendaciones de rondas de precios geográficos. Cada recomendación se dirige a un país con un único cambio de precio y se ejecuta como una prueba A/B independiente.
Adapty detecta los países que necesitan ajustes de precios y proporciona recomendaciones basadas en datos validadas por el [Adapty Pricing Index](https://uploads.adapty.io/adapty_pricing_index.pdf).
#### Cómo genera Adapty las sugerencias de precios geográficos \{#how-adapty-makes-geo-pricing-suggestions\}
- Las recomendaciones de precios se basan en datos de App Store. La prueba A/B resultante puede ejecutarse tanto en App Store como en Google Play.
- El porcentaje de cambio de precio es el mismo para todas las duraciones de suscripción.
- Todos los precios se redondean al nivel de precio de App Store más cercano.
- Los precios se muestran en moneda local (por ejemplo, EUR o GBP) si Adapty dispone de datos de transacciones para ese país. Cuando no hay datos locales disponibles, los precios se muestran en USD.
## Modificar el plan \{#modify-the-plan\}
### Obtener nuevas recomendaciones \{#get-new-recommendations\}
Puedes actualizar el plan de crecimiento para obtener nuevas recomendaciones automáticas basadas en los datos de mercado más recientes.
Haz clic en **Update** y vuelve a iniciar el análisis. Una vez finalizado, Adapty actualizará las recomendaciones del plan de crecimiento. Si las nuevas sugerencias no te convencen, siempre puedes [restaurar](#restore-an-older-version-of-the-growth-plan) una versión anterior.
### Añadir tu propia hipótesis \{#add-your-own-hypothesis\}
Autopilot te permite ampliar tu plan de crecimiento con nuevas rondas. Haz clic en el botón "Add Hypothesis" para añadir una nueva hipótesis.
Rellena el formulario: añade un título, una descripción y selecciona el tipo de ronda (**Monetization** o **Visual**).
- Selecciona las métricas que esperas mejorar en el menú desplegable.
- Al añadir una ronda de monetización, debes especificar qué productos involucra la prueba.
## Ejecuta las pruebas \{#run-the-tests\}
Puedes ejecutar las pruebas en cualquier orden, pero debes ejecutarlas **de una en una**. Una vez que finalice una prueba, lleva la estrategia ganadora a la siguiente ronda. Cada ronda te acerca a una configuración más eficiente para tu aplicación.
Según nuestras estimaciones, ejecutar un conjunto completo de pruebas de Autopilot podría aumentar tus ingresos **hasta un 80%**.
:::important
Cada sugerencia incluye la duración mínima para la prueba A/B. Sigue estas recomendaciones para obtener los datos más precisos antes de pasar a la siguiente etapa. Tendrás que detener la prueba A/B manualmente.
:::
Abre una hipótesis y haz clic en **Set Up & Run Test** para iniciar el asistente de creación de pruebas A/B.
### Paso 1: Ver la hipótesis \{#step-1-view-the-hypothesis\}
El primer paso presenta un resumen de la hipótesis. Describe los cambios sugeridos y explica el razonamiento detrás de ellos. Haz clic en "Set up & Run Test" para pasar al siguiente paso.
### Paso 2: Crear nuevos productos \{#step-2-create-new-products\}
Si la prueba implica un cambio de precio, el segundo paso te ayuda a crear nuevos productos para la variante de prueba. Las hipótesis visuales omiten este paso.
* Haz clic en **Create a new product and push to stores** para crear un nuevo producto desde cero.
* Haz clic en **Connect an existing product** si el producto necesario ya existe en la configuración de tu store.
### Paso 3: Configurar el segmento y el paywall \{#step-3-set-up-segment-and-paywall\}
El tercer paso te permite configurar la variante de prueba del paywall. Adapty te sugiere duplicar el paywall y aplicar los cambios recomendados.
Para las **hipótesis de precios geográficos**, el asistente te pide que selecciones un segmento geolocalizado existente o que crees uno nuevo.
Haz clic en **Next** cuando el nuevo paywall esté listo y el segmento configurado.
### Paso 4: Revisar y lanzar \{#step-4-review--launch\}
El último paso es un resumen de la prueba que está a punto de ejecutarse. Incluye:
- Las métricas clave para **Variant A vs Variant B**: nombre del paywall, selección de productos, duración de la prueba y precio.
- La **Duration** (duración), el **Traffic** (distribución) y los **Subscribers** (tamaño mínimo de muestra) de la prueba.
- Una sección **How to interpret results** que describe qué señales indican el éxito de la prueba.
Revisa la configuración y haz clic en **Launch Test** para iniciar la prueba A/B.
## Restaurar una versión anterior del plan de crecimiento \{#restore-an-older-version-of-the-growth-plan\}
Haz clic en el botón **Clock** para ver el historial de versiones y volver a una versión anterior del análisis.
## Eliminar tu plan de crecimiento \{#delete-your-growth-plan\}
Para eliminar tu plan de crecimiento, abre el resumen del plan y haz clic en el botón **Trash**. Esta acción es irreversible.
:::warning
- Las pruebas A/B que ya hayas creado no se eliminarán.
- Esta acción elimina todas las versiones del plan de crecimiento. No podrás restaurar una versión anterior del análisis después de esto.
:::
Para crear un nuevo análisis, [empieza de nuevo](autopilot-analysis#select-a-paywall-for-analysis).
---
# File: how-adapty-analytics-works
---
---
title: "Cómo funciona Adapty Analytics"
description: "Aprende cómo funciona Adapty Analytics para rastrear el rendimiento de suscripciones de forma eficiente."
---
Este artículo describe cómo funciona Adapty Analytics: qué datos muestra, de dónde provienen y cómo se procesan. También explica las decisiones de diseño que hacen que Adapty Analytics sea diferente y cómo estas decisiones te benefician.
## Adapty Analytics vs. analíticas del store \{#adapty-analytics-vs-store-analytics\}
- **Variedad de datos**: Los stores solo pueden mostrar sus propios datos y no pueden acceder al comportamiento del usuario dentro de la app.
Adapty puede combinar datos de múltiples stores, así como fuentes adicionales: plataformas de marketing y redes publicitarias. El SDK de Adapty registra las interacciones de los usuarios con los paywalls y onboardings.
- **Frecuencia de actualización**: Los stores de apps suelen actualizar sus datos una vez al día, lo que puede limitar tu capacidad de tomar decisiones en tiempo real.
Adapty ofrece analíticas [casi en tiempo real](#data-processing).
- **Métricas avanzadas**: Los stores de apps muestran métricas básicas como descargas, ingresos y tasas de retención.
Adapty también calcula métricas avanzadas, como los ingresos recurrentes o el ingreso medio por usuario. Secciones dedicadas analizan problemas de suscripciones: abandono de usuarios, fallos de facturación, etc. Consulta el artículo [Tabla de comparación de métricas](metric-comparison-table) para ver la lista completa.
- **Predicciones**: Adapty usa algoritmos avanzados de machine learning para [predecir el LTV y los ingresos futuros](predicted-ltv-and-revenue).
## Datos y sus fuentes \{#data-and-its-sources\}
Adapty Analytics procesa los siguientes datos en [gráficos y tablas](analytics):
- [Eventos de suscripción](events) generados a lo largo del ciclo de vida del usuario: inicios de prueba, compras, renovaciones, cancelaciones, fallos de facturación y reembolsos. Adapty los agrega en los [gráficos de analíticas](analytics) y los reenvía en tiempo real a [webhooks](webhook), el [feed de eventos](event-feed) e [integraciones basadas en eventos](analytics-integration).
- [Datos de transacciones](revenue): ingresos, reembolsos, país del comprador, etc.
- **Datos de la aplicación**, como el número de instalaciones o las [interacciones con paywalls](paywalls).
- [Datos de atribución para transacciones](attribution-integration): fuentes de tráfico y campañas publicitarias.
Estos datos provienen de las siguientes fuentes:
- El
La columna **Predicted revenue** muestra los ingresos totales estimados que se espera que genere una cohorte de suscriptores durante el período de tiempo seleccionado desde la creación de la cohorte. Este valor se calcula usando el modelo de predicción de Adapty, basado en los patrones históricos de retención de cohortes de la app.
La columna **Predicted LTV** muestra el valor de vida estimado de cada usuario en la cohorte seleccionada. Este valor se calcula dividiendo los ingresos proyectados entre el número proyectado de usuarios de pago en la cohorte.
### Seleccionar el horizonte \{#select-the-horizon\}
Para cambiar el horizonte de predicción, selecciona un valor en el desplegable **Predictions**. Las opciones disponibles son 3, 6, 9, 12, 18 y 24 meses desde la creación de la cohorte.
### Filtrar por producto \{#filter-by-product\}
Puedes filtrar los ingresos proyectados y el LTV por producto. Por defecto, las predicciones se construyen a partir de todos los datos de compra; filtrar por producto muestra la contribución de cada producto.
## Cuándo las predicciones no están disponibles \{#when-predictions-are-unavailable\}
Cuando no se puede generar una predicción para una cohorte, las columnas de Ingresos Proyectados y LTV Proyectado muestran guiones largos (—) en lugar de valores. Esto puede ocurrir por varios motivos:
- **Tiempo insuficiente desde la creación de la cohorte**: Las predicciones solo están disponibles después de que la cohorte completa su primer período de renovación —aproximadamente una semana para suscripciones semanales y unas cuatro semanas para suscripciones mensuales.
- **Tamaño de la cohorte reducido**: Muy pocos suscriptores de pago para generar una proyección fiable.
- **Comportamiento inusual de la cohorte**: La cohorte se desvía significativamente de los patrones que espera el modelo. Esperar algunas semanas puede resolverlo a medida que se acumulan más datos.
- **Horizonte superado**: La cohorte es más antigua que el horizonte de predicción seleccionado. Por ejemplo, la predicción a 3 meses se oculta después de tres meses, la predicción a 12 meses después de doce meses, y no se muestran predicciones para cohortes con más de 24 meses de antigüedad.
:::warning
Al activar las predicciones, ten en cuenta que puede haber un retraso máximo de 24 horas antes de que los datos de predicción de Ingresos y LTV estén disponibles en tu Adapty Dashboard.
:::
---
# File: predictions-in-ab-tests
---
---
title: "Predicciones en pruebas A/B"
description: "Aprende cómo las predicciones en las pruebas A/B ayudan a perfeccionar las estrategias de precios de suscripción."
---
Bienvenido a la documentación de Análisis Predictivo de Adapty para nuestra funcionalidad de pruebas A/B. Esta herramienta te proporcionará información sobre los resultados futuros de tus pruebas A/B en curso y te ayudará a tomar decisiones basadas en datos más rápidamente 🚀 con las predicciones potenciadas por ML de Adapty.
### ¿Qué son las predicciones en pruebas A/B? \{#what-are-ab-test-predictions\}
Las predicciones de pruebas A/B de Adapty utilizan técnicas avanzadas de aprendizaje automático (concretamente modelos de gradient boosting) para pronosticar el potencial de ingresos a largo plazo de los paywalls que se comparan en una prueba A/B.
Este modelo predictivo te permite seleccionar el paywall más efectivo basándote en los ingresos proyectados al cabo de un año, en lugar de basarte únicamente en las métricas que observas mientras la prueba está en curso. Esto te permite decidir el ganador de forma más fiable y rápida, sin tener que esperar semanas a que se acumulen los datos.
### ¿Cómo funciona el modelo? \{#how-does-the-model-work\}
El modelo se entrena con un amplio historial de datos de pruebas A/B procedentes de una gran variedad de apps en distintas categorías. Incorpora un amplio conjunto de características para predecir los ingresos que es probable que genere un paywall en el año siguiente al inicio del experimento. Estas características incluyen:
- Transacciones de usuarios y tasas de conversión en diferentes períodos
- Distribución geográfica de los usuarios
- Plataforma de uso (iOS o Android)
- Tasas de cancelación y reembolso
- Productos de suscripción y sus duraciones (diaria, mensual, anual, etc.)
- Otros datos relacionados con transacciones
El modelo también tiene en cuenta los períodos de prueba en los paywalls, utilizando tasas de conversión históricas para predecir los ingresos como si los usuarios ya hubieran convertido. Esto garantiza una comparación justa entre paywalls con y sin ofertas de prueba, ya que también se tienen en cuenta las pruebas activas que potencialmente podrían generar ingresos en el futuro.
### ¿En qué se diferencia el P2BB Predicho del P2BB normal? \{#how-is-predicted-p2bb-different-from-just-the-p2bb\}
Nuestras pruebas A/B utilizan el enfoque bayesiano: básicamente modelamos la distribución de los ingresos por usuario (o "Ingresos por cada 1.000 usuarios", para ser más precisos) y luego calculamos la probabilidad de que una distribución sea "realmente" mejor que la otra y no por pura casualidad — a esto lo llamamos Probabilidad de ser el mejor o P2BB (puedes obtener más información sobre nuestro enfoque [aquí](maths-behind-it)).
Es importante tener en cuenta que al hacer esto, nos basamos únicamente en los ingresos que se han acumulado durante el tiempo que lleva ejecutándose la prueba. Por tanto, si quisieras realizar una prueba comparando una suscripción anual con una semanal, tendrías que esperar mucho tiempo para entender realmente cuál rinde mejor. Algo similar ocurre cuando comparas suscripciones con período de prueba frente a suscripciones sin período de prueba en una prueba A/B — ya que las pruebas activas que podrían potencialmente cambiar la dinámica del ganador nunca se tienen en cuenta en los ingresos.
Aquí es donde entra en juego nuestro modelo predictivo. Con la distribución de ingresos actual de una prueba A/B y entrenado sobre un amplio conjunto de datos, es capaz de predecir la versión futura de la distribución de ingresos (concretamente tras 1 año). Y tras hacerlo, produce un P2BB predicho — el que obtendrías si ejecutaras la prueba durante todo el año.
Ten en cuenta que a veces el P2BB predicho puede contradecir el P2BB actual. Cuando esto ocurre, resaltamos las filas de variación en amarillo, así:
Consideramos que esto es una señal de que deberías acumular más datos para confirmar el ganador o profundizar en la prueba A/B para averiguar la causa. En general, recomendamos confiar en el P2BB predicho sobre el P2BB actual porque simplemente tiene en cuenta más datos, aunque la decisión final es, por supuesto, tuya.
### Precisión y certeza del modelo \{#model-accuracy-and-certainty\}
El modelo alcanza un alto nivel de precisión, con un Error Porcentual Absoluto Medio (MAPE) ligeramente inferior al 10%. Este nivel de precisión permite a las empresas confiar en las predicciones del modelo al tomar decisiones basadas en datos.
Para garantizar aún más la estabilidad, el modelo emplea un criterio de "certeza" basado en tres factores:
- Un intervalo de predicción estrecho: el modelo tiene confianza en su resultado
- Una cantidad suficiente de suscripciones e ingresos en la prueba
- Han transcurrido al menos 2 semanas desde el inicio de la prueba
Una predicción se considera fiable cuando se cumplen al menos dos de estos tres criterios.
Cuando comienza una nueva prueba A/B, el modelo proporciona una predicción de ingresos por 1.000 usuarios a un año vista (nuestra métrica principal en pruebas A/B) para cada paywall. Las predicciones solo se muestran cuando cumplen los criterios de certeza. Si los datos son insuficientes, el modelo indicará "datos insuficientes para la predicción".
### Limitaciones y consideraciones \{#limitations-and-considerations\}
Aunque nuestro modelo predictivo es una herramienta potente, es importante tener en cuenta sus limitaciones.
El rendimiento del modelo depende de la calidad y representatividad de los datos disponibles. El comportamiento inusual de una cohorte o las apps nuevas que no están incluidas en el conjunto de entrenamiento pueden afectar a la precisión de las predicciones.
No obstante, las predicciones se actualizan diariamente para reflejar los datos y comportamientos de usuario más recientes. Esto garantiza que la información que recibes siempre se basa en los datos más actuales.
🚧 Nota: Esta herramienta es un complemento, no un sustituto, de tu criterio experto y tu comprensión de la dinámica particular de tu app. Utiliza estas predicciones como guía junto con otras métricas y el conocimiento del mercado para tomar decisiones fundamentadas.
---
# File: adapty-ads-manager
---
---
title: "Apple Ads Manager"
description: "Get realtime analytics from Apple Ads and manage and optimize your campaigns"
---
**Apple Ads Manager** is an all-in-one platform designed to help you manage, optimize, and scale your Apple Ads campaigns more efficiently. It connects your Apple Search Ads performance with key revenue metrics such as installs, trials, subscriptions, and lifetime value without requiring an MMP.
With real-time analytics, AI-driven forecasts, and smart automation, Apple Ads Manager eliminates tedious manual bid changes, spreadsheets, and guesswork, and replaces them with clear insights and tools that help you take action faster.
With Apple Ads Manager, you get:
- **[Overview](ads-manager-overview)**: All key metrics at a glance — spend, revenue, ROAS, CPA, and more — each with a daily trend chart
- **Real-time performance data**: Across campaigns, ad groups, and keywords
- **End-to-end revenue tracking**: From search → install → trial → subscription → LTV
- **AI predictions & recommendations**: For profitable scaling
- **Bulk management**: Of bids, budgets, statuses, and structures
- **Rule-based automations**: Manage the full keyword lifecycle
- **[Market Intelligence](ads-manager-market-intelligence)**: Competitor keyword strategies across 50+ countries
### Eventos compatibles \{#supported-events\}
Por defecto, Adapty envía tres grupos de eventos a User Acquisition:
- Trials
- Suscripciones
- Problemas
Puedes consultar la lista completa de eventos compatibles [aquí](events).
## Paso 2. Conecta tu plataforma de publicidad y añade enlaces de seguimiento \{#step-2-connect-your-ad-platform-and-add-tracking-links\}
Adapty utiliza enlaces de seguimiento para conectar las instalaciones de la app con los datos de la campaña.
Debes usar un enlace de seguimiento como URL de destino en cada campaña publicitaria que quieras medir en Adapty UA.
Si publicas anuncios en varias plataformas, configura los enlaces de seguimiento para cada plataforma por separado.
Adapty trabaja con plataformas de publicidad de dos maneras:
- **Integraciones nativas (Meta Ads, TikTok Ads).** Adapty se conecta directamente a la plataforma publicitaria. Los enlaces de seguimiento se generan automáticamente y los parámetros de la campaña se rellenan de forma dinámica según dónde se use el enlace. Puedes usar el mismo enlace en diferentes campañas, conjuntos de anuncios o creatividades, y Adapty recibirá automáticamente los datos correctos de la campaña y el gasto en publicidad.
- **Solo enlaces de seguimiento (todas las demás plataformas publicitarias).** Adapty no se conecta a la plataforma publicitaria. Los enlaces de seguimiento se crean manualmente y todos los parámetros de la campaña deben definirse explícitamente al crear el enlace. Los datos de gasto en publicidad no están disponibles para estas plataformas.
3. En el editor de políticas, pega el siguiente JSON y cambia `adapty-s3-integration-test` por el nombre de tu bucket:
```json showLineNumbers title="Json"
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListObjectsInBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::adapty-s3-integration-test"
},
{
"Sid": "AllowAllObjectActions",
"Effect": "Allow",
"Action": "s3:*Object",
"Resource": [
"arn:aws:s3:::adapty-s3-integration-test/*",
"arn:aws:s3:::adapty-s3-integration-test"
]
},
{
"Sid": "AllowBucketLocation",
"Effect": "Allow",
"Action": "s3:GetBucketLocation",
"Resource": "arn:aws:s3:::adapty-s3-integration-test"
}
]
}
```
4. Tras completar la configuración de la política, puedes añadir etiquetas (opcional) y luego hacer clic en **Next** para pasar al paso final
5. En este paso, asigna un nombre a tu política y haz clic en el botón **Create policy** para finalizar el proceso de creación
#### 1.2. Crear un usuario IAM \{#12-create-iam-user\}
Para que Adapty UA pueda subir informes de datos sin procesar a tu bucket, necesitarás proporcionarle el Access Key ID y el Secret Access Key de un usuario con acceso de escritura al bucket correspondiente.
1. Ve a la IAM Console y selecciona la [sección Users](https://console.aws.amazon.com/iamv2/home#/users)
2. Haz clic en el botón **Add users**
3. Asigna un nombre al usuario, elige **Access key – Programmatic access** y continúa con los permisos
4. En el siguiente paso, selecciona la opción **Add user to group** y luego haz clic en el botón **Create group**
5. A continuación, asigna un nombre a tu User Group y selecciona la política que creaste anteriormente
6. Una vez seleccionada la política, haz clic en el botón **Create group** para completar el proceso
7. Después de crear el grupo correctamente, **selecciónalo** y continúa al siguiente paso
8. Como este es el último paso de esta sección, puedes continuar simplemente haciendo clic en el botón **Create User**
9. Por último, puedes **descargar las credenciales en formato .csv** o bien copiarlas y pegarlas directamente desde el dashboard
### Paso 2. Configurar la integración en Adapty UA \{#step-2-configure-integration-in-adapty-ua\}
1. Ve a [**Integrations** -> **Amazon S3**](https://app.adapty.io/ua/integrations/s3)
2. Activa el toggle **Export install events to Amazon S3**.
3. Rellena los siguientes campos para establecer la conexión entre Amazon S3 y los perfiles de Adapty UA:
| Campo | Descripción |
|:-----------------------------| :----------------------------------------------------------- |
| **Access Key ID** | Identificador único que se usa para autenticar el acceso de un usuario o aplicación a un servicio de AWS. Encuéntralo en el [archivo csv](ua-amazon-s3#step-1-create-amazon-s3-credentials) descargado. |
| **Secret Access Key** | Clave privada que se usa junto con el Access Key ID para autenticar el acceso de un usuario o aplicación a un servicio de AWS. Encuéntrala en el [archivo csv](ua-amazon-s3#step-1-create-amazon-s3-credentials) descargado. |
| **S3 Bucket Name** | Nombre único global que identifica un bucket de S3 específico dentro de la nube de AWS. Los buckets de S3 son un servicio de almacenamiento simple que permite guardar y recuperar objetos de datos, como archivos e imágenes, en la nube. |
| **Folder Inside the Bucker** | El nombre de la carpeta que quieres tener dentro del bucket de S3 seleccionado. Ten en cuenta que S3 simula carpetas usando prefijos de clave de objeto, que son esencialmente nombres de carpeta. |
| **Region** (Opcional) | Obtén tu región en la AWS Management Console bajo tu cuenta de usuario IAM. |
## Exportación manual de datos \{#manual-data-export\}
Además de la exportación automática de datos de eventos a Amazon S3, Adapty UA también ofrece la funcionalidad de exportación manual de archivos. Con esta función, puedes seleccionar una fecha concreta para los datos de adquisición de usuarios y exportarlos manualmente a tu bucket de S3. Esto te da mayor control sobre qué datos exportas y cuándo lo haces.
## Estructura de la tabla \{#table-structure\}
En la integración con AWS S3, Adapty UA proporciona una tabla para almacenar el historial de datos de eventos de instalación. La tabla contiene información sobre el perfil del usuario, los ingresos y beneficios netos, y la store de origen, entre otros datos.
:::warning
Ten en cuenta que esta estructura puede crecer con el tiempo, con nuevos datos introducidos por nosotros o por terceros con los que trabajamos. Asegúrate de que el código que la procesa sea lo suficientemente robusto y se base en campos concretos, no en la estructura en su conjunto.
:::
Esta es la estructura de la tabla para los eventos:
| Columna | Descripción |
|--------------------------|-------------------------------------------|
| `adapty_profile_id` | Identificador único del perfil de Adapty |
| `install_id` | Identificador único de instalación |
| `created_at` | Marca de tiempo de creación del registro (ISO 8601) |
| `installed_at` | Marca de tiempo de instalación de la app (ISO 8601) |
| `store` | App store (`ios`, `android`) |
| `country` | Código de país del usuario (ISO 3166-1 alpha-2) |
| `ip_address` | Dirección IP del cliente |
| `idfa` | iOS Identifier for Advertisers |
| `idfv` | iOS Identifier for Vendors |
| `gaid` | Google Advertising ID (Android) |
| `android_id` | ID de dispositivo Android |
| `app_set_id` | Android App Set ID |
| `channel` | Canal de atribución |
| `campaign_id` | Identificador de campaña |
| `campaign_name` | Nombre de la campaña |
| `adset_id` | Identificador del conjunto de anuncios |
| `adset_name` | Nombre del conjunto de anuncios |
| `ad_id` | Identificador del anuncio |
| `ad_name` | Nombre del anuncio |
| `keyword_id` | Identificador de palabra clave |
| `keyword_name` | Nombre de la palabra clave |
| `asa_org_id` | ID de organización de Apple Search Ads |
| `asa_keyword_match_type` | Tipo de coincidencia de palabra clave de ASA (`Exact`, `Broad`) |
| `asa_attribution` | Datos de atribución de ASA (cadena JSON) |
| `asa_conversion_type` | Tipo de conversión de ASA |
| `asa_country_or_region` | País o región de ASA |
| `asa_creative_set_name` | Nombre del conjunto creativo de ASA |
| `fbclid` | Facebook Click ID |
| `ttclid` | TikTok Click ID |
| `utm_source` | Parámetro de fuente UTM |
| `utm_medium` | Parámetro de medio UTM |
| `utm_campaign` | Parámetro de campaña UTM |
| `utm_term` | Parámetro de término UTM |
| `utm_content` | Parámetro de contenido UTM |
---
# File: ua-google-cloud-storage
---
---
title: "Google Cloud Storage"
description: "Integra Google Cloud Storage con Adapty UA para almacenar de forma segura los datos de adquisición de usuarios."
---
La integración de Adapty UA con Google Cloud Storage te permite almacenar los datos de tus campañas de adquisición de usuarios de forma segura en un único lugar centralizado. Podrás guardar los datos de rendimiento de tus campañas, los datos de atribución y los eventos de adquisición de usuarios en tu bucket de Google Cloud Storage como archivos .csv.
Para configurar esta integración, deberás seguir unos sencillos pasos en la consola de Google Cloud y en el dashboard de Adapty UA.
:::note
Programación
Adapty UA envía tus datos a Google Cloud Storage cada 24h a las 4:00 UTC.
Cada archivo contendrá los datos de los eventos creados durante el día natural anterior completo en UTC. Por ejemplo, los datos exportados automáticamente a las 4:00 UTC del 8 de marzo incluirán todos los eventos creados el 7 de marzo desde las 00:00:00 hasta las 23:59:59 en UTC.
:::
## Cómo configurar la integración con Google Cloud Storage \{#how-to-set-up-google-cloud-storage-integration\}
### Paso 1. Crear las credenciales de Google Cloud Storage \{#step-1-create-google-cloud-storage-credentials\}
Esta guía te ayudará a crear las credenciales necesarias en la consola de Google Cloud Platform.
Para que Adapty UA pueda subir informes de datos sin procesar a tu bucket designado, se necesita la clave de la cuenta de servicio, así como acceso de escritura al bucket correspondiente. Al proporcionar la clave de la cuenta de servicio y conceder acceso de escritura al bucket, permites que Adapty UA transfiera de forma segura y eficiente los informes de datos sin procesar desde su plataforma a tu entorno de almacenamiento.
:::warning
Ten en cuenta que solo admitimos la autorización mediante clave HMAC de cuenta de servicio, por lo que es imprescindible que tu clave HMAC de cuenta de servicio tenga asignados los roles "Storage Object Viewer", "Storage Legacy Bucket Writer" y "Storage Object Creator" para habilitar el acceso correcto a Google Cloud Storage.
:::
#### 2.1. Crear una cuenta de servicio \{#21-create-service-account\}
1. Ve a la sección [IAM](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) de tu cuenta de Google Cloud y selecciona el proyecto correspondiente o crea uno nuevo
2. A continuación, crea una nueva cuenta de servicio para Adapty UA haciendo clic en el botón "+ CREATE SERVICE ACCOUNT"
3. Rellena los campos del primer paso, ya que el acceso se concederá en una etapa posterior. Para obtener más información sobre esta página, consulta la documentación [aquí](https://docs.cloud.google.com/iam/docs/service-accounts-create)
4. Para crear y descargar una [clave JSON privada](https://docs.cloud.google.com/iam/docs/keys-create-delete), ve a la sección KEYS y haz clic en el botón "ADD KEY"
5. En la sección DETAILS, localiza el valor de Email vinculado a la cuenta de servicio recién creada y cópialo. Esta información será necesaria en los próximos pasos para autorizar la cuenta y permitirle escribir en el bucket
#### 2.2. Configurar los permisos del bucket \{#22-configure-bucket-permissions\}
6. Ve a la página de [Buckets](https://console.cloud.google.com/storage/browser) de Google Cloud Storage y selecciona un bucket existente o crea uno nuevo para almacenar los informes de datos de adquisición de usuarios de Adapty UA
7. Ve a la sección PERMISSIONS y selecciona la opción [GRANT ACCESS](https://docs.cloud.google.com/identity/docs/how-to?hl=en)
8. En la sección PERMISSIONS, introduce el Email de la cuenta de servicio obtenido en el quinto paso anterior y selecciona el rol Storage Object Creator
9. Por último, haz clic en SAVE para aplicar los cambios
10. Recuerda guardar el nombre del bucket para futuras referencias
11. Tras completar estos pasos, habrás finalizado la configuración necesaria en la consola de Google Cloud. El último paso consiste en introducir el nombre del bucket y descargar el archivo JSON para usarlo en Adapty UA
### Paso 2. Configurar la integración en Adapty UA \{#step-2-configure-integration-in-adapty-ua\}
1. Ve a [**Integrations** -> **Google Cloud Storage**](https://app.adapty.io/ua/integrations/google-cloud-storage)
2. Activa el toggle **Export install events to Google Cloud Storage**
3. Rellena los campos requeridos para establecer la conexión entre Google Cloud Storage y Adapty UA:
| Campo | Descripción |
|:------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Google Cloud service account key file** | El [archivo de clave JSON](ua-google-cloud-storage#step-1-create-google-cloud-storage-credentials) privado descargado. |
| **Google Cloud bucket name** | El nombre del bucket en Google Cloud Storage donde deseas almacenar tus datos. Debe ser único dentro del entorno de Google Cloud Storage y no puede contener espacios. |
| **Folder inside the bucket** | El nombre de la carpeta dentro del bucket donde deseas almacenar tus datos. Debe ser único dentro del bucket y puede usarse para organizar los datos. Este campo es opcional. |
## Exportación manual de datos \{#manual-data-export\}
Además de la exportación automática de datos de eventos a Google Cloud Storage, Adapty UA también ofrece una funcionalidad de exportación manual de archivos. Con esta función, puedes seleccionar una fecha concreta para los datos de adquisición de usuarios y exportarlos manualmente a tu bucket de GCS. Esto te da mayor control sobre los datos que exportas y cuándo lo haces.
## Estructura de la tabla \{#table-structure\}
En la integración con Google Cloud Storage, Adapty UA proporciona una tabla para almacenar el historial de datos de eventos de instalación. La tabla contiene información sobre el perfil del usuario, los ingresos y beneficios, y el store de origen, entre otros datos.
:::warning
Ten en cuenta que esta estructura puede crecer con el tiempo, con nuevos datos introducidos por nosotros o por terceros con los que trabajamos. Asegúrate de que el código que procesa estos datos sea lo suficientemente robusto y se base en campos específicos, no en la estructura en su conjunto.
:::
A continuación se muestra la estructura de la tabla para los eventos:
| Columna | Descripción |
|--------------------------|-----------------------------------------------------|
| `adapty_profile_id` | Identificador único de perfil de Adapty |
| `install_id` | Identificador único de instalación |
| `created_at` | Marca de tiempo de creación del registro (ISO 8601) |
| `installed_at` | Marca de tiempo de instalación de la app (ISO 8601) |
| `store` | Store de la app (`ios`, `android`) |
| `country` | Código de país del usuario (ISO 3166-1 alpha-2) |
| `ip_address` | Dirección IP del cliente |
| `idfa` | Identificador de iOS para anunciantes |
| `idfv` | Identificador de iOS para proveedores |
| `gaid` | ID de publicidad de Google (Android) |
| `android_id` | ID de dispositivo Android |
| `app_set_id` | ID de conjunto de apps de Android |
| `channel` | Canal de atribución |
| `campaign_id` | Identificador de campaña |
| `campaign_name` | Nombre de campaña |
| `adset_id` | Identificador de conjunto de anuncios |
| `adset_name` | Nombre del conjunto de anuncios |
| `ad_id` | Identificador de anuncio |
| `ad_name` | Nombre del anuncio |
| `keyword_id` | Identificador de palabra clave |
| `keyword_name` | Nombre de la palabra clave |
| `asa_org_id` | ID de organización de Apple Search Ads |
| `asa_keyword_match_type` | Tipo de concordancia de palabra clave de ASA (`Exact`, `Broad`) |
| `asa_attribution` | Datos de atribución de ASA (cadena JSON) |
| `asa_conversion_type` | Tipo de conversión de ASA |
| `asa_country_or_region` | País o región de ASA |
| `asa_creative_set_name` | Nombre del conjunto creativo de ASA |
| `fbclid` | ID de clic de Facebook |
| `ttclid` | ID de clic de TikTok |
| `utm_source` | Parámetro de fuente UTM |
| `utm_medium` | Parámetro de medio UTM |
| `utm_campaign` | Parámetro de campaña UTM |
| `utm_term` | Parámetro de término UTM |
| `utm_content` | Parámetro de contenido UTM |
---
# File: adapty-mail
---
---
title: "Adapty Mail"
description: "AI-generated email campaigns that turn trial users into paid subscribers."
---
Las integraciones ofrecen las siguientes opciones de configuración que afectan a todos los eventos enviados a través de ella:
| Ajuste | Descripción |
|:--------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Reporting Proceeds** | Selecciona cómo se presentan los valores de ingresos: netos de las comisiones de App Store y Play Store, o brutos (antes de deducciones). Activa la casilla "Send sales as proceeds" para mostrar las ventas como ingresos netos tras descontar las comisiones de App Store / Play Store. |
| **Send Trial Price** | Si está marcado, Adapty transmitirá el precio de la suscripción para el evento Trial Started. |
| **Exclude Historical Events** | Elige excluir los eventos que ocurrieron antes de que el usuario instalara la app con el SDK de Adapty. Esto evita la duplicación de eventos y garantiza informes precisos. Por ejemplo, si un usuario activó una suscripción mensual el 10 de enero y actualizó la app con el SDK de Adapty el 6 de marzo, Adapty omitirá los eventos anteriores al 6 de marzo y conservará los posteriores. |
| **Report User's Currency** | Elige si las ventas se reportan en la divisa del usuario o en USD. |
| **Send User Attributes** | Si deseas enviar atributos específicos del usuario, como preferencias de idioma, y tu plan de OneSignal admite más de 10 etiquetas, selecciona esta opción. Al activarla, se permite incluir información adicional más allá de las 10 etiquetas predeterminadas. Ten en cuenta que superar los límites de etiquetas puede generar errores. |
| **Send Attributions** | Activa esta opción para transmitir información de atribución (por ejemplo, atribución de AppsFlyer) y recibir los detalles correspondientes. |
| **Send Play Store purchase token** | Activa esta opción para recibir el token de Play Store necesario para revalidar la compra si es preciso. Añadirá el parámetro `play_store_purchase_token` al evento. |
| **Delay events with future datetime** | **Solo para AppsFlyer y webhooks personalizados**: Cuando está activado, los eventos de renovación y conversión de trial se envían en la fecha en que realmente ocurren. Cuando está desactivado (por defecto), estos eventos se envían en cuanto se detectan, aunque la fecha sea futura. |
| **Data residency** | **Solo para Mixpanel y Amplitude**: Selecciona la residencia de datos para determinar dónde se procesan y almacenan tus eventos. |
## Configurar los eventos \{#configure-the-events\}
Debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar a la plataforma de integración seleccionada desde Adapty. Debes activar los que necesites.
Es importante tener en cuenta que la personalización de nombres de eventos está disponible en ciertas integraciones, mientras que en otras los nombres de eventos están fijos y no se pueden modificar. Además, con determinadas integraciones como [Airbridge](airbridge#configure-events-and-tags), por ejemplo, tienes la flexibilidad de asociar varios nombres de eventos a un único evento de Adapty. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Aunque recomendamos utilizar los nombres de eventos predeterminados de Adapty, tienes la libertad de adaptarlos según tus necesidades específicas.
---
# File: events
---
---
title: "Eventos para enviar a integraciones de terceros"
description: "Realiza el seguimiento de los eventos clave de suscripción con las herramientas de análisis de Adapty."
---
Apple y Google envían los eventos de suscripción directamente a los servidores mediante las [Notificaciones del servidor de App Store](enable-app-store-server-notifications) y las [Notificaciones de desarrollador en tiempo real (RTDN)](enable-real-time-developer-notifications-rtdn). Como resultado, las apps móviles no pueden enviar eventos a los sistemas de análisis en tiempo real de forma fiable. Por ejemplo, si un usuario se suscribe pero nunca vuelve a abrir la app, el desarrollador no recibirá ninguna actualización del estado de la suscripción sin un servidor.
Adapty cubre esta brecha recopilando datos de suscripción y convirtiéndolos en eventos legibles. Estos eventos de integración se envían en formato JSON. Aunque todos los eventos comparten la misma estructura, sus campos varían según el tipo de evento, el store y la configuración específica. Puedes consultar los campos exactos incluidos en cada evento en las páginas de integración correspondientes.
Para entender cómo determinar si un evento se procesó correctamente o si algo salió mal, consulta la página de [estados de eventos](event-statuses).
## Tipos de eventos \{#event-types\}
La mayoría de los eventos se crean y envían a todas las integraciones configuradas si están habilitadas. Sin embargo, el evento **Access level updated** solo se activa si la [integración de webhook](webhook) está configurada y este evento está habilitado. Este evento aparecerá en el [Event Feed](https://app.adapty.io/event-feed) y también se enviará al webhook, pero no se compartirá con otras integraciones.
Si no hay ninguna integración de webhook configurada o este tipo de evento no está habilitado, el evento **Access level updated** no se creará y no aparecerá en el [Event Feed](https://app.adapty.io/event-feed).
| Nombre del evento | Descripción |
|:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| subscription_started | Se activa cuando un usuario activa una suscripción de pago sin período de prueba, es decir, se le cobra de inmediato. |
| subscription_renewed | Ocurre cuando se renueva una suscripción y se cobra al usuario. Este evento comienza a partir de la segunda facturación, tanto en suscripciones con prueba como sin ella. |
| subscription_renewal_cancelled | El usuario ha desactivado la renovación automática de la suscripción. El usuario conserva el acceso a las funciones premium hasta el final del período de suscripción pagado. |
| subscription_renewal_reactivated | Se activa cuando un usuario reactiva la renovación automática de la suscripción. |
| subscription_expired | Se activa cuando una suscripción finaliza por completo tras ser cancelada. Por ejemplo, si un usuario cancela una suscripción el 12 de diciembre pero esta permanece activa hasta el 31 de diciembre, el evento se registra el 31 de diciembre cuando la suscripción expira. |
| subscription_paused | Ocurre cuando un usuario activa la [pausa de suscripción](https://developer.android.com/google/play/billing/lifecycle/subscriptions#pause) (solo Android). |
| subscription_deferred | Se activa cuando una compra de suscripción se [aplaza](https://adapty.io/glossary/subscription-purchase-deferral/), lo que permite a los usuarios retrasar el pago manteniendo el acceso a las funciones premium. Esta función está disponible a través de la Google Play Developer API y puede usarse para pruebas gratuitas o para ayudar a usuarios con dificultades económicas. |
| non_subscription_purchase | Cualquier compra que no sea una suscripción, como el acceso de por vida o productos consumibles como monedas del juego. |
| trial_started | Se activa cuando un usuario activa una suscripción de prueba. |
| trial_converted | Ocurre cuando finaliza una prueba y se cobra al usuario (primera compra). Por ejemplo, si un usuario tiene una prueba hasta el 14 de enero pero se le cobra el 7 de enero, este evento se registra el 7 de enero. |
| trial_renewal_cancelled | El usuario desactivó la renovación automática de la suscripción durante el período de prueba. El usuario conserva el acceso a las funciones premium hasta que finalice la prueba, pero no se le cobrará ni comenzará una suscripción. |
| trial_renewal_reactivated | Ocurre cuando un usuario reactiva la renovación automática de la suscripción durante el período de prueba. |
| trial_expired | Se activa cuando finaliza una prueba sin convertirse en suscripción. |
| entered_grace_period | Ocurre cuando falla un intento de pago y el usuario entra en un período de gracia (si está habilitado). El usuario conserva el acceso premium durante este tiempo. |
| billing_issue_detected | Se activa cuando ocurre un problema de facturación durante un intento de cobro (p. ej., saldo insuficiente en la tarjeta). |
| subscription_refunded | Se activa cuando se reembolsa una suscripción (p. ej., por parte del soporte de Apple). |
| non_subscription_purchase_refunded | Se activa cuando se reembolsa una compra que no es una suscripción. |
| access_level_updated | Ocurre cuando se actualiza el nivel de acceso de un usuario. |
Los eventos anteriores cubren completamente el estado de los usuarios en cuanto a compras. Veamos algunos ejemplos.
### Ejemplo 1 \{#example-1\}
_El usuario activó una suscripción mensual el 1 de abril con un periodo de prueba de 7 días. El día 4, se dio de baja._
En ese caso, se enviarán los siguientes eventos:
1. `trial_started` el 1 de abril
2. `trial_renewal_cancelled` el 4 de abril
3. `trial_expired` el 7 de abril
### Ejemplo 2 \{#example-2\}
_El usuario activó una suscripción mensual el 1 de abril con un periodo de prueba de 7 días. El día 10, se dio de baja._
En ese caso, se enviarán los siguientes eventos:
1. `trial_started` el 1 de abril
2. `trial_converted` el 7 de abril
3. `subscription_renewal_cancelled` el 10 de abril
4. `subscription_expired` el 1 de mayo
Para un desglose detallado de qué eventos se activan en cada escenario, consulta los [flujos de eventos](event-flows).
---
# File: event-flows
---
---
title: "Flujos de eventos"
description: "Descubre esquemas detallados de flujos de eventos de suscripción en Adapty. Aprende cómo se generan y envían los eventos de suscripción a las integraciones, lo que te ayuda a rastrear los momentos clave en el recorrido de tus clientes."
---
En Adapty recibirás distintos eventos de suscripción a lo largo del recorrido del usuario en tu app. Estos flujos de suscripción describen los escenarios más habituales para ayudarte a entender los eventos que Adapty genera cuando los usuarios se suscriben, cancelan o reactivan suscripciones.
Ten en cuenta que Apple procesa los pagos de suscripción varias horas antes del inicio o renovación real. En los flujos siguientes mostramos el inicio/renovación de la suscripción y el cargo ocurriendo al mismo tiempo para mantener los diagramas claros.
Además, los eventos relacionados con la misma acción ocurren de forma simultánea y pueden aparecer en tu **Event Feed** en cualquier orden, que podría diferir de la secuencia mostrada en nuestros diagramas.
## Ciclo de vida de la suscripción \{#subscription-lifecycle\}
### Flujo de compra inicial \{#initial-purchase-flow\}
Este flujo ocurre cuando un cliente compra una suscripción por primera vez sin período de prueba. En esta situación, se crean los siguientes eventos:
- **Subscription started**
- **Access level updated** para conceder acceso al usuario
Cuando llega la fecha de renovación de la suscripción, esta se renueva. En este caso, se crean los siguientes eventos:
- **Subscription renewal** para iniciar un nuevo período de la suscripción
- **Access level updated** para actualizar la fecha de vencimiento de la suscripción, extendiendo el acceso por otro período
Las situaciones en las que el pago no se realiza correctamente o el usuario cancela la renovación se describen en [Flujo de resultado de problema de facturación](event-flows#billing-issue-outcome-flow) y [Flujo de cancelación de suscripción](event-flows#subscription-cancellation-flow), respectivamente.
### Flujo de cancelación de suscripción \{#subscription-cancellation-flow\}
Cuando un usuario cancela su suscripción, se generan los siguientes eventos:
- **Subscription renewal canceled** para indicar que la suscripción sigue activa hasta el final del período actual, tras el cual el usuario perderá el acceso
- El evento **Access level updated** se crea para deshabilitar la renovación automática del nivel de acceso
Una vez que la suscripción finaliza, se activa el evento **Subscription expired (churned)** para marcar el fin de la suscripción.
Si se aprueba un reembolso, el siguiente evento reemplaza a **Subscription expired (churned)**:
- **Subscription refunded** para finalizar la suscripción y proporcionar los detalles del reembolso
En Stripe, una suscripción puede cancelarse de forma inmediata, omitiendo el período restante. En este caso, todos los eventos se crean simultáneamente:
- **Subscription renewal cancelled**
- **Subscription expired (churned)**
- **Access Level updated** para eliminar el acceso del usuario
Si se aprueba un reembolso, también se activa el evento **Subscription refunded** en el momento de la aprobación.
### Flujo de reactivación de suscripción \{#subscription-reactivation-flow\}
Si un usuario cancela una suscripción, esta expira y luego vuelve a comprarla, se creará un evento **Subscription renewed**. Aunque haya un período sin acceso, Adapty lo trata como una única cadena de transacciones vinculada por el `vendor_original_transaction_id`. Por tanto, la nueva compra se considera una renovación.
Los eventos **Access level updated** se crearán dos veces:
- al finalizar la suscripción, para revocar el acceso del usuario
- al recomprar la suscripción, para conceder el acceso
### Flujo de pausa de suscripción (solo Android) \{#subscription-pause-flow-android-only\}
Este flujo se aplica cuando un usuario pausa y posteriormente reanuda una suscripción en Android.
Pausar una suscripción tiene efectos diferidos. Si el usuario pausa una suscripción antes de que se renueve, la suscripción sigue activa y el usuario conserva el acceso de pago durante el resto del período de facturación.
1. Cuando el usuario pausa una suscripción, se activa el evento **Subscription paused (Android only)**.
2. Al finalizar el período de suscripción, Adapty activa el evento **Access level updated** para revocar el acceso del usuario.
3. Cuando el usuario reanuda la suscripción, se activan los siguientes eventos:
- **Subscription renewed**
- **Access level updated** para restaurar el acceso del usuario
Estas suscripciones pertenecerán a la misma cadena de transacciones, vinculadas por el mismo **vendor_original_transaction_id**.
## Flujos de prueba \{#trial-flows\}
Si usas períodos de prueba en tu app, recibirás eventos adicionales relacionados con las pruebas.
### Flujo de prueba con conversión exitosa \{#trial-with-successful-conversion-flow\}
El flujo más habitual ocurre cuando un usuario inicia una prueba, proporciona una tarjeta de crédito y se convierte exitosamente en una suscripción estándar al final del período de prueba. En este caso, los siguientes eventos se crean en el momento del inicio de la prueba:
- **Trial started** para marcar el inicio de la prueba
- **Access level updated** para conceder acceso
El evento **Trial converted** se crea cuando comienza la suscripción estándar.
### Flujo de prueba gratuita sin conversión exitosa \{#trial-without-successful-conversion-flow\}
Si un usuario cancela la prueba gratuita antes de que se convierta en una suscripción, en el momento de la cancelación se crean los siguientes eventos:
- **Trial renewal cancelled** para deshabilitar la conversión automática de la prueba gratuita en una suscripción
- **Access level updated** para deshabilitar la renovación del acceso
El usuario tendrá acceso hasta el final del período de prueba, momento en el que se crea el evento **Trial expired** para marcar su fin.
### Reactivación de suscripción tras un período de prueba expirado \{#subscription-reactivation-after-expired-trial-flow\}
Si un período de prueba expira (por un problema de pago o cancelación) y el usuario luego compra una suscripción, se crean los siguientes eventos:
- **Access level updated** para conceder acceso al usuario
- **Trial converted**
Aunque haya un intervalo entre el período de prueba y la suscripción, Adapty vincula ambos mediante `vendor_original_transaction_id`. Esta conversión se trata como parte de una cadena de transacciones continua que comienza con un período de prueba de precio cero. Por eso se crea el evento **Trial converted** en lugar de **Subscription started**.
## Cambios de producto \{#product-changes\}
Esta sección cubre los ajustes realizados en suscripciones activas, como actualizaciones, degradaciones o compras de un producto de otro grupo.
### Flujo de cambio de producto inmediato \{#immediate-product-change-flow\}
Después de que un usuario cambia un producto, el cambio puede aplicarse en el sistema de forma inmediata antes de que finalice la suscripción (principalmente en casos de actualización o sustitución de un producto). En este caso, en el momento del cambio de producto:
- El nivel de acceso cambia y se crean dos eventos **Access level updated**:
1. para eliminar el acceso al primer producto.
2. para conceder acceso al segundo producto.
- La suscripción antigua finaliza y se realiza un reembolso (se crea el evento **Subscription refunded** con `cancellation_reason` = `upgraded`). Ten en cuenta que no se crea ningún evento **Subscription expired (churned)**; el evento **Subscription refunded** lo reemplaza.
- La nueva suscripción comienza (se crea el evento **Subscription started** para el nuevo producto).
Si un usuario realiza un downgrade de su suscripción, la primera suscripción se mantendrá activa hasta el final del período pagado y, cuando finalice, será reemplazada por la nueva suscripción de nivel inferior. En este caso, solo se creará de inmediato el evento **Access level updated** para deshabilitar la renovación automática del acceso. El resto de los eventos se crearán en el momento en que se produzca el reemplazo efectivo de la suscripción:
- Se crea otro evento **Access level updated** para conceder acceso al segundo producto.
- Se crea el evento **Subscription expired (churned)** para finalizar la suscripción del primer producto.
- Se crea el evento **Subscription started** para iniciar una nueva suscripción con el nuevo producto.
### Flujo de cambio de producto diferido \{#delayed-product-change-flow\}
También existe una variante en la que el usuario cambia el producto en el momento de la renovación de la suscripción. Esta variante es muy similar a la anterior: se creará un evento **Access level updated** para deshabilitar la autorenovación del acceso al producto anterior. El resto de eventos se crearán en el momento en que el usuario cambie la suscripción y el cambio quede registrado en el sistema:
- Se crea otro evento **Access level updated** para conceder acceso al segundo producto.
- Se crea el evento **Subscription expired (churned)** para finalizar la suscripción del primer producto.
- Se crea el evento **Subscription started** para iniciar una nueva suscripción con el nuevo producto.
## Flujo de resultados ante un problema de facturación \{#billing-issue-outcome-flow\}
Si los intentos de convertir una prueba o renovar una suscripción fallan por un problema de facturación, lo que ocurre a continuación depende de si hay un período de gracia habilitado.
Con un período de gracia, si el pago se realiza correctamente, la prueba se convierte o la suscripción se renueva. Si falla, el store seguirá intentando cobrar al usuario por la suscripción y, si continúa fallando, el store pondrá fin a la prueba o suscripción por sí mismo.
Por lo tanto, en el momento del problema de facturación, se crean los siguientes eventos en Adapty:
- **Billing issue detected**
- **Entered grace period** (si el período de gracia está activado)
- **Access level updated** para mantener el acceso hasta el final del período de gracia
Si el pago se completa más adelante, Adapty registra un evento **Trial converted** o **Subscription renewed**, y el usuario no pierde el acceso.
Si el pago finalmente falla y el store cancela la suscripción, Adapty genera estos eventos:
- **Trial expired** o **Subscription expired (churned)** con `cancellation_reason: billing_error`
- **Access level updated** para revocar el acceso del usuario
Sin período de gracia, el Período de Reintento de Cobro (el período durante el cual el store sigue intentando cobrar al usuario) comienza de inmediato.
Si el pago nunca tiene éxito antes de que finalice el período de gracia, el flujo es el mismo: se crean los mismos eventos cuando el store cancela la suscripción automáticamente:
- Evento **Trial expired** o **Subscription expired (churned)** con un `cancellation_reason` de `billing_error`
- **Access level updated** para revocar el acceso del usuario
## Flujos para compartir compras entre cuentas de usuario \{#sharing-purchases-across-user-accounts-flows\}
Cuando un
A continuación se describen los campos relacionados con la asignación y transferencia del nivel de acceso en los eventos generados en este escenario:
- **Usuario A: Nivel de acceso actualizado (se envía cuando el Usuario A realiza una compra de suscripción en la app)**
```json showLineNumbers
{
"profile_id": "00000000-0000-0000-0000-000000000000",
"customer_user_id": UserA,
"event_properties": {
"profile_has_access_level": true,
},
"profiles_sharing_access_level": null
}
```
- **Usuario A: Nivel de acceso actualizado (se envía cuando se reinstala la app y el Usuario B inicia sesión, revocando el acceso del Usuario A)**
```json showLineNumbers
{
"profile_id": "00000000-0000-0000-0000-000000000000",
"customer_user_id": UserA,
"event_properties": {
"profile_has_access_level": false,
},
"profiles_sharing_access_level": null
}
```
- **Usuario B: Nivel de acceso actualizado (enviado cuando el Usuario B inicia sesión y se concede el acceso)**
```json showLineNumbers
{
"profile_id": "00000000-0000-0000-0000-000000000001",
"customer_user_id": UserB,
"event_properties": {
"profile_has_access_level": true,
},
"profiles_sharing_access_level": null
}
```
### Flujo de acceso compartido entre usuarios \{#shared-access-between-users-flow\}
Esta opción permite que varios usuarios compartan el mismo nivel de acceso si su dispositivo está conectado con el mismo Apple/Google ID. Resulta útil cuando un usuario reinstala la app e inicia sesión con un correo diferente: seguirá teniendo acceso a su compra anterior. Con esta opción, varios usuarios identificados pueden compartir el mismo nivel de acceso. Mientras el nivel de acceso se comparte, todas las transacciones se registran bajo el
A continuación se describen los campos relacionados con la asignación y el intercambio de niveles de acceso en los eventos generados en este escenario:
**Usuario B: Access level updated (enviado cuando el Usuario B inicia sesión y se concede el acceso)**
```json showLineNumbers
{
"profile_id": "00000000-0000-0000-0000-000000000000",
"customer_user_id": UserA,
"event_properties": {
"profile_has_access_level": true,
},
"profiles_sharing_access_level": [
{
"profile_id": "00000000-0000-0000-0000-000000000001,
"customer_user_id": UserB
}
]
}
```
### Flujo de acceso no compartido entre usuarios \{#access-not-shared-between-users-flow\}
Con esta opción, solo el primer perfil de usuario que reciba el nivel de acceso lo conserva de forma permanente. Es ideal cuando las compras deben estar vinculadas a un único
---
# File: event-statuses
---
---
title: "Estados de los eventos de integración"
description: ""
---
Adapty determina la entregabilidad en función del código de estado HTTP, considerando cualquier respuesta fuera del rango `200-399` como un error.
Puedes hacer seguimiento del estado de los eventos de integración en la **Event List** dentro del Adapty Dashboard. El sistema muestra los estados de todas las integraciones habilitadas, independientemente de si un tipo de evento específico está activado para una integración concreta.
- Negro: El evento se envió correctamente.
- Gris: El tipo de evento está deshabilitado para esta integración.
- Rojo: Hay un problema con la integración que requiere atención.
Para más detalles sobre los eventos fallidos, pasa el cursor sobre el nombre de la integración para ver un tooltip con información específica del error.
El **Event Feed** muestra datos de las últimas dos semanas para optimizar el rendimiento. Esta limitación mejora la velocidad de carga de la página, lo que facilita a los usuarios navegar y analizar los eventos de forma eficiente.
---
# File: adjust
---
---
title: "Adjust"
description: "Conecta Adjust con Adapty para un mejor seguimiento de suscripciones y análisis."
---
[Adjust](https://www.adjust.com/) es una de las principales plataformas MMP (Mobile Measurement Partner) que recopila y presenta datos de campañas de marketing para ayudar a las empresas a medir el rendimiento de sus campañas.
Adapty proporciona un conjunto completo de datos que te permite rastrear [eventos de suscripción](events) de los stores en un solo lugar. Con Adapty, puedes ver fácilmente el comportamiento de tus suscriptores, conocer sus preferencias y usar esa información para comunicarte con ellos de forma dirigida y efectiva. Esta integración te permite rastrear eventos de suscripción en Adjust y analizar con precisión cuántos ingresos generan tus campañas.
La integración entre Adapty y Adjust funciona de dos maneras principales.
1. **Adapty recibe datos de atribución de Adjust**
Una vez que hayas configurado la integración con Adjust, Adapty comenzará a recibir datos de atribución de Adjust. Puedes acceder a estos datos fácilmente en la página del perfil del usuario.
2. **Adapty envía eventos de suscripción a Adjust**
Adapty puede enviar todos los eventos de suscripción configurados en tu integración a Adjust. Como resultado, podrás rastrear estos eventos dentro del dashboard de Adjust. Esta integración es muy útil para evaluar la efectividad de tus campañas publicitarias.
## Configurar la integración \{#set-up-integration\}
### Conectar Adapty a Adjust \{#connect-adapty-to-adjust\}
1. Abre el Adapty Dashboard y ve a [Integrations > Adjust](https://app.adapty.io/integrations/adjust).
2. Activa el interruptor en la parte superior de la página.
3. Rellena los campos e introduce tus credenciales de acceso.
3. Si habilitaste la autorización OAuth en la plataforma de Adjust, es obligatorio proporcionar un **OAuth Token** durante el proceso de integración para tus apps de iOS y Android.
4. A continuación, proporciona los **app tokens** para tus apps de iOS y Android. Abre tu dashboard de Adjust y verás tus apps.
:::note
Puedes tener aplicaciones de Adjust distintas para iOS y Android, por eso en Adapty hay dos secciones independientes para ello. Si solo tienes una app de Adjust, simplemente introduce la misma información en ambas.
:::
5. Selecciona tu app de la lista y copia el **App Token**. Pega el token en el campo correspondiente del dashboard de Adapty.
### Configurar eventos y etiquetas \{#configure-events-and-tags\}
Adjust funciona de manera algo diferente al resto de plataformas. Debes crear los eventos manualmente en el dashboard de Adjust, obtener los tokens de evento y copiarlos en los eventos correspondientes en Adapty.
El primer paso es encontrar los tokens de evento para todos los eventos que quieres que Adapty envíe. Para eso:
1. En el dashboard de Adjust, abre tu app y cambia a la pestaña **Events**.
1. Copia el token del evento y pégalo en Adapty. Debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar desde Adapty a Adjust. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Adapty enviará eventos de suscripción a Adjust mediante una integración servidor a servidor, lo que te permitirá ver todos los eventos de suscripción en tu dashboard de Adjust y vincularlos a tus campañas de adquisición.
:::important
Ten en cuenta lo siguiente:
- Adjust no admite eventos con más de 58 días de antigüedad. Si tienes un evento anterior a ese plazo, Adapty lo enviará a Adjust, pero la fecha y hora del evento se reemplazará por la marca de tiempo actual.
- Adjust no es compatible con IPv6. Si desactivas la recopilación de IP en el SDK desde **App settings** o al activar el SDK, puede que solo se envíe una IPv6 del backend y el seguimiento falle — mantén la recopilación de IP del SDK activada para asegurarte de que se use IPv4.
:::
### Conectar tu app a Adjust \{#connect-your-app-to-adjust\}
Tras completar los pasos anteriores, añade los dos métodos siguientes a tu app. Establecerán la comunicación entre tu app y Adjust:
1. **Para enviar datos de suscripción a Adjust**: pasa el ID de dispositivo de Adjust al método `setIntegrationIdentifier()` del SDK.
2. **Para recibir datos de atribución de Adjust**: actualiza los datos de atribución con el método `updateAttribution()` del SDK.
Para Adjust versión 5.0 o posterior, usa el siguiente ejemplo:
Ambos se encuentran en tu dashboard de Airbridge, en la sección [Third-party Integrations > Adapty](https://app.airbridge.io/app/testad/integrations/third-party/adapty).
El campo del token de API de Adapty se genera previamente en el backend de Adapty. Debes copiar el valor del token de API de Adapty y pegarlo en el dashboard de Airbridge en el campo Adapty Authorization Token.
### Configurar eventos y etiquetas \{#configure-events-and-tags\}
Debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar a Airbridge desde Adapty.
Simplemente activa los que necesites.
### Conectar tu app con Airbridge \{#connect-your-app-to-airbridge\}
Para la integración, debes pasar `airbridge_device_id` al perfil y llamar a `setIntegrationIdentifier` tal como se muestra en el siguiente ejemplo:
## Configurar la integración \{#set-up-integration\}
### Conectar Adapty al framework AdServices \{#connect-adapty-to-the-adservices-framework\}
Apple Ads a través de [AdServices](https://developer.apple.com/documentation/adservices) requiere cierta configuración en el Adapty Dashboard, y también deberás habilitarlo en la parte de la app. Para configurar Apple Ads usando el framework AdServices a través de Adapty, sigue estos pasos:
#### Paso 1: Configurar Info.plist \{#step-1-configure-infoplist\}
Añade `AdaptyAppleSearchAdsAttributionCollectionEnabled` al archivo `Info.plist` de la app y establece su valor en `YES` (booleano).
#### Paso 2: Obtener la clave pública \{#step-2-obtain-public-key\}
En el Adapty Dashboard, ve a [Settings -> Apple Ads.](https://app.adapty.io/settings/apple-search-ads)
Localiza la clave pública pregenerada (Adapty te proporciona un par de claves) y cópiala.
:::note
Si usas un servicio alternativo o tu propia solución para la atribución de Apple Ads, puedes subir tu propia clave privada.
:::
#### Paso 3: Configurar la gestión de usuarios en Apple Ads \{#step-3-configure-user-management-on-apple-ads\}
En tu [cuenta de Apple Ads](https://ads.apple.com/app-store), ve a la página **Settings > User Management**. Para que Adapty pueda obtener los datos de atribución, debes invitar a otra cuenta de Apple ID y concederle acceso como API Account Manager. Puedes usar cualquier cuenta a la que tengas acceso o crear una nueva específicamente para este fin. Lo importante es que debes poder iniciar sesión en Apple Ads con ese Apple ID.
#### Paso 4: Generar las credenciales de API \{#step-4-generate-api-credentials\}
A continuación, inicia sesión en Apple Ads con la cuenta recién añadida. Ve a Settings -> API en la interfaz de Apple Ads. Pega la clave pública que copiaste anteriormente en el campo correspondiente. Genera nuevas credenciales de API.
#### Paso 5: Configurar Adapty con las credenciales de Apple Ads \{#step-5-configure-adapty-with-apple-ads-credentials\}
Copia los campos Client ID, Team ID y Key ID de los ajustes de Apple Ads. En el Adapty Dashboard, pega estas credenciales en los campos correspondientes.
### Conectar tu app a la red AdServices \{#connect-your-app-to-the-adservices-network\}
Una vez que completes [la configuración del framework AdServices](#connect-the-adservices-framework), Adapty empieza a recopilar automáticamente los datos de atribución de Apple Search Ads. No necesitas añadir ningún código al SDK.
En aplicaciones iOS, estos datos de atribución **siempre** tendrán prioridad sobre los datos de otras fuentes. Si este comportamiento no es el deseado, *desactiva* la atribución de ASA siguiendo las instrucciones a continuación.
## Desactivar la integración \{#disable-integration\}
Para desactivar la atribución de Apple Search Ads, abre la pestaña [**App Settings** -> **Apple Search Ads**](https://app.adapty.io/settings/apple-search-ads) y desactiva el interruptor **Receive Apple Search Ads attribution**.
:::warning
Ten en cuenta que desactivar esto detendrá completamente la recepción de análisis de ASA. Como resultado, ASA dejará de usarse en los análisis y no se enviará a las integraciones. Además, SplitMetrics Acquire y Asapty dejarán de funcionar, ya que dependen de la atribución de ASA para operar correctamente.
La atribución recibida antes de este cambio no se verá afectada.
:::
## Subir tus propias claves \{#uploading-your-own-keys\}
:::note
Opcional
Estos pasos no son necesarios para la atribución de Apple Ads, solo para trabajar con otros servicios como Asapty o tu propia solución.
:::
Puedes usar tu propio par de claves pública-privada si estás utilizando otros servicios o una solución propia para la atribución de ASA.
### Paso 1 \{#step-1\}
Genera la clave privada en el Terminal
```text showLineNumbers title="Text"
openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem
```
Súbela en Adapty Settings -> Apple Ads (botón Upload private key)
### Paso 2 \{#step-2\}
Genera la clave pública en el Terminal
```text showLineNumbers title="Text"
openssl ec -in private-key.pem -pubout -out public-key.pem
```
Puedes usar esta clave pública en los ajustes de Apple Ads de la cuenta con el rol API Account Manager. Así podrás usar los valores generados de Client ID, Team ID y Key ID tanto en Adapty como en otros servicios.
---
# File: switch-from-appsflyer-s2s-api-2-to-3
---
---
title: "Cambiar de AppsFlyer S2S API 2 a 3"
description: "Actualiza de AppsFlyer S2S API 2 a 3 en Adapty."
---
Según las [novedades oficiales de AppsFlyer](https://support.appsflyer.com/hc/en-us/articles/20509378973457-Bulletin-Upgrading-the-AppsFlyer-S2S-API), para ofrecer un uso más seguro de la API y reducir el fraude, AppsFlyer ha actualizado su API servidor a servidor (S2S) para eventos in-app. El endpoint actual quedará obsoleto en el futuro, por lo que recomendamos empezar a planificar la migración.
Adapty es compatible con AppsFlyer S2S API 3 y te permite realizar el cambio desde API 2 sin complicaciones. Ten en cuenta que este cambio es unidireccional, por lo que no podrás volver a API 2 una vez realizado.
Para cambiar de AppsFlyer S2S API 2 a 3:
1. Abre el [sitio de AppsFlyer](https://www.appsflyer.com/home) e inicia sesión.
2. Haz clic en **Tu nombre de cuenta** -> **Security Center** en la esquina superior izquierda del dashboard.
3. En la ventana **Manage your account security**, haz clic en el botón **Manage your AppsFlyer API and S2S tokens**.
4. Si no tienes un token S2S, haz clic en el botón **New token**. Si ya lo tienes, continúa con el paso 8.
5. En la ventana **New token**, introduce el nombre del token. Este nombre es solo para tu referencia.
6. Selecciona **S2S** en la lista **Choose type**.
7. No olvides hacer clic en el botón **Create new token** para guardar el nuevo token.
8. En la ventana **Tokens**, copia el token S2S.
9. Abre [**Integrations** -> **AppsFlyer**](https://app.adapty.io/integrations/appsflyer) en el Adapty Dashboard.
10. En el campo **AppsFlyer S2S API**, selecciona **API 3**.
11. Pega la clave S2S copiada en los campos **Dev key for iOS** y **Dev key for Android**.
12. Haz clic en el botón **Save** para confirmar el cambio.
En ese momento, tu integración cambia instantáneamente a AppsFlyer S2S API 3 y los nuevos eventos se enviarán a la nueva URL: `https://api3.appsflyer.com/inappevent`.
---
# File: asapty
---
---
title: "Asapty"
description: "Descubre Asapty y su papel en el ecosistema de suscripciones de Adapty."
---
Con la integración de [Asapty](https://asapty.com/) puedes optimizar tus campañas de Search Ads. Adapty envía eventos de suscripción a Asapty para que puedas crear dashboards personalizados basados en la atribución de Apple Search Ads.
Esta integración en concreto no añade ningún dato de atribución a Adapty, ya que obtenemos todo lo necesario directamente desde [ASA](apple-search-ads).
## Configurar la integración \{#set-up-integration\}
### Conectar Adapty con Asapty \{#connect-adapty-to-asapty\}
Para integrar Asapty, ve a [Integrations > Asapty](https://app.adapty.io/integrations/asapty) en el Adapty Dashboard y rellena el campo con tu Asapty ID.
El Asapty ID se encuentra en la sección Settings > General de tu cuenta de Asapty.
### Configurar eventos y etiquetas \{#configure-events-and-tags\}
Justo debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar a Asapty desde Adapty. Activa únicamente los que necesites. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Recomendamos usar los nombres de evento predeterminados que proporciona Asapty, aunque puedes cambiarlos según tus necesidades.
### Conectar tu app con Asapty \{#connect-your-app-to-asapty\}
Una vez completados los pasos anteriores, Adapty recibe automáticamente los datos de atribución de Asapty. No es necesario solicitar explícitamente esos datos en el código de tu aplicación. Para mejorar la precisión de la atribución, configura Asapty para que incluya el `customerUserId` en los datos de cada evento.
## Estructura de eventos de Asapty \{#asapty-event-structure\}
Adapty envía eventos a Asapty mediante una petición GET con parámetros de consulta. Cada URL de evento tiene este aspecto:
```
https://asapty.com/_api/mmpEvents/?source=adapty&asaptyid=a1b2c3d4&keywordid=12345&adgroupid=67890&campaignid=11223&conversiondate=1709294400000&event_name=subscription_renewed&install_time=1709100000&app_name=MyApp&json=%7B%22af_revenue%22%3A%229.99%22%2C%22af_currency%22%3A%22USD%22...%7D
```
Parámetros de consulta:
| Parámetro | Tipo | Descripción |
|:-----------------|:-------|:------------------------------------------------------------------|
| `source` | String | Siempre "adapty". |
| `asaptyid` | String | El Asapty ID de tus credenciales. |
| `keywordid` | String | ID de palabra clave de Apple Search Ads (si está disponible). |
| `adgroupid` | String | ID del grupo de anuncios de Apple Search Ads (si está disponible).|
| `campaignid` | String | ID de campaña de Apple Search Ads (si está disponible). |
| `conversiondate` | Long | Marca de tiempo del evento en **milisegundos**. |
| `event_name` | String | Nombre del evento (mapeado desde el evento de Adapty). |
| `install_time` | Long | Marca de tiempo de la instalación en segundos. |
| `app_name` | String | Título de la app en Adapty (si está disponible). |
| `json` | String | Cadena JSON codificada en URL con los detalles del evento (ver más abajo). |
El parámetro `json` es una cadena JSON codificada en URL que contiene los siguientes campos:
| Parámetro | Tipo | Descripción |
|:--------------------------|:-------|:---------------------------------------------------|
| `af_revenue` | String | Importe de ingresos como cadena de texto. |
| `af_currency` | String | Código de moneda (p. ej., "USD"). |
| `transaction_id` | String | ID de transacción del store. |
| `original_transaction_id` | String | ID de transacción original del store. |
| `purchase_date` | Long | Marca de tiempo de la compra en milisegundos. |
| `original_purchase_date` | Long | Marca de tiempo de la compra original en milisegundos. |
| `environment` | String | `Production` o `Sandbox`. |
| `vendor_product_id` | String | ID del producto en el store. |
| `profile_country` | String | Código de país basado en la IP del usuario. |
| `store_country` | String | Código de país del store del usuario. |
## Solución de problemas \{#troubleshooting\}
- Asegúrate de haber configurado [Apple Search Ads](apple-search-ads) en Adapty y de haber [subido las credenciales](https://app.adapty.io/settings/apple-search-ads); sin ellas, Asapty no funcionará.
- Solo los perfiles con atribución de ASA detallada y no orgánica enviarán sus eventos a Asapty. Verás el mensaje "The user profile is missing the required integration data." si la atribución no es suficiente.
- Los perfiles creados antes de configurar las integraciones no podrán enviar sus eventos a Asapty.
- Si la integración con Adapty no funciona a pesar de estar correctamente configurada, comprueba que el toggle **Receive Apple Search Ads attribution in Adapty** esté activado en la pestaña [**App Settings** -> **Apple Search Ads**](https://app.adapty.io/settings/apple-search-ads).
---
# File: branch
---
---
title: "Branch"
description: "Integra Branch con Adapty para rastrear deep links y conversiones de la app."
---
[Branch](https://www.branch.io/) permite a los clientes llegar, interactuar y evaluar resultados en distintos dispositivos, canales y plataformas. Es una plataforma fácil de usar diseñada para aumentar los ingresos móviles mediante enlaces especializados que funcionan perfectamente en todos los dispositivos, canales y plataformas.
Adapty ofrece un conjunto completo de datos que te permite rastrear los [eventos de suscripción](events) de los stores en un solo lugar. Con Adapty, puedes ver fácilmente el comportamiento de tus suscriptores, conocer sus preferencias y usar esa información para comunicarte con ellos de forma dirigida y efectiva.
La integración entre Adapty y Branch funciona de dos maneras principales.
1. **Recibir datos de atribución de Branch**
Una vez que hayas configurado la integración con Branch, Adapty comenzará a recibir datos de atribución de Branch. Puedes acceder y ver estos datos fácilmente en la página de perfil del usuario.
2. **Enviar eventos de suscripción a Branch**
Adapty puede enviar todos los eventos de suscripción configurados en tu integración a Branch. Como resultado, podrás rastrear esos eventos dentro del dashboard de Branch.
## Configurar la integración \{#set-up-integration\}
### Conectar Adapty con Branch \{#connect-adapty-to-branch\}
Para integrar Branch, ve a [Integrations > Branch](https://app.adapty.io/integrations/branch) en el Adapty Dashboard, activa el interruptor y rellena los campos.
Para obtener el valor del campo **Branch Key**, abre tu [Account Settings](https://dashboard.branch.io/account-settings/profile) de Branch y localiza el campo **Branch Key**. Úsalo para el campo **Key test** (para Sandbox) o **Key live** (para Producción) en el Adapty Dashboard. En Branch, cambia entre los entornos Live y Tests para obtener la clave correspondiente.
### Configurar eventos y etiquetas \{#configure-events-and-tags\}
Debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar a Branch desde Adapty. Activa únicamente los que necesites. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Puedes enviar un evento con los ingresos netos \(después del recorte de Apple/Google\) o solo los ingresos brutos. También puedes marcar la casilla para reportar en la moneda del usuario.
Te recomendamos usar los nombres de evento predeterminados que proporciona Adapty. Sin embargo, puedes cambiarlos según tus necesidades.
Adapty enviará los eventos de suscripción a Branch mediante una integración servidor a servidor, lo que te permitirá ver todos los eventos de suscripción en tu dashboard de Branch y vincularlos a tus campañas de adquisición.
### Conectar tu app con Branch \{#connect-your-app-to-branch\}
1. Llama al método `.setIntegrationIdentifier()` del SDK para inicializar la conexión. Puedes pasar tu Branch Identity ID al parámetro `customerUserId`.
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
1. Para encontrar el App ID, abre la página de tu app en [App Store Connect](https://appstoreconnect.apple.com/), ve a la página **App Information** en la sección **General** y busca el **Apple ID** en la parte inferior izquierda de la pantalla.
2. Necesitas una aplicación en la plataforma [Meta for Developers](https://developers.facebook.com/). Inicia sesión en tu app y accede a la configuración avanzada. Encontrarás el **App ID** en la cabecera.
3. Desactiva el seguimiento del lado del cliente en la configuración de tu Meta SDK para evitar el doble conteo de ingresos en Meta Ads Manager. Puedes encontrar este ajuste en tu Meta Developer Console en **App Settings > Advanced Settings**. Establece **Log in-app events automatically** en "No". Esto garantizará que los eventos de ingresos solo se registren a través de la integración de Adapty.
Para rastrear eventos de instalación y uso, deberás activar el Meta SDK en tu código. Puedes encontrar los detalles de implementación en la documentación del Meta SDK para tu plataforma:
- [iOS SDK](https://developers.facebook.com/docs/ios/getting-started)
- [Android SDK](https://developers.facebook.com/docs/android/getting-started)
- [Unity SDK](https://developers.facebook.com/docs/unity/getting-started/canvas)
También puedes usar esta integración con apps Android. Si configuras la configuración del Android SDK en **App Settings**, con introducir el **Facebook App ID** es suficiente.
### Configurar eventos y etiquetas \{#configure-events-and-tags\}
Ten en cuenta que la integración de Facebook Ads está orientada específicamente a empresas que utilizan Meta para sus campañas publicitarias y las optimizan en función del comportamiento de los clientes. Es compatible con los eventos estándar de Meta para fines de optimización. Por ello, no es posible modificar el nombre del evento en la integración de Meta Ads. Adapty mapea automáticamente los eventos de tus clientes a sus correspondientes eventos de Meta para un análisis preciso.
| Evento de Adapty | Evento de Meta Ads |
| :---------------------------- | :-------------------------- |
| Subscription initial purchase | Subscribe |
| Subscription renewed | Subscribe |
| Subscription cancelled | CancelSubscription |
| Trial started | StartTrial |
| Trial converted | Subscribe |
| Trial cancelled | CancelTrial |
| Non subscription purchase | fb_mobile_purchase |
| Billing issue detected | billing_issue_detected |
| Entered grace period | entered_grace_period |
| Auto renew off | auto_renew_off |
| Auto renew on | auto_renew_on |
| Auto renew off subscription | auto_renew_off_subscription |
| Auto renew on subscription | auto_renew_on_subscription |
StartTrial, Subscribe y CancelSubscription son eventos estándar.
Para activar eventos específicos, simplemente activa los que necesites. Si se seleccionan varios nombres de eventos, Adapty consolidará los datos de todos los eventos seleccionados en un único nombre de evento de Adapty.
### Conectar tu app con Facebook Ads \{#connect-your-app-to-facebook-ads\}
Si sigues los pasos anteriores, Facebook recibirá automáticamente los datos de suscripción desde Adapty.
Tras los cambios en el IDFA en iOS 14.5, recomendamos que solicites el `facebookAnonymousId` del usuario a Facebook. De este modo, si el IDFA del usuario no está disponible, la integración seguirá funcionando. Sigue la
Debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar a Singular desde Adapty. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Te recomendamos usar los nombres de evento predeterminados que proporciona Adapty, aunque puedes modificarlos según tus necesidades.
Adapty enviará los eventos de suscripción a Singular mediante una integración server-to-server, lo que te permitirá ver todos los eventos de suscripción en tu dashboard de Singular y vincularlos con tus campañas de adquisición.
:::warning
Los perfiles creados antes de configurar las integraciones no podrán enviar sus eventos a Singular.
:::
### Conectar tu app con Singular \{#connect-your-app-to-singular\}
La integración entre Adapty y Singular es server-to-server, por lo que no necesitas añadir ningún código adicional en tu aplicación.
## Estructura del evento \{#event-structure\}
Adapty envía eventos a Singular mediante una solicitud GET con parámetros de consulta. Cada evento tiene esta estructura:
```json
{
"n": "subscription_renewed",
"a": "singular_sdk_key_123",
"p": "iOS",
"i": "com.example.app",
"ip": "192.168.100.1",
"idfa": "00000000-0000-0000-0000-000000000000",
"idfv": "00000000-0000-0000-0000-000000000000",
"ve": "17.0.1",
"att_authorization_status": 3,
"custom_user_id": "user_12345",
"utime": 1709294400,
"amt": 9.99,
"cur": "USD",
"purchase_product_id": "yearly.premium.6999",
"purchase_transaction_id": "GPA.3383...",
"e": "{\"is_revenue_event\":true,\"amt\":9.99,\"cur\":\"USD\",\"purchase_product_id\":\"yearly.premium.6999\",\"purchase_transaction_id\":\"GPA.3383...\"}"
}
```
Donde:
| Parámetro | Tipo | Descripción |
|:---------------------------|:--------|:---------------------------------------------------------------|
| `n` | String | El nombre del evento (mapeado desde el evento de Adapty). |
| `a` | String | Tu Singular SDK Key. |
| `p` | String | Plataforma ("iOS" o "Android"). |
| `i` | String | ID de la app en el store (Bundle ID). |
| `ip` | String | Dirección IP del usuario. |
| `idfa` | String | **Solo iOS**. ID for Advertisers (en mayúsculas). |
| `idfv` | String | **Solo iOS**. ID for Vendors (en mayúsculas). |
| `aifa` | String | **Solo Android**. Google Advertising ID (en minúsculas). |
| `andi` | String | **Solo Android**. Android ID (en minúsculas). |
| `asid` | String | **Solo Android**. App Set ID (en minúsculas). |
| `ve` | String | Versión del sistema operativo. |
| `att_authorization_status` | Integer | **Solo iOS**. Estado ATT (p. ej., `3` para autorizado). |
| `custom_user_id` | String | El Customer User ID del usuario. |
| `utime` | Long | Marca de tiempo UNIX del evento en segundos. |
| `amt` | Float | Importe de los ingresos. |
| `cur` | String | Código de moneda (p. ej., "USD"). |
| `purchase_product_id` | String | El ID del producto en el store. |
| `purchase_transaction_id` | String | ID de transacción original. |
| `e` | String | Cadena JSON con los detalles del evento (ver más abajo). |
El parámetro `e` (datos de evento personalizados) es una cadena codificada en JSON que contiene:
| Parámetro | Tipo | Descripción |
|:--------------------------|:--------|:-----------------------------------------------|
| `is_revenue_event` | Boolean | `true` si el evento incluye ingresos. |
| `amt` | Float | Importe de los ingresos. |
| `cur` | String | Código de moneda. |
| `purchase_product_id` | String | El ID del producto en el store. |
| `purchase_transaction_id` | String | ID de transacción original. |
---
# File: tenjin
---
---
title: "Integración con Tenjin"
description: ""
---
Tenjin es una plataforma de atribución y analítica móvil para desarrolladores de apps y profesionales del marketing. Proporciona herramientas para medir y optimizar campañas de adquisición de usuarios, ofreciendo información detallada sobre el rendimiento de la app y el comportamiento de los usuarios. Con su enfoque transparente y flexible, Tenjin agrega datos de redes publicitarias y stores de apps, lo que permite a los equipos analizar el ROI, rastrear conversiones y monitorear métricas clave de rendimiento.
Al reenviar [eventos de suscripción](events) a Tenjin, puedes ver exactamente de dónde provienen las conversiones y qué campañas generan más valor en todos los canales, plataformas y dispositivos. En esencia, los dashboards de Tenjin ofrecen analítica avanzada para campañas de marketing.
Al reenviar la atribución de Tenjin a Adapty, enriqueces la analítica de Adapty con criterios de filtrado adicionales que puedes usar en el análisis de cohortes y conversiones.
Esta integración funciona de dos maneras principales:
1. **Recibir datos de atribución de Tenjin**
Una vez integrado, Adapty recopila datos de atribución de Tenjin. Puedes acceder a esta información en la página del perfil del usuario en el Adapty Dashboard.
2. **Enviar eventos de suscripción a Tenjin**
Adapty envía eventos de compra a Tenjin en tiempo real. Estos eventos ayudan a evaluar la efectividad de tus campañas publicitarias directamente en el dashboard de Tenjin.
| Característica de integración | Descripción |
| ----------------------------- | ------------------------------------------------------------ |
| Frecuencia | Tiempo real |
| Dirección de datos | Transmisión bidireccional:
3. Inicia sesión en el [Tenjin Dashboard](https://tenjin.com/).
4. Ve a **Configuration** -> **Apps** en el menú de navegación.
5. Selecciona la app para tu plataforma (iOS o Android) y navega a la pestaña **App and SDK**.
6. En la pestaña **App and SDK**, haz clic en **Copy** en la columna **SDK Key**. Si aún no tienes una SDK Key, haz clic en el botón **Generate SDK Key** para crear una.
7. Vuelve al Adapty Dashboard y pega la SDK Key copiada en el campo de la plataforma correspondiente:
- Para apps iOS: pégala en el campo **iOS SDK Key** o **iOS Sandbox SDK Key**
- Para apps Android: pégala en el campo **Android SDK Key** o **Android Sandbox SDK Key**
:::info
Tenjin no tiene un modo Sandbox específico para la integración server-to-server. Usa una app de Tenjin separada o la misma clave tanto para eventos de producción como de sandbox.
:::
8. Si tienes apps en ambas plataformas, repite los pasos 5-7 para la otra plataforma.
9. (opcional) Ajusta la sección **How the revenue data should be sent** si es necesario. Para una explicación detallada de sus configuraciones, consulta la sección [Integration settings](configuration#integration-settings).
10. Haz clic en **Save** para finalizar la configuración.
Adapty comenzará a enviar eventos de compra a Tenjin y a recibir datos de atribución. Puedes ajustar el intercambio de eventos en la sección **Events names**.
### Configurar eventos y etiquetas \{#configure-events-and-tags\}
Tenjin solo acepta eventos de compra y **Trial started**. En la sección **Events names**, selecciona qué eventos compartir con Tenjin según tus objetivos de seguimiento.
### Conectar tu app con Tenjin \{#connect-your-app-to-tenjin\}
Usa el método del SDK `Adapty.updateAttribution()` para obtener los datos de atribución de Tenjin y enviarlos a Adapty.
2. Activa **Amplitude integration** para habilitarla.
3. Rellena los campos de la integración:
| Campo | Descripción |
| ------------------------------------------ | ------------------------------------------------------------ |
| **Amplitude iOS/ Android/ Stripe API key** | Introduce la **API Key** de Amplitude para iOS/ Android/ Stripe en Adapty. Encuéntrala en **Project settings** dentro de Amplitude. Para más ayuda, consulta la [documentación de Amplitude](https://amplitude.com/docs/apis/authentication). Comienza con las claves de **Sandbox** para pruebas y luego cambia a las claves de **Production** tras pruebas exitosas. |
4. Ajustes opcionales para mayor personalización:
| Parámetro | Descripción |
| --------------------------------------- | ------------------------------------------------------------ |
| **How the revenue data should be sent** | Elige si enviar los ingresos brutos o los ingresos después de impuestos y comisiones. Consulta [Comisión del store e impuestos](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) para más detalles. |
| **Exclude historical events** | Elige excluir los eventos anteriores a la instalación del SDK de Adapty para evitar datos duplicados. Por ejemplo, si un usuario se suscribió el 10 de enero pero instaló el SDK de Adapty el 6 de marzo, Adapty solo enviará eventos a partir del 6 de marzo. |
| **Send User Attributes** | Selecciona esta opción para enviar atributos específicos del usuario, como preferencias de idioma. |
| **Always populate user_id** | Adapty envía automáticamente `device_id` como `amplitudeDeviceId`. Para `user_id`, esta configuración define el comportamiento:
Recomendamos usar los nombres de eventos predeterminados que proporciona Adapty. No obstante, puedes cambiarlos según tus necesidades. Adapty enviará los eventos de suscripción a Amplitude mediante una integración servidor a servidor, lo que te permitirá ver todos los eventos de suscripción en tu dashboard de Amplitude.
### Configuración del SDK \{#sdk-configuration\}
Usa el método `setIntegrationIdentifier()` para establecer el parámetro `amplitude_device_id`. Es imprescindible configurarlo para que la integración funcione.
Si tienes registro de usuarios, también puedes pasar `amplitude_user_id`.
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
4. Ve a [Integrations > AppMetrica](https://app.adapty.io/integrations/appmetrica) en el Adapty Dashboard
5. Pega tus credenciales de AppMetrica.
### Eventos y etiquetas \{#events-and-tags\}
Adapty te permite enviar tres grupos de eventos a AppMetrica. Puedes habilitar los eventos que necesitas para rastrear el rendimiento de tu app. Para ver la lista completa de eventos disponibles, consulta nuestra [documentación de eventos](events).
:::note
AppMetrica sincroniza los eventos cada 4 horas, por lo que puede haber un retraso antes de que los eventos aparezcan en tu dashboard.
:::
:::tip
Recomendamos usar los nombres de eventos predeterminados de Adapty para mantener la coherencia, aunque puedes personalizarlos para que coincidan con tu configuración de análisis existente.
:::
### Configuración de ingresos \{#revenue-settings\}
De forma predeterminada, Adapty envía los datos de ingresos como propiedades en los eventos, que aparecen en el informe de Events de AppMetrica. Puedes configurar cómo se calculan y muestran estos datos:
- **Revenue calculation**: Elige cómo se calculan los valores de ingresos para que coincidan con tus necesidades de informes financieros:
- **Gross revenue**: Muestra los ingresos totales antes de cualquier deducción, útil para rastrear el importe completo que pagan los clientes
- **Proceeds after store commission**: Muestra los ingresos después de deducir las comisiones de App Store/Play Store, lo que te ayuda a rastrear los ingresos reales
- **Proceeds after store commission and taxes**: Muestra los ingresos netos después de las comisiones del store y los impuestos aplicables, lo que ofrece la imagen más precisa de tus ganancias
- **Report user's currency**: Cuando está habilitado, las ventas se informan en la moneda local del usuario, lo que facilita el análisis de ingresos por región. Cuando está deshabilitado, todas las ventas se convierten a USD para mantener informes coherentes en diferentes mercados.
- **Send revenue events**: Habilita esta opción para que los datos de ingresos aparezcan no solo en el informe de Events, sino también en el informe [In-app and ad revenue](https://appmetrica.yandex.com/docs/en/mobile-reports/revenue-report) de AppMetrica. Asegúrate de no enviar ingresos desde ningún otro lugar, ya que esto podría generar duplicados.
- **Exclude historical events**: Cuando está habilitado, Adapty no enviará eventos que ocurrieron antes de que el usuario instalara la app con el SDK de Adapty. Esto ayuda a evitar la duplicación de datos si ya estabas enviando eventos a analytics antes de integrar Adapty.
### Configuración del SDK \{#sdk-configuration\}
Para habilitar la integración con AppMetrica en tu app, necesitas configurar dos identificadores:
1. `appmetrica_device_id`: Necesario para la integración básica
2. `appmetrica_profile_id`: Opcional, pero recomendado si tu app tiene registro de usuarios
Usa el método `setIntegrationIdentifier()` para establecer estos valores. A continuación se muestra cómo implementarlo en cada plataforma:
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
### 2\. Integra con Adapty \{#2-integrate-with-adapty\}
A continuación, Adapty necesita tu Firebase App ID y el API Secret de Google Analytics para enviar eventos y propiedades de usuario. Puedes encontrar estos parámetros en la Firebase Console y en la pestaña Data Streams de Google Analytics, respectivamente.
A continuación, accede a la página de detalles del Stream de la app dentro de la sección Data Streams de la configuración de administrador en [Google Analytics](https://analytics.google.com/analytics/web/#/).
En **Additional settings**, ve a la página **Measurement Protocol API secrets** y crea un nuevo **API Secret** si no existe. Copia el valor.
El siguiente paso será ajustar la integración en el Adapty Dashboard. Deberás proporcionarnos el Firebase App ID y el API Secret de Google Analytics para tus plataformas iOS, Android y/o Stripe.
:::note
Si usas la integración con Stripe, ten en cuenta sus limitaciones en la [guía](stripe#current-limitations) correspondiente. Estas limitaciones también se aplicarán a la integración con Firebase.
:::
## Configuración del SDK \{#sdk-configuration\}
:::important
Para que la integración funcione, asegúrate de añadir Firebase a tu app primero:
- [iOS](https://firebase.google.com/docs/ios/setup)
- [Android](https://firebase.google.com/docs/android/setup)
- [React Native](https://firebase.google.com/docs/web/setup)
- [Flutter](https://firebase.google.com/docs/flutter/setup)
- [Unity](https://firebase.google.com/docs/unity/setup)
:::
A continuación, debes configurar el SDK de Adapty para asociar a tus usuarios con Firebase. Para cada usuario, debes enviar el `firebase_app_instance_id` a Adapty. A continuación puedes ver un ejemplo del código que se puede usar para integrar el SDK de Firebase y el SDK de Adapty.
Verás que algunos eventos tienen nombres específicos, como "Purchase", mientras que otros son eventos habituales de Adapty. Esta diferencia se debe a los [tipos de eventos de Google Analytics](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events). Actualmente, los eventos compatibles son [Refund](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#refund) y [Purchase](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#purchase). El resto son eventos personalizados. Por lo tanto, asegúrate de que los nombres de tus eventos sean [compatibles](https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=firebase#limitations) con Google Analytics.
También puedes configurar el envío de propiedades de usuario desde el Adapty Dashboard.
Esto significa que Adapty enriquecerá tus eventos con `subscription_state` y `subscription_product_id`. Sin embargo, también debes [habilitar](https://support.google.com/analytics/answer/14240153?hl=en) esta función en Google Analytics. Para usar **User properties** en tus análisis, empieza por asignarlas a una dimensión personalizada en la Firebase Console, a través de **Custom Definitions**, seleccionando el ámbito **User**, y asignándoles un nombre y una descripción.
Asegúrate de que los nombres de tus propiedades de usuario sean `subscription_state` y `subscription_product_id`. De lo contrario, no podremos enviarte los datos del estado de la suscripción.
¡Y eso es todo! Espera a recibir nuevos insights de Google.
## Solución de problemas \{#troubleshooting\}
### Discrepancia de datos \{#data-discrepancy\}
Si existe una discrepancia de datos entre Adapty y Firebase, puede deberse a que no todos tus usuarios utilizan la versión de la app que incluye el SDK de Adapty. Para garantizar la consistencia de los datos, puedes obligar a tus usuarios a actualizar la app a una versión que incluya el SDK de Adapty.
Además, los eventos de sandbox se envían a Firebase por defecto y esto no se puede deshabilitar. Por eso, en situaciones en las que una app tiene pocos eventos de producción y muchos de sandbox, puede haber una discrepancia notable entre los datos de Analytics de Adapty y los de Firebase.
### Los eventos aparecen como entregados en Adapty pero no están disponibles en Firebase \{#events-are-shown-as-delivered-in-adapty-but-not-available-in-firebase\}
Existe un retraso entre el momento en que Adapty envía los eventos y el momento en que aparecen en el dashboard de Google Analytics. Se recomienda consultar el Realtime Dashboard de tu cuenta de Google Analytics para ver los eventos más recientes en tiempo real.
---
# File: mixpanel
---
---
title: "Mixpanel"
description: "Conecta Mixpanel con Adapty para potentes analíticas de suscripciones."
---
[Mixpanel](https://mixpanel.com/home/) es un potente servicio de analítica de producto. Su solución de seguimiento basada en eventos permite a los equipos de producto obtener información valiosa sobre las mejores estrategias de adquisición, conversión y retención de usuarios en distintas plataformas.
Esta integración te permite llevar todos los eventos de Adapty a Mixpanel. Como resultado, obtendrás una visión más completa de tu negocio de suscripciones y las acciones de tus clientes. Adapty proporciona un conjunto completo de datos que te permite hacer seguimiento de los [eventos de suscripción](events) desde los stores en un solo lugar. Con Adapty, puedes ver fácilmente cómo se comportan tus suscriptores, entender qué les gusta y usar esa información para comunicarte con ellos de forma dirigida y eficaz.
## Cómo configurar la integración con Mixpanel \{#how-to-set-up-mixpanel-integration\}
1. Abre la página [Integrations -> Mixpanel](https://app.adapty.io/integrations/mixpanel) en el Adapty Dashboard.
2. Activa el interruptor e introduce tu **Mixpanel Token**. Puedes especificar un token para todas las plataformas o limitarlo a plataformas concretas si solo quieres recibir datos de algunas de ellas.
### Cómo encontrar tu Mixpanel Token \{#finding-your-mixpanel-token\}
Para obtener tu **Mixpanel Token**:
1. Inicia sesión en tu [Mixpanel Dashboard](https://mixpanel.com/settings/project/).
2. Abre **Settings** y selecciona **Organization Settings**.
3. En la barra lateral izquierda, ve a **Projects** y selecciona tu proyecto.
## Cómo funciona la integración \{#how-the-integration-works\}
Adapty mapea automáticamente las propiedades de evento relevantes —como el ID de usuario y los ingresos— a las [propiedades nativas de Mixpanel](https://docs.mixpanel.com/docs/data-structure/user-profiles). Esto garantiza un seguimiento e informes precisos de los eventos relacionados con suscripciones.
Además, Adapty acumula datos de ingresos por usuario y actualiza sus [Propiedades de Perfil de Usuario](https://docs.mixpanel.com/docs/data-structure/user-profiles), incluidas `subscription state` y `subscription product ID`. Una vez recibido un evento, Mixpanel actualiza los campos correspondientes en tiempo real.
## Eventos y etiquetas \{#events-and-tags\}
Debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar a Mixpanel desde Adapty. Activa simplemente los que necesites. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Recomendamos usar los nombres de evento predeterminados que proporciona Adapty. Aun así, puedes cambiarlos según tus necesidades.
## Configuración del SDK \{#sdk-configuration\}
Usa el método `.setIntegrationIdentifier()` para establecer `mixpanelUserId`. Si no se establece, Adapty usa tu ID de usuario (`customerUserId`) o, si es nulo, el ID de Adapty. Asegúrate de que el ID de usuario que utilizas para enviar datos a Mixpanel desde tu app sea el mismo que envías a Adapty.
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
2. Inicia sesión en el [PostHog Dashboard](https://posthog.com/).
3. Ve a **Settings -> Project**.
4. En la ventana **Project**, desplázate hacia abajo hasta la sección **Project ID** y copia la **Project API key**.
5. Pega la API key en el campo **Project API key** del Adapty Dashboard. PostHog no tiene un modo Sandbox específico para la integración servidor a servidor.
6. Elige tu **PostHog Deployment**:
| Opción | Descripción |
| ------ | ----------- |
| us/eu | Despliegues de PostHog alojados por defecto. |
| Custom | Para instancias autoalojadas. Introduce la URL de tu instancia en el campo **PostHog Instance URL**. |
7. (Opcional) Si usas un despliegue de PostHog autoalojado, introduce la dirección de tu despliegue en el campo **PostHog Instance URL**.
8. (opcional) Ajusta opciones como **Reporting Proceeds**, **Exclude Historical Events**, **Report User's Currency** y **Send Trial Price**. Consulta [Configuración de la integración](configuration#integration-settings) para más detalles sobre estas opciones.
9. (opcional) También puedes personalizar qué eventos se envían a PostHog en la sección **Events names**. Desactiva los eventos que no necesites o cámbiales el nombre según convenga.
10. Haz clic en **Save** para finalizar la configuración.
## Configuración del SDK \{#sdk-configuration\}
Para habilitar la recepción de datos de atribución desde PostHog, pasa el valor `distinctId` a Adapty tal como se muestra a continuación:
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
Abre tu cuenta de SplitMetrics Acquire, pasa el cursor sobre uno de los logotipos de MMP y haz clic en el botón **Settings**. Busca tu Client ID en el cuadro de diálogo bajo el elemento **5**, cópialo y pégalo en Adapty como **Client ID**.
También deberás configurar el Apple App ID para usar la integración. Para encontrar tu App ID, abre la página de tu app en App Store Connect, ve a la página **App Information** en la sección **General** y busca el **Apple ID** en la parte inferior izquierda de la pantalla.
## Eventos y etiquetas \{#events-and-tags\}
Debajo de las credenciales, hay tres grupos de eventos que puedes enviar a SplitMetrics Acquire desde Adapty. Simplemente activa los que necesites. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Recomendamos usar los nombres de evento predeterminados que ofrece Adapty. Sin embargo, puedes cambiarlos según tus necesidades. Adapty enviará los eventos de suscripción a SplitMetrics Acquire mediante una integración server-to-server, lo que te permitirá ver todos los eventos de suscripción en tu dashboard de SplitMetrics.
## Configuración del SDK \{#sdk-configuration\}
No necesitas configurar nada en el lado del SDK, pero recomendamos enviar el `customerUserId` a Adapty para mayor precisión.
:::warning
Asegúrate de haber configurado [Apple Search Ads](apple-search-ads) en Adapty y de haber [subido las credenciales](https://app.adapty.io/settings/apple-search-ads); sin ellas, SplitMetrics Acquire no funcionará.
:::
## Solución de problemas \{#troubleshooting\}
Si la integración con SplitMetrics Acquire no funciona a pesar de haberla configurado correctamente:
- Asegúrate de que el toggle **Receive Apple Search Ads attribution in Adapty** esté activado en [App Settings -> Apple Search Ads tab](https://app.adapty.io/settings/apple-search-ads), de haber configurado [Apple Search Ads](apple-search-ads) en Adapty y de haber [subido las credenciales](https://app.adapty.io/settings/apple-search-ads); sin ellas, SplitMetrics no funcionará.
- Comprueba que los perfiles tengan atribución ASA no orgánica. Solo los perfiles con atribución ASA detallada y no orgánica enviarán sus eventos a Adapty.
## Estructura de eventos de SplitMetrics Acquire \{#splitmetrics-acquire-event-structure\}
Adapty envía eventos a SplitMetrics Acquire mediante una solicitud GET utilizando parámetros de consulta. Cada evento tiene esta estructura:
```json
{
"source": "Apple Search Ads",
"app_id": "123456789",
"name": "subscription_renewed",
"type": "subscription_renewed",
"revenue": 9.99,
"currency": "USD",
"tap_time": "2024-03-01 12:00:00",
"open_time": "2024-03-01 12:05:00",
"event_time": "2024-03-02 12:00:00",
"adaccount_id": "123456",
"campaign_id": "123456789",
"adgroup_id": "123456789",
"keyword_id": "123456789",
"creative_set_id": "123456789",
"Ad_id": "123456789",
"country_or_region": "US",
"conversion_type": "Download",
"user_id": "user_12345",
"att_status": "3",
"device_type": "iphone",
"app_version": "1.2.3",
"sdk_version": "2.10.0",
"ios_version": "17.2",
"event_value": "{\"vendor_product_id\":\"yearly.premium.6999\",\"original_transaction_id\":\"GPA.3383...\"}",
"event_id": "123e4567-e89b-12d3-a456-426614174000"
}
```
It looks like your message got cut off — there's no MDX documentation included to translate.
Could you paste the MDX content you'd like translated from English to Spanish (es-ES)? Once you share it, I'll get started right away.
| Parámetro | Tipo | Descripción |
|:--------------------|:-------|:---------------------------------------------------------------------------------------------------------------------|
| `source` | String | Siempre "Apple Search Ads". |
| `app_id` | String | ID de la app en Apple. |
| `name` | String | Nombre del evento (mapeado desde el evento de Adapty). |
| `type` | String | Tipo de evento (igual que `name`). |
| `revenue` | Float | Importe de los ingresos. |
| `currency` | String | Código de moneda. |
| `tap_time` | String | Fecha y hora del toque en el anuncio. |
| `open_time` | String | Fecha y hora de la apertura de la app (instalación). |
| `event_time` | String | Fecha y hora del evento. |
| `adaccount_id` | String | ID de organización de ASA. |
| `campaign_id` | String | ID de campaña de ASA. |
| `adgroup_id` | String | ID de grupo de anuncios de ASA. |
| `keyword_id` | String | ID de palabra clave de ASA. |
| `creative_set_id` | String | ID del conjunto creativo de ASA. |
| `Ad_id` | String | ID de anuncio de ASA. |
| `country_or_region` | String | País o región del store. |
| `conversion_type` | String | Tipo de conversión (p. ej., "Download"). |
| `user_id` | String | Customer User ID o ID de perfil de Adapty. |
| `att_status` | String | Estado de uso del seguimiento (0-3). |
| `device_type` | String | Tipo de dispositivo (p. ej., "iphone", "ipad"). |
| `app_version` | String | Versión de la aplicación. |
| `sdk_version` | String | Versión del SDK de Adapty. |
| `ios_version` | String | Versión de iOS. |
| `event_value` | String | Cadena JSON con todos los [detalles del evento](webhook-event-types-and-fields#for-most-event-types) disponibles. |
| `event_id` | String | ID único del evento (UUID). |
---
# File: braze
---
---
title: "Braze"
description: "Integra Braze con Adapty para una mejor interacción con clientes y notificaciones push."
---
Como una de las principales soluciones de captación de clientes, [Braze](https://www.braze.com/) ofrece una amplia gama de herramientas para notificaciones push, email, SMS y mensajería in-app. Al integrar Adapty con Braze, puedes acceder fácilmente a todos tus eventos de suscripción en un solo lugar, lo que te permite activar comunicaciones automatizadas basadas en esos eventos.
Adapty proporciona un conjunto completo de datos que te permite rastrear [eventos de suscripción](events) de todas las stores en un solo lugar y puede usarse para actualizar los perfiles de tus usuarios en Braze. Con Adapty, puedes ver fácilmente el comportamiento de tus suscriptores, conocer sus preferencias y utilizar esa información para comunicarte con ellos de forma dirigida y efectiva. Por tanto, esta integración te permite rastrear eventos de suscripción en tu dashboard de Braze y relacionarlos con tus [campañas de adquisición.](https://www.braze.com/product/journey-orchestration)
Adapty envía eventos de suscripción, propiedades de usuario y compras a Braze, para que puedas crear comunicaciones dirigidas a clientes mediante notificaciones push de Braze tras una integración sencilla y rápida, tal como se describe a continuación.
## Cómo configurar la integración con Braze \{#how-to-set-up-braze-integration\}
Para integrar Braze, ve a [Integrations -> Braze](https://app.adapty.io/integrations/braze), activa el interruptor y rellena los campos.
El primer paso del proceso de integración es proporcionar las credenciales necesarias para establecer una conexión entre tus perfiles de Braze y Adapty. Necesitarás la **REST API Key**, tu **Braze Instance ID** y los **App IDs** para iOS y Android para que la integración funcione correctamente:
1. La **REST API Key** se puede crear en **Braze Dashboard** → **Settings** → **API Keys**. Asegúrate de que tu clave tenga el permiso `users.track` al crearla:
2. Para obtener el **Braze Instance ID**, fíjate en la URL de tu Braze Dashboard y accede a la sección de [Braze Docs](https://www.braze.com/docs/api/basics/#endpoints) donde se especifica el ID de instancia. Tendrá un formato regional como US-03, EU-01, etc.
3. Los App IDs de iOS y Android también se encuentran en Braze Dashboard → Settings → API Keys. Cópialos desde aquí:
## Eventos, atributos de usuario y compras \{#events-user-attributes-and-purchases\}
Justo debajo de las credenciales hay tres grupos de eventos que puedes enviar a Braze desde Adapty. Activa simplemente los que necesites. También puedes cambiar los nombres de los eventos según lo que necesites enviar a Braze. Consulta la lista completa de eventos que ofrece Adapty [aquí](events):
Adapty enviará eventos de suscripción y atributos de usuario a Braze mediante una integración servidor a servidor, lo que te permitirá verlos en tu Braze Dashboard y configurar campañas basándote en ellos.
Para los eventos que generan ingresos, como las conversiones de prueba y las renovaciones, Adapty enviará esta información a Braze como compras.
[Aquí](messaging#event-properties) encontrarás las especificaciones completas de las propiedades de los eventos que se envían a Braze.
:::note
Atributos de usuario útiles
Adapty envía algunos atributos de usuario para la integración con Braze de forma predeterminada. Puedes consultar la lista que se muestra a continuación para determinar cuáles se adaptan mejor a tus necesidades.
:::
| Atributo de usuario | Tipo | Valor |
|--------------|----|-----|
| `adapty_customer_user_id` | String | Contiene el valor del identificador único del usuario definido por el cliente. Se puede encontrar tanto en el [Dashboard](profiles-crm) de Adapty como en Braze. |
| `adapty_profile_id` | String | Contiene el valor del identificador único del Perfil de Usuario de Adapty, que se puede encontrar en el [Dashboard](profiles-crm) de Adapty. |
| `environment` | String | Indica si el usuario opera en un entorno sandbox o de producción.
Los valores son `Sandbox` o `Production`
| | `store` | String |Contiene el nombre de la Store utilizada para realizar la compra.
Valores posibles:
`app_store` o `play_store`.
| | `vendor_product_id` | String |Contiene el valor del ID de producto en la store de Apple/Google.
p. ej., org.locals.12345
| | `subscription_expires_at` | String |Contiene la fecha de vencimiento de la suscripción más reciente.
El formato del valor es:
YYYY-MM-DDTHH:mm:ss.SSS+TZ
p. ej., 2023-02-15T17:22:03.000+0000
| | `active_subscription` | String | El valor se establecerá en `true` en cualquier evento de compra o renovación, o en `false` si la suscripción ha expirado. | | `period_type` | String |Indica el tipo de período más reciente para la compra o renovación.
Los valores posibles son
`trial` para un período de prueba o `normal` para el resto.
| Todos los valores float se redondearán a int. Los strings permanecen igual. Además de la lista predefinida de etiquetas disponibles, es posible enviar [atributos personalizados](segments#custom-attributes) mediante etiquetas. Esto permite mayor flexibilidad en el tipo de datos que se pueden incluir con la etiqueta y puede resultar útil para rastrear información específica relacionada con un producto o servicio. Todos los atributos de usuario personalizados se envían automáticamente a Braze si el usuario marca la casilla **Send user attributes** en [la página de integración](https://app.adapty.io/integrations/braze). ## Configuración del SDK \{#sdk-configuration\} Para vincular perfiles de usuario en Adapty y Braze, debes configurar el SDK de Braze con el mismo ID de usuario que Adapty o usar su método `.changeUser()`:
2. Activa el interruptor de la integración.
3. Introduce tu **OneSignal App ID**.
Para configurar la integración con OneSignal, ve a [Integrations -> OneSignal](https://app.adapty.io/integrations/onesignal) en tu Adapty dashboard, activa el interruptor y configura las credenciales de la integración.
## Obtener tu OneSignal App ID \{#retrieving-your-onesignal-app-id\}
Encuentra tu **OneSignal App ID** en tu [OneSignal Dashboard](https://dashboard.onesignal.com/login):
1. Ve a **Settings** → **Keys & IDs**.
2. Copia tu **OneSignal App ID** y pégalo en el campo **App ID** del Adapty Dashboard.
Puedes encontrar más información sobre el ID de OneSignal en la [siguiente documentación.](https://documentation.onesignal.com/docs/en/keys-and-ids)
### Configurar eventos \{#configuring-events\}
Adapty te permite enviar tres grupos de eventos a OneSignal. Activa los que necesites en el Adapty Dashboard. Puedes ver la lista completa de eventos disponibles con una descripción detallada [aquí](events).
Adapty envía eventos de suscripción a OneSignal mediante una integración servidor a servidor, lo que te permite hacer seguimiento de toda la actividad relacionada con suscripciones en OneSignal.
:::warning
A partir del 17 de abril de 2023, el Plan Gratuito de OneSignal ya no incluye esta integración. Solo está disponible en los planes **Growth**, **Professional** y superiores. Para más información, consulta [OneSignal Pricing](https://onesignal.com/pricing).
:::
## Etiquetas personalizadas \{#custom-tags\}
Esta integración actualiza y asigna diversas propiedades a tus usuarios de Adapty como etiquetas, que luego se envían a OneSignal. Consulta la lista de etiquetas a continuación para encontrar las que mejor se adapten a tus necesidades.
:::warning
OneSignal tiene un límite de etiquetas. Esto incluye tanto las etiquetas generadas por Adapty como las ya existentes en OneSignal. Superar el límite puede provocar errores al enviar eventos.
:::
| Etiqueta | Tipo | Descripción |
|---|----|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `adapty_customer_user_id` | String | El identificador único del usuario en tu app. Debe ser coherente en tu sistema, Adapty y OneSignal. |
| `adapty_profile_id` | String | El ID de perfil del usuario en Adapty, disponible en tu [Adapty Dashboard](profiles-crm). |
| `environment` | String | `Sandbox` o `Production`, que indica el entorno actual del usuario. |
| `store` | String | Store donde se compró el producto. Opciones: **app_store**, **play_store**, **stripe** o el nombre de tu [store personalizado](custom-store). |
| `vendor_product_id` | String | El ID del producto en el store (p. ej., `org.locals.12345`). |
| `subscription_expires_at` | String | Fecha de expiración de la suscripción más reciente (`YYYY-MM-DDTHH:MM:SS+0000`, p. ej., `2023-02-10T17:22:03.000000+0000`). |
| `last_event_type` | String | El tipo de evento más reciente de la [lista de eventos de Adapty](events).
1. El **App ID** se encuentra en tu dashboard de Pushwoosh.
2. El **Auth token** se encuentra en la sección API Access dentro de la configuración de Pushwoosh.
## Eventos y etiquetas \{#events-and-tags\}
Debajo de las credenciales encontrarás tres grupos de eventos que puedes enviar a Pushwoosh desde Adapty. Activa simplemente los que necesites. También puedes cambiar los nombres de los eventos antes de enviarlos a Pushwoosh. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
Adapty enviará los eventos de suscripción a Pushwoosh mediante una integración server-to-server, lo que te permitirá ver todos los eventos de suscripción en tu Pushwoosh Dashboard.
:::note
Etiquetas personalizadas
Con Adapty también puedes usar tus propias etiquetas personalizadas para la integración con Pushwoosh. Consulta la lista de etiquetas que se muestra a continuación para determinar cuál se adapta mejor a tus necesidades.
:::
| Etiqueta | Tipo | Valor |
|---|----|-----|
| `adapty_customer_user_id` | String | Contiene el valor del identificador único del usuario, que puede encontrarse en el lado de Pushwoosh. |
| `adapty_profile_id` | String | Contiene el valor del identificador único del perfil de usuario de Adapty, que puede encontrarse en tu [dashboard](profiles-crm) de Adapty. |
| `environment` | String | Indica si el usuario opera en un entorno sandbox o de producción.
Los valores son `Sandbox` o `Production`.
| | `store` | String |Contiene el nombre del store utilizado para realizar la compra.
Valores posibles:
`app_store` o `play_store`.
| | `vendor_product_id` | String |Contiene el valor del Product ID en la store de Apple o Google.
p. ej., org.locals.12345
| | `subscription_expires_at` | String |Contiene la fecha de expiración de la última suscripción.
El formato del valor es:
año-mes díaTHhora:minuto:segundo
p. ej., 2023-02-10T17:22:03.000000+0000
| | `last_event_type` | String | Indica el tipo del último evento recibido de la lista de [eventos estándar de Adapty](events) que has habilitado para la integración. | | `purchase_date` | String |Contiene la fecha de la última transacción (compra original o renovación).
El formato del valor es:
año-mes díaTHhora:minuto:segundo
p. ej., 2023-02-10T17:22:03.000000+0000
| | `original_purchase_date` | String |Contiene la fecha de la primera compra según la transacción.
El formato del valor es:
año-mes díaTHhora:minuto:segundo
p. ej., 2023-02-10T17:22:03.000000+0000
| | `active_subscription` | String | El valor se establecerá en `true` ante cualquier evento de compra o renovación, o en `false` si la suscripción ha expirado. | | `period_type` | String |Indica el tipo de período más reciente para la compra o renovación.
Los valores posibles son
`trial` para un período de prueba o `normal` para el resto.
| Todos los valores float se redondearán a int. Las cadenas de texto permanecen igual. Además de la lista predefinida de etiquetas disponibles, es posible enviar [atributos personalizados](segments#custom-attributes) mediante etiquetas. Esto ofrece mayor flexibilidad en el tipo de datos que se pueden incluir y resulta útil para rastrear información específica relacionada con un producto o servicio. Todos los atributos personalizados de usuario se envían automáticamente a Pushwoosh si el usuario marca la casilla **Send user custom attributes** en [la página de integración](https://app.adapty.io/integrations/pushwoosh). ## Configuración del SDK \{#sdk-configuration\} Para vincular Adapty con Pushwoosh, necesitas enviarnos el valor `HWID`:
2. Dale cualquier nombre (`Adapty`, por ejemplo) y agrégala a tu workspace:
### 2\. Dar permiso para publicar y obtener un token para tu app \{#2-give-permission-to-post-and-get-a-token-for-your-app\}
Serás redirigido a la página de tu app en Slack.
1. Desplázate hacia abajo y haz clic en **Permissions**:
2. Tras la redirección, desplázate hacia abajo hasta **Scopes** y haz clic en **Add an OAuth Scope**:
3. Otorga los permisos `chat:write`, `chat:write.public` y `chat:write.customize`. Estos son necesarios para publicar en tus canales y personalizar los mensajes:
4. Desplázate de nuevo hasta la parte superior de la página y haz clic en **Install to Workspace**:
5. Haz clic en **Allow**:
Después de esto, serás redirigido a la misma página, pero ahora tendrás disponible un OAuth Token (`xoxb-...`). Esto es exactamente lo que necesitas para completar la configuración:
### 3\. Configurar la integración en Adapty \{#3-configure-the-integration-in-adapty\}
1. Ve a [**Integrations** → **Slack**](https://app.adapty.io/integrations/slack):
2. Pega el token `xoxb-...` del paso anterior y elige en qué canales publicará la app. Puedes configurar la integración para recibir eventos solo en producción, en sandbox o en ambos. También puedes elegir en qué moneda se mostrarán los mensajes (la original o convertida a USD).
:::note
Ten en cuenta que si quieres publicar mensajes de Adapty en un canal privado, deberás añadir manualmente la app `Adapty` que creaste en Slack a ese canal. De lo contrario, no funcionará.
:::
3. Por último, puedes elegir qué eventos quieres recibir en **Events**:
¡Listo!
Los eventos se enviarán a los canales que hayas especificado. Podrás ver los ingresos cuando corresponda y consultar el perfil del cliente en Adapty:
---
# File: s3-exports
---
---
title: "Amazon S3"
description: "Exporta datos de suscripción a S3 para análisis e informes avanzados."
---
La integración de Adapty con Amazon S3 te permite almacenar de forma segura los datos de eventos y visitas a paywalls en un único lugar centralizado. Podrás guardar tus [eventos de suscripción](events) en tu bucket de Amazon S3 como archivos .csv.
Para configurar esta integración, solo tienes que seguir unos sencillos pasos en la consola de AWS y en el Adapty Dashboard.
:::note
Programación
Adapty envía tus datos cada **24h** a las 4:00 UTC.
Cada archivo contendrá datos de los eventos creados durante el día natural anterior completo en UTC. Por ejemplo, los datos exportados automáticamente a las 4:00 UTC del 8 de marzo contendrán todos los eventos creados el 7 de marzo entre las 00:00:00 y las 23:59:59 UTC.
:::
## Cómo configurar la integración con Amazon S3 \{#how-to-set-up-amazon-s3-integration\}
Para empezar a recibir datos, necesitarás las siguientes credenciales:
1. Access key ID
2. Secret access key
3. S3 bucket name
4. Folder name inside the S3 bucket
:::note
Directorios anidados
Puedes especificar directorios anidados en el campo S3 bucket name, por ejemplo: adapty-events/com.sample-app
:::
Para integrar Amazon S3, ve a [**Integrations** -> **Amazon S3**](https://app.adapty.io/integrations/s3), activa el interruptor y rellena los campos.
En primer lugar, introduce las credenciales para establecer la conexión entre Amazon S3 y los perfiles de Adapty.
En el Adapty Dashboard, los siguientes campos son necesarios para configurar la conexión:
| Campo | Descripción |
| :--- | :--- |
| **Access Key ID** | Identificador único que se usa para autenticar el acceso de un usuario o aplicación a un servicio de AWS. Encuéntralo en el [archivo csv](s3-exports#how-to-create-amazon-s3-credentials) descargado. |
| **Secret Access Key** | Clave privada que se usa junto con el Access Key ID para autenticar el acceso de un usuario o aplicación a un servicio de AWS. Encuéntrala en el [archivo csv](s3-exports#how-to-create-amazon-s3-credentials) descargado. |
| **S3 Bucket Name** | Nombre único a nivel global que identifica un bucket de S3 específico dentro de la nube de AWS. Los buckets de S3 son un servicio de almacenamiento simple que permite a los usuarios guardar y recuperar objetos de datos, como archivos e imágenes, en la nube. |
| **Folder Inside the Bucker** | El nombre de la carpeta que quieres crear dentro del bucket de S3 seleccionado. Ten en cuenta que S3 simula carpetas mediante prefijos de clave de objeto, que son esencialmente nombres de carpetas. |
## Cómo crear credenciales de Amazon S3 \{#how-to-create-amazon-s3-credentials\}
Esta guía te ayudará a crear las credenciales necesarias en tu consola de AWS.
### 1\. Crear política de acceso \{#create-access-policy\}
Primero, ve al [Panel de políticas de IAM](https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/policies) en tu consola de AWS y selecciona la opción **Create Policy**.
En el editor de políticas, pega el siguiente JSON y cambia `adapty-s3-integration-test` por el nombre de tu bucket:
```json showLineNumbers title="Json"
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowListObjectsInBucket",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::adapty-s3-integration-test"
},
{
"Sid": "AllowAllObjectActions",
"Effect": "Allow",
"Action": "s3:*Object",
"Resource": [
"arn:aws:s3:::adapty-s3-integration-test/*",
"arn:aws:s3:::adapty-s3-integration-test"
]
},
{
"Sid": "AllowBucketLocation",
"Effect": "Allow",
"Action": "s3:GetBucketLocation",
"Resource": "arn:aws:s3:::adapty-s3-integration-test"
}
]
}
```
Una vez completada la configuración de la política, puedes añadir etiquetas (opcional) y hacer clic en **Next** para continuar con el paso final. En este paso, deberás asignar un nombre a tu política y simplemente hacer clic en el botón **Create policy** para finalizar el proceso de creación.
### 2\. Crear un usuario IAM \{#2-create-iam-user\}
Para que Adapty pueda subir informes de datos brutos a tu bucket, deberás proporcionarles el Access Key ID y el Secret Access Key de un usuario con acceso de escritura al bucket específico.
Para ello, ve a la consola de IAM y selecciona la [sección Users](https://console.aws.amazon.com/iamv2/home#/users). Desde allí, haz clic en el botón **Add users**.
Dale un nombre al usuario, elige **Access key – Programmatic access** y continúa con los permisos.
Para el siguiente paso, selecciona la opción **Add user to group** y luego haz clic en el botón **Create group**.
A continuación, asigna un nombre a tu Grupo de Usuarios y selecciona la política que creaste anteriormente. Una vez seleccionada, haz clic en el botón **Create group** para completar el proceso.
Una vez creado el grupo con éxito, **selecciónalo** y continúa con el siguiente paso.
Como este es el último paso de esta sección, puedes continuar haciendo clic en el botón **Create User**.
Por último, puedes **descargar las credenciales en formato .csv** o copiarlas y pegarlas directamente desde el dashboard.
## Exportación manual de datos \{#manual-data-export\}
Además de la exportación automática de datos de eventos a Amazon S3, Adapty también ofrece una funcionalidad de exportación manual de archivos. Con esta función, puedes seleccionar un intervalo de tiempo específico para los datos de eventos y exportarlos a tu bucket de S3 de forma manual. Esto te da mayor control sobre los datos que exportas y cuándo los exportas.
El rango de fechas especificado se usará para exportar los eventos creados desde la Fecha A 00:00:00 UTC hasta la Fecha B 23:59:59 UTC.
## Estructura de la tabla \{#table-structure\}
En la integración con AWS S3, Adapty proporciona una tabla para almacenar datos históricos de eventos de transacciones y visitas a paywalls. La tabla contiene información sobre el perfil del usuario, los ingresos y beneficios, y el store de origen, entre otros datos. En esencia, estas tablas registran todas las transacciones generadas por una app durante un período de tiempo determinado.
:::warning
Ten en cuenta que esta estructura puede crecer con el tiempo, ya que nosotros o los terceros con los que trabajamos podemos añadir nuevos datos. Asegúrate de que el código que la procesa sea lo suficientemente robusto y se base en campos concretos, no en la estructura en su conjunto.
:::
Aquí está la estructura de la tabla para los eventos:
| Columna | Descripción |
|---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **profile_id** | ID de usuario de Adapty. |
| **event_type** | Nombre del evento en minúsculas. Consulta la sección [Eventos](events) para conocer los tipos de eventos. |
| **event_datetime** | Fecha en formato ISO 8601. |
| **transaction_id** | Identificador único de una transacción, como una compra o renovación. |
| **original_transaction_id** | Identificador de la transacción de compra original. |
| **subscription_expires_at** | Fecha de vencimiento de la suscripción. Normalmente en el futuro. |
| **environment** | Puede ser Sandbox o Production. |
| **revenue_usd** | Ingresos en USD. Puede estar vacío. |
| **proceeds_usd** | Ingresos netos en USD. Puede estar vacío. |
| **net_revenue_usd** | Ingresos netos (tras impuestos) en USD. Puede estar vacío. |
| **tax_amount_usd** | Importe deducido en concepto de impuestos en USD. Puede estar vacío. |
| **revenue_local** | Ingresos en moneda local. Puede estar vacío. |
| **proceeds_local** | Ingresos netos en moneda local. Puede estar vacío. |
| **net_revenue_local** | Ingresos netos (tras impuestos) en moneda local. Puede estar vacío. |
| **tax_amount_local** | Importe deducido en concepto de impuestos en moneda local. Puede estar vacío. |
| **customer_user_id** | ID de usuario del desarrollador. Por ejemplo, puede ser tu UUID de usuario, email u otro identificador. Null si no lo has configurado. |
| **store** | Puede ser _app_store_ o _play_store_. |
| **product_id** | ID del producto en Apple App Store, Google Play Store o Stripe. |
| **base_plan_id** | [ID del plan base](https://support.google.com/googleplay/android-developer/answer/12154973) en Google Play Store o [ID de precio](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices) en Stripe. |
| **developer_id** | ID del desarrollador (SDK) del paywall donde se originó la transacción. |
| **ab_test_name** | Nombre de la prueba A/B donde se originó la transacción. |
| **ab_test_revision** | Revisión de la prueba A/B donde se originó la transacción. |
| **paywall_name** | Nombre del paywall donde se originó la transacción. |
| **paywall_revision** | Revisión del paywall donde se originó la transacción. |
| **profile_county** | País del perfil determinado por Adapty a partir de la IP. |
| **install_date** | Fecha de instalación en formato ISO 8601. |
| **idfv** | [identifierForVendor](https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor) en dispositivos iOS |
| **idfa** | [advertisingIdentifier](https://developer.apple.com/documentation/adsupport/asidentifiermanager/advertisingidentifier) en dispositivos iOS |
| **advertising_id** | El Advertising ID es un código único asignado por el sistema operativo Android que los anunciantes pueden usar para identificar de forma única el dispositivo de un usuario. |
| **ip_address** | IP del dispositivo (puede ser IPv4 o IPv6, con preferencia por IPv4 cuando esté disponible). Se actualiza cada vez que cambia la IP del dispositivo. |
| **cancellation_reason** | Motivo por el que el usuario canceló una suscripción.
Puede ser:
**iOS & Android** _voluntarily_cancelled_, _billing_error_, _refund_
**iOS** _price_increase_, _product_was_not_available_, _unknown_, _upgraded_
**Android** _new_subscription_replace_, _cancelled_by_developer_
| | **android_app_set_id** | Un [AppSetId](https://developer.android.com/design-for-safety/privacy-sandbox/reference/adservices/appsetid/AppSetId): ID único por dispositivo y por cuenta de desarrollador, restablecible por el usuario, para casos de uso publicitario sin monetización. | | **android_id** | En Android 8.0 (nivel de API 26) y versiones superiores, un número de 64 bits (expresado como cadena hexadecimal), único para cada combinación de clave de firma de la app, usuario y dispositivo. Para más detalles, consulta la [documentación para desarrolladores de Android](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID). | | **device** | Nombre del modelo de dispositivo visible para el usuario final. | | **currency** | Código de moneda de 3 letras (ISO-4217) de la transacción. | | **store_country** | País del perfil determinado por la store de Apple/Google. | | **attribution_source** | Fuente de atribución. | | **attribution_network_user_id** | ID asignado al usuario por la fuente de atribución. | | **attribution_status** | Puede ser organic, non_organic o unknown. | | **attribution_channel** | Nombre del canal de marketing. | | **attribution_campaign** | Nombre de la campaña de marketing. | | **attribution_ad_group** | Grupo de anuncios de atribución. | | **attribution_ad_set** | Conjunto de anuncios de atribución. | | **attribution_creative** | Palabra clave creativa de atribución. | | **attributes** | JSON de [atributos de usuario personalizados](setting-user-attributes#custom-user-attributes). Incluye los atributos personalizados que hayas configurado para enviar desde tu app móvil. Para enviarlo, activa la opción **Send User Attributes** en la página [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook). | | **integration_ids** | Todos los IDs de integración asociados a un perfil. Diccionario. Ejemplo: {'mixpanel_user_id': 'mixpanelUserId-test', 'facebook_anonymous_id': 'facebookAnonymousId-test'} | Here is the table structure for the paywall visits: | Columna | Descripción | | :-------------------- | :------------------------------------------------------------------------------------------------------------------ | | **profile_id** | ID de usuario de Adapty. | | **customer_user_id** | ID de usuario del desarrollador. Por ejemplo, puede ser tu UUID de usuario, email o cualquier otro ID. Null si no lo configuraste. | | **profile_country** | País del perfil determinado por la store de Apple/Google. | | **install_date** | Fecha ISO 8601 en que se produjo la instalación. | | **store** | Puede ser _app_store_ o _play_store_. | | **paywall_showed_at** | La fecha en que el paywall se mostró al cliente. | | **developer_id** | ID de desarrollador (SDK) del paywall donde se originó la transacción. | | **ab_test_name** | Nombre de la prueba A/B donde se originó la transacción. | | **ab_test_revision** | Revisión de la prueba A/B donde se originó la transacción. | | **paywall_name** | Nombre del paywall donde se originó la transacción. | | **paywall_revision** | Revisión del paywall donde se originó la transacción. | ## Eventos y etiquetas \{#events-and-tags\} Puedes gestionar qué datos comunica la integración. La integración ofrece las siguientes opciones de configuración: | Parámetro | Descripción | | :--------------------------------- | :----------------------------------------------------------- | | **Exclude Historical Events** | Elige excluir los eventos que ocurrieron antes de que el usuario instalara la app con el SDK de Adapty. Esto evita la duplicación de eventos y garantiza informes precisos. Por ejemplo, si un usuario activó una suscripción mensual el 10 de enero y actualizó la app con el SDK de Adapty el 6 de marzo, Adapty omitirá los eventos anteriores al 6 de marzo y conservará los posteriores. | | **Include events without profile** | Elige incluir las transacciones que no están vinculadas a un perfil de usuario en Adapty. Esto puede incluir compras realizadas antes de instalar el SDK de Adapty o transacciones recibidas desde las notificaciones del servidor del store que no pueden asociarse inmediatamente a un usuario concreto. | | **Send User Attributes** | Si deseas enviar atributos específicos del usuario, como preferencias de idioma, y tu plan de OneSignal admite más de 10 etiquetas, selecciona esta opción. Al activarla, se permite incluir información adicional más allá de las 10 etiquetas predeterminadas. Ten en cuenta que superar los límites de etiquetas puede provocar errores. |
Debajo de los ajustes de integración, hay tres grupos de eventos que puedes exportar, enviar y almacenar en Amazon S3 desde Adapty. Activa los que necesites. Consulta la lista completa de eventos que ofrece Adapty [aquí](events).
---
# File: google-cloud-storage
---
---
title: "Google Cloud Storage"
description: "Integra Google Cloud Storage con Adapty para almacenar datos de forma segura."
---
Activa la integración con Google Cloud Storage para almacenar de forma segura los [eventos de suscripción](events) y los [datos de visitas a paywalls](paywall-metrics) en un único lugar: tu bucket de Google Cloud Storage.
Cada día a las 4 AM UTC, Adapty subirá archivos .csv con los datos del día anterior a tus buckets. Puedes elegir si quieres recibir datos de **eventos**, datos de **visitas a paywalls**, o **ambos**. También puedes exportar estos datos [manualmente](#manual-data-export) en cualquier momento y para cualquier período de tiempo.
Para configurar la integración, [genera una clave de acceso al bucket](#create-google-cloud-storage-credentials) en tu consola de Google Cloud y [añádela en los ajustes de Adapty](#set-up-google-cloud-storage-integration).
## Programación y duración de las subidas \{#upload-schedule-and-duration\}
Adapty sube datos a Google Cloud Storage cada 24 horas, a las 04:00 UTC.
Los archivos contienen datos de los eventos creados durante el día natural anterior (UTC). El archivo subido el 8 de marzo incluirá todos los eventos creados el 7 de marzo, de 00:00:00 a 23:59:59 UTC.
El proceso puede tardar varias horas, dependiendo del número total de archivos en cola y del volumen de datos que hayas solicitado. Si Adapty incluye datos históricos en tu primera subida, tardará más que las subidas diarias posteriores.
## Configurar la integración con Google Cloud Storage \{#set-up-google-cloud-storage-integration\}
Necesitas una clave de cuenta de servicio de Google Cloud válida con **acceso de escritura**. Para generarla, sigue los pasos de la sección [crear credenciales](#create-google-cloud-storage-credentials).
:::warning
Puedes usar distintos buckets con diferentes credenciales para eventos y visitas a paywalls. Sin embargo, si **cualquiera** de las credenciales es inválida, [**ambas subidas fallarán**](#troubleshooting).
:::
Ve a [**Integrations** -> **Google Cloud Storage**](https://app.adapty.io/integrations/google-cloud-storage) y abre la pestaña correspondiente (**Events** o **Paywall visits**). Activa la integración.
Sube el archivo con tu **clave de cuenta de servicio de Google Cloud**. Especifica el **bucket** y la **carpeta** de destino. Guarda los cambios.
### Configuración opcional para datos de eventos \{#optional-settings-for-event-data\}
Puedes especificar qué eventos incluir en el informe y definir nombres personalizados para ellos. Consulta el artículo de [eventos](events) para ver la lista completa de eventos disponibles.
| Nombre | Valor predeterminado | Descripción |
| ------------------------------ | ----------------- | ----------- |
| Exclude historical events | true | Excluye información sobre eventos ocurridos antes de integrar el SDK de Adapty en tu app. Un usuario compró una suscripción mensual el 10 de enero. La actualización del 1 de marzo de tu aplicación fue la primera en incluir el SDK de Adapty.
Si este ajuste está **activado**, el informe no incluirá el evento "subscription started" de enero ni el evento "subscription renewed" de febrero. **Sí** incluirá el evento "subscription renewed" del 10 de marzo.
El motivo por el que el usuario canceló una suscripción.
Valores posibles:
**iOS y Android** — *voluntarily_cancelled*, *billing_error*, *refund*
**Solo iOS** — *price_increase*, *product_was_not_available*, *unknown*, *upgraded*
**Solo Android** — *new_subscription_replace*, *cancelled_by_developer*
| | **android_app_set_id** | Un [AppSetId](https://developer.android.com/design-for-safety/privacy-sandbox/reference/adservices/appsetid/AppSetId): ID único por dispositivo y cuenta de desarrollador, restablecible por el usuario, para casos de uso publicitario sin monetización. | | **android_id** | En Android 8.0 (nivel de API 26) y versiones superiores, un número de 64 bits (expresado como cadena hexadecimal), único para cada combinación de clave de firma de app, usuario y dispositivo. Para más detalles, consulta la [documentación para desarrolladores de Android](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID). | | **device** | Nombre del modelo de dispositivo visible para el usuario final. | | **currency** | Código de divisa de 3 letras (ISO-4217) de la transacción. | | **store_country** | País del perfil determinado por Apple/Google store. | | **attribution_source** | Fuente de atribución. | | **attribution_network_user_id** | ID asignado al usuario por la fuente de atribución. | | **attribution_status** | Puede ser organic, non_organic o unknown. | | **attribution_channel** | Nombre del canal de marketing. | | **attribution_campaign** | Nombre de la campaña de marketing. | | **attribution_ad_group** | Grupo de anuncios de atribución. | | **attribution_ad_set** | Conjunto de anuncios de atribución. | | **attribution_creative** | Palabra clave creativa de atribución. | | **attributes** | JSON con los [atributos personalizados del usuario](setting-user-attributes#custom-user-attributes). Incluirá todos los atributos personalizados que hayas configurado para enviar desde tu app móvil. Para enviarlo, activa la opción **Send User Attributes** en la página [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook). | | **integration_ids** | Todos los IDs de integración asociados a un perfil. Diccionario. Ejemplo: {'mixpanel_user_id': 'mixpanelUserId-test', 'facebook_anonymous_id': 'facebookAnonymousId-test'} | ### Visitas a paywalls \{#paywall-visits\} | Columna | Descripción | | :-------------------- | :----------------------------------------------------------------------------------------------------------- | | **profile_id** | ID de usuario de Adapty. | | **customer_user_id** | ID de usuario del desarrollador. Por ejemplo, puede ser tu UUID de usuario, email u otro identificador. Nulo si no lo has definido. | | **profile_country** | País del perfil determinado por Apple/Google store. | | **install_date** | Fecha en formato ISO 8601 de cuando ocurrió la instalación. | | **store** | Puede ser *app_store* o *play_store*. | | **paywall_showed_at** | La fecha en que se mostró el paywall al cliente. | | **developer_id** | ID de desarrollador (SDK) del paywall donde se originó la transacción. | | **ab_test_name** | Nombre de la prueba A/B donde se originó la transacción. | | **ab_test_revision** | Revisión de la prueba A/B donde se originó la transacción. | | **paywall_name** | Nombre del paywall donde se originó la transacción. | | **paywall_revision** | Revisión del paywall donde se originó la transacción. | ## Solución de problemas \{#troubleshooting\} Adapty comprueba la validez de tus claves de acceso **antes** de comenzar la subida. Aunque solo una de tus claves de Google Cloud Storage sea inválida, Adapty **cancela la subida** y genera un error. Para garantizar subidas ininterrumpidas, reemplaza tus claves antes de que expiren. Si actualizas la clave de **eventos**, no olvides actualizar también la clave de **visitas a paywalls**, y viceversa. --- # File: webhook-event-types-and-fields --- --- title: "Tipos de eventos y campos de webhook" description: "" --- Adapty envía webhooks en respuesta a eventos de suscripción. Esta sección define los tipos de eventos y los datos que contiene cada webhook. ## Tipos de eventos de webhook \{#webhook-event-types\} Puedes enviar todos los tipos de eventos a tu webhook o elegir solo algunos. Consulta nuestros [Flujos de eventos](event-flows) para saber qué tipo de datos entrantes puedes esperar y cómo estructurar tu lógica de negocio en torno a ellos. Puedes desactivar los tipos de eventos que no necesites al [configurar tu integración con Webhook](set-up-webhook-integration#configure-webhook-integration-in-the-adapty-dashboard). También puedes sustituir los IDs de eventos predeterminados de Adapty por los tuyos propios si es necesario. | Nombre del evento | Descripción | |:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | subscription_started | Se activa cuando un usuario activa una suscripción de pago sin período de prueba, es decir, se le cobra de inmediato. | | subscription_renewed | Ocurre cuando se renueva una suscripción y se cobra al usuario. Este evento comienza a partir de la segunda facturación, tanto en suscripciones con prueba como sin ella. | | subscription_renewal_cancelled | El usuario ha desactivado la renovación automática de la suscripción. El usuario conserva el acceso a las funciones premium hasta el final del período de suscripción pagado. | | subscription_renewal_reactivated | Se activa cuando un usuario reactiva la renovación automática de la suscripción. | | subscription_expired | Se activa cuando una suscripción finaliza por completo tras ser cancelada. Por ejemplo, si un usuario cancela una suscripción el 12 de diciembre pero esta permanece activa hasta el 31 de diciembre, el evento se registra el 31 de diciembre cuando la suscripción expira. | | subscription_paused | Ocurre cuando un usuario activa la [pausa de suscripción](https://developer.android.com/google/play/billing/lifecycle/subscriptions#pause) (solo Android). | | subscription_deferred | Se activa cuando una compra de suscripción se [aplaza](https://adapty.io/glossary/subscription-purchase-deferral/), lo que permite a los usuarios retrasar el pago manteniendo el acceso a las funciones premium. Esta función está disponible a través de la Google Play Developer API y puede usarse para pruebas gratuitas o para ayudar a usuarios con dificultades económicas. | | non_subscription_purchase | Cualquier compra que no sea una suscripción, como el acceso de por vida o productos consumibles como monedas del juego. | | trial_started | Se activa cuando un usuario activa una suscripción de prueba. | | trial_converted | Ocurre cuando finaliza una prueba y se cobra al usuario (primera compra). Por ejemplo, si un usuario tiene una prueba hasta el 14 de enero pero se le cobra el 7 de enero, este evento se registra el 7 de enero. | | trial_renewal_cancelled | El usuario desactivó la renovación automática de la suscripción durante el período de prueba. El usuario conserva el acceso a las funciones premium hasta que finalice la prueba, pero no se le cobrará ni comenzará una suscripción. | | trial_renewal_reactivated | Ocurre cuando un usuario reactiva la renovación automática de la suscripción durante el período de prueba. | | trial_expired | Se activa cuando finaliza una prueba sin convertirse en suscripción. | | entered_grace_period | Ocurre cuando falla un intento de pago y el usuario entra en un período de gracia (si está habilitado). El usuario conserva el acceso premium durante este tiempo. | | billing_issue_detected | Se activa cuando ocurre un problema de facturación durante un intento de cobro (p. ej., saldo insuficiente en la tarjeta). | | subscription_refunded | Se activa cuando se reembolsa una suscripción (p. ej., por parte del soporte de Apple). | | non_subscription_purchase_refunded | Se activa cuando se reembolsa una compra que no es una suscripción. | | access_level_updated | Ocurre cuando se actualiza el nivel de acceso de un usuario. | ## Estructura de eventos del webhook \{#webhook-event-structure\} Adapty te enviará únicamente los eventos que hayas seleccionado en la sección **Events names** de la página [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook). Los eventos de webhook se serializan en JSON. El cuerpo de la solicitud `POST` a tu servidor contendrá el evento serializado con la siguiente estructura. Todos los eventos siguen la misma estructura, pero sus campos varían según el tipo de evento, el store y tu configuración específica. Los atributos de usuario son los [atributos de usuario personalizados](setting-user-attributes#custom-user-attributes) que hayas configurado, por lo que contienen lo que hayas definido. Los campos de datos de atribución son iguales para todos los tipos de eventos; sin embargo, la lista de atribuciones dependerá de las fuentes de atribución que uses en tu app móvil. A continuación encontrarás un ejemplo de evento: ```json title="Json" showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem", "idfv": "00000000-0000-0000-0000-000000000000", "idfa": "00000000-0000-0000-0000-000000000000", "advertising_id": "00000000-0000-0000-0000-000000000000", "profile_install_datetime": "2000-01-31T00:00:00.000000+0000", "user_agent": "ExampleUserAgent/1.0 (Device; OS Version) Browser/Engine", "email": "john.doe@company.com", "event_type": "subscription_started", "event_datetime": "2000-01-31T00:00:00.000000+0000", "event_properties": { "store": "play_store", "currency": "USD", "price_usd": 4.99, "profile_id": "00000000-0000-0000-0000-000000000000", "cohort_name": "All Users", "environment": "Production", "price_local": 4.99, "base_plan_id": "b1", "developer_id": "onboarding_placement", "ab_test_name": "onboarding_ab_test", "ab_test_revision": 1, "paywall_name": "UsedPaywall", "proceeds_usd": 4.2315, "variation_id": "00000000-0000-0000-0000-000000000000", "purchase_date": "2024-11-15T10:45:36.181000+0000", "store_country": "AR", "event_datetime": "2000-01-31T00:00:00.000000+0000", "proceeds_local": 4.2415, "tax_amount_usd": 0, "transaction_id": "0000000000000000", "net_revenue_usd": 4.2415, "profile_country": "AR", "paywall_revision": "1", "profile_event_id": "00000000-0000-0000-0000-000000000000", "tax_amount_local": 0, "net_revenue_local": 4.2415, "vendor_product_id": "onemonth_no_trial", "profile_ip_address": "10.10.1.1", "consecutive_payments": 1, "rate_after_first_year": false, "original_purchase_date": "2000-01-31T00:00:00.000000+0000", "original_transaction_id": "0000000000000000", "subscription_expires_at": "2000-01-31T00:00:00.000000+0000", "profile_has_access_level": true, "profile_total_revenue_usd": 4.99, "promotional_offer_id": null, "store_offer_category": null, "store_offer_discount_type": null }, "event_api_version": 1, "profiles_sharing_access_level": [{"profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem"}], "attributions": { "appsflyer": { "ad_set": "Keywords 1.12", "status": "non_organic", "channel": "Google Ads", "ad_group": null, "campaign": "Social media influencers - Rest of the world", "creative": null, "created_at": "2000-01-31T00:00:00.000000+0000" } }, "user_attributes": {"Favourite_color": "Violet", "Pet_name": "Fluffy"}, "integration_ids": {"firebase_app_instance_id": "val1", "branch_id": "val2", "one_signal_player_id": "val3"}, "play_store_purchase_token": { "product_id": "product_123", "purchase_token": "token_abc_123", "is_subscription": true } } ``` ### Campos del evento \{#event-fields\} Los parámetros del evento son los mismos para todos los tipos de evento. | **Campo** | **Tipo** | **Descripción** | |---|---|---| | **advertising_id** | UUID | ID de publicidad (solo Android). | | **attributions** | JSON | [Datos de atribución](webhook-event-types-and-fields#attributions). Se incluye si **Send Attribution** está habilitado en los [ajustes del Webhook](https://app.adapty.io/integrations/customwebhook). | | **customer_user_id** | String | ID de usuario de tu app (UUID, email u otro ID) si lo configuras en el código de tu app al [identificar usuarios](ios-quickstart-identify). Si no identificas usuarios en el código de la app o este usuario concreto es anónimo (no ha iniciado sesión), este campo es `null`. | | **email** | String | Email del usuario si lo configuras mediante el método [`updateProfile`](setting-user-attributes) en el SDK de Adapty o al crear/actualizar perfiles a través de la API del servidor. Si no pasas el valor `email` al SDK o al método de la API, este campo es `null`. | | **event_api_version** | Integer | Versión de la API de Adapty (actual: `1`). | | **event_datetime** | ISO 8601 | Marca de tiempo del evento en formato [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) (p. ej., `2020-07-10T15:00:00.000000+0000`). | | **event_properties** | JSON | [Propiedades del evento](webhook-event-types-and-fields#event-properties). | | **event_type** | String | Nombre del evento en formato Adapty. Consulta los [tipos de eventos del Webhook](webhook-event-types-and-fields#webhook-event-types) para ver la lista completa. | | **idfa** | UUID | ID de publicidad (solo Apple). **IDFA** en el perfil en el [Adapty Dashboard](https://app.adapty.io/profiles/users). Puede ser `null` si no está disponible por restricciones de seguimiento, modo para niños o ajustes de privacidad. | | **idfv** | UUID | Identificador para proveedores (IDFV), único por desarrollador. **IDFV** en el perfil en el [Adapty Dashboard](https://app.adapty.io/profiles/users). | | **integration_ids** | JSON | IDs de integración del usuario si los configuras mediante el método `setIntegrationIdentifier` en el SDK de Adapty o al crear/actualizar perfiles a través de la API del servidor. `null` si no están disponibles o las integraciones están deshabilitadas. | | **play_store_purchase_token** | JSON | [Token de compra de Play Store](webhook-event-types-and-fields#play-store-purchase-token), incluido si **Send Play Store purchase token** está habilitado en los [ajustes del Webhook](https://app.adapty.io/integrations/customwebhook). | | **profile_id** | UUID | ID de perfil generado automáticamente por Adapty para cada perfil. Un mismo ID de Apple/Google puede asociarse a diferentes IDs de perfil si no identificas usuarios o permites compras antes del inicio de sesión. Más información sobre [cómo funciona Adapty con perfiles padre/heredero](how-profiles-work#parent-and-inheritor-profiles). | | **profile_install_datetime** | ISO 8601 | Marca de tiempo de instalación en formato [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) (p. ej., `2020-07-10T15:00:00.000000+0000`). | | **profiles_sharing_access_level** | JSON | Lista de usuarios que [comparten el nivel de acceso](general#6-sharing-paid-access-between-user-accounts) excluyendo el perfil del usuario actual. Si el uso compartido de niveles de acceso está habilitado para tu app, esta lista incluye otros perfiles que se han usado con el mismo ID de Apple/Google.Aunque los valores de los atributos personalizados en el código de la app móvil pueden definirse como floats o strings, los atributos recibidos a través de la API del servidor o una importación histórica pueden llegar en distintos formatos. En ese caso, los valores booleanos y enteros se convertirán a float.
| ### Atribuciones \{#attributions\} Para enviar los datos de atribución, activa la opción **Send Attribution** en la página [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook). Si has activado el envío de datos de atribución y has configurado las [integraciones de atribución](attribution-integration), los datos que se muestran a continuación se enviarán con el evento para cada fuente. Los mismos datos de atribución se envían a todos los tipos de eventos. ```json title="Json" showLineNumbers { "attributions": { "appsflyer": { "ad_set": "sample_ad_set_123", "status": "non_organic", "channel": "sample_channel", "ad_group": "sample_ad_group_456", "campaign": "sample_ios_campaign", "creative": "sample_creative_789", "created_at": "2000-01-31T00:00:00.000000+0000", "network_user_id": "0000000000000-0000000" } } } ``` | Nombre del campo | Tipo de campo | Descripción | | :------------------ | :------------ | :------------------------------------------------- | | **ad_set** | String | Conjunto de anuncios de atribución. | | **status** | String | Puede ser `organic`, `non_organic,` o `unknown`. | | **channel** | String | Nombre del canal de marketing. | | **ad_group** | String | Grupo de anuncios de atribución. | | **campaign** | String | Nombre de la campaña de marketing. | | **creative** | String | Palabra clave creativa de atribución. | | **created_at** | ISO 8601 date | Fecha y hora de creación del registro de atribución. | | **network_user_id** | String | ID asignado al usuario por la fuente de atribución. | ### IDs de integración \{#integration-ids\} Los siguientes IDs de integración se utilizan actualmente en los eventos: - `adjust_device_id` - `airbridge_device_id` - `amplitude_device_id` - `amplitude_user_id` - `appmetrica_device_id` - `appmetrica_profile_id` - `appsflyer_id` - `branch_id` - `facebook_anonymous_id` - `firebase_app_instance_id` - `mixpanel_user_id` - `pushwoosh_hwid` - `one_signal_player_id` - `one_signal_subscription_id` - `tenjin_analytics_installation_id` - `posthog_distinct_user_id` ### Token de compra de Play Store \{#play-store-purchase-token\} Este campo incluye todos los datos necesarios para revalidar una compra, si fuera necesario. Solo se envía si la opción **Send Play Store purchase token** está habilitada en la [configuración de la integración de Webhook](https://app.adapty.io/integrations/customwebhook). | Campo | Tipo | Descripción | | :------------------ | :------ | :----------------------------------------------------------- | | **product_id** | String | El identificador único del producto (SKU) comprado en Play Store. | | **purchase_token** | String | Token generado por Google Play para identificar de forma única esta transacción de compra. | | **is_subscription** | Boolean | Indica si el producto comprado es una suscripción (`true`) o una compra única (`false`). | ### Propiedades del evento \{#event-properties\} Las propiedades de los eventos pueden variar según el tipo de evento e incluso entre eventos del mismo tipo. Por ejemplo, un evento que proviene de App Store no incluirá propiedades específicas de Android como `base_plan_id`. El evento [Nivel de acceso actualizado](webhook-event-types-and-fields#for-access-level-updated-event) tiene propiedades específicas, por lo que le hemos dedicado una sección aparte. Del mismo modo, hemos separado las [Propiedades adicionales de eventos de impuestos e ingresos](webhook-event-types-and-fields#additional-tax-and-revenue-event-properties), ya que son exclusivas de ciertos tipos de eventos. #### Para la mayoría de los tipos de eventos \{#for-most-event-types\} Las propiedades de los eventos son consistentes en la mayoría de los tipos de eventos (excepto el evento **Access Level Updated**, que se describe en su propia sección). A continuación encontrarás una tabla completa con las propiedades y si pertenecen a eventos específicos. | Campo | Tipo | Descripción | |:------------------------------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **ab_test_name** | String | Nombre de la [prueba A/B de Adapty](ab-tests) donde se originó la transacción. | | **ab_test_revision** | Integer | Revisión de la prueba A/B donde se originó la transacción. | | **base_plan_id** | String | [ID del plan base](https://support.google.com/googleplay/android-developer/answer/12154973) en Google Play Store o [ID de precio](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices) en Stripe. | | **cancellation_reason** | String |Posibles motivos de cancelación: `voluntarily_cancelled`, `billing_error`, `price_increase`, `product_was_not_available`, `refund`, `cancelled_by_developer`, `new_subscription_replace`, `upgraded`, `unknown`, `adapty_revoked`.
Presente en los siguientes tipos de evento:
`subscription_cancelled`, `subscription_refunded` y `trial_cancelled`. | | **cohort_name** | String | Nombre de la [audiencia](audience) que determinó qué paywall se mostró al usuario. | | **consecutive_payments** | Integer | Número de períodos que un usuario lleva suscrito sin interrupciones. Incluye el período actual. | | **currency** | String | Moneda local. | | **developer_id** | String | ID del [placement](placements) donde se originó la transacción. | | **environment** | String | Los valores posibles son `Sandbox` o `Production`. | | **event_datetime** | Fecha ISO 8601 | Fecha y hora del evento. Igual que en el nivel raíz del evento. | | **original_purchase_date** | Fecha ISO 8601 | En suscripciones recurrentes, la compra original es la primera transacción de la cadena; su ID, llamado ID de transacción original, vincula la cadena de renovaciones. Las transacciones posteriores son extensiones de ella. La fecha de compra original es la fecha y hora de esa primera transacción. | | **original_transaction_id** | String |En suscripciones recurrentes, es el ID de transacción original que vincula la cadena de renovaciones. La transacción original es la primera de la cadena; las siguientes son extensiones de ella.
Si no hay extensiones, `original_transaction_id` coincide con store_transaction_id.
| | **paywall_name** | String | Nombre del paywall donde se originó la transacción. | | **paywall_revision** | String | Revisión del paywall donde se originó la transacción. El valor predeterminado es 1. | | **price_local** | Float | Precio del producto antes de la comisión de Apple/Google en moneda local. | | **price_usd** | Float | Precio del producto antes de la comisión de Apple/Google en USD. | | **profile_country** | String | Determinado por Adapty a partir de la IP del perfil. | | **profile_event_id** | UUID | ID de evento único que puede usarse para deduplicación. | | **profile_has_access_level** | Boolean | Valor booleano que indica si el perfil tiene un nivel de acceso activo. | | **profile_id** | UUID | ID de perfil generado por Adapty. Igual que en el nivel raíz del evento. | | **profile_ip_address** | String | IP del perfil (puede ser IPv4 o IPv6; se prefiere IPv4 cuando está disponible). `null` si **Collect users' IP addresses** está desactivado en los [ajustes de la app](https://app.adapty.io/settings/general). | | **profile_total_revenue_usd** | Float | Ingresos totales del perfil con los reembolsos descontados. | | **promotional_offer_id** | String | ID de Adapty de la [oferta promocional](offers) utilizada. Este ID lo defines tú al crear una oferta en el dashboard. | | **purchase_date** | Fecha ISO 8601 | Fecha y hora de la compra del producto. | | **rate_after_first_year** | Boolean | Booleano que indica que la suscripción cumple los requisitos para una comisión reducida (normalmente el 15%) tras un año de renovación continua. Las tasas de comisión varían según la elegibilidad del programa y el país. Consulta [Comisión del store e impuestos](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) para más detalles. | | **store** | String | Store donde se realizó la compra. Valores estándar: **app_store**, **play_store**, **stripe**, **paddle**.En suscripciones recurrentes, es el ID de transacción original que vincula la cadena de renovaciones. La transacción original es la primera de la cadena; las posteriores son extensiones de ella.
Si no hay extensiones, `original_transaction_id` coincide con store_transaction_id.
El identificador de transacción de la compra original. | | **paywall_name** | String | Nombre del paywall donde se originó la transacción. | | **paywall_revision** | String | Revisión del paywall donde se originó la transacción. El valor por defecto es 1. | | **profile_country** | String | Determinado por Adapty a partir de la IP del perfil. | | **profile_event_id** | UUID | ID de evento único que puede usarse para deduplicación. | | **profile_has_access_level** | Boolean | Booleano que indica si el perfil tiene un nivel de acceso activo. | | **profile_id** | UUID | ID interno de perfil de usuario de Adapty. | | **profile_ip_address** | String | Dirección IP del perfil del usuario. | | **profile_total_revenue_usd** | Float | Ingresos totales del perfil, incluidos los reembolsos. | | **purchase_date** | ISO 8601 date | La fecha y hora de compra del producto. | | **renewed_at** | ISO 8601 date | Fecha y hora en que se renovará el acceso. | | **starts_at** | ISO 8601 date | Fecha y hora en que comienza el nivel de acceso. | | **store** | String | Store donde se compró el producto. Valores estándar: **app_store**, **play_store**, **stripe**, **paddle**.
1. **Configura tu endpoint:** 1. Asegúrate de que tu servidor pueda procesar las solicitudes de Adapty con la cabecera **Content-Type** establecida en `application/json`. 2. Configura tu servidor para recibir la solicitud de verificación de Adapty y responder con cualquier estado `2xx` y un cuerpo JSON. 3. [Gestiona los eventos de suscripción](#subscription-events) una vez verificada la conexión. 2. **Configura y activa la integración de webhook** en el [Adapty Dashboard](#configure-webhook-integration-in-the-adapty-dashboard). También puedes [mapear los eventos de Adapty a nombres de eventos personalizados](#configure-webhook-integration-in-the-adapty-dashboard). Te recomendamos probar en el entorno **Sandbox** antes de pasar a producción. 3. **Adapty envía una solicitud de verificación** a tu servidor. 4. **Tu servidor responde** con un estado `2XX` y un cuerpo JSON. 5. **Una vez que Adapty recibe una respuesta válida, empieza a enviar eventos de suscripción.** ## Configura tu servidor para procesar las solicitudes de Adapty \{#set-up-your-server-to-process-adapty-requests\} Adapty enviará a tu endpoint de webhook 2 tipos de solicitudes: 1. [Solicitud de verificación](#verification-request): la solicitud inicial para verificar que la conexión está configurada correctamente. Esta solicitud no contendrá ningún evento y se enviará en el momento en que hagas clic en el botón **Save** en la integración de Webhook del Adapty Dashboard. Para confirmar que tu endpoint recibió correctamente la solicitud de verificación, tu endpoint debe responder con la respuesta de verificación. 2. [Evento de suscripción](#subscription-events): una solicitud estándar que el servidor de Adapty envía cada vez que se crea un evento en él. Tu servidor no necesita responder con ninguna respuesta específica. Lo único que necesita el servidor de Adapty es recibir una respuesta HTTP estándar con código 200 si recibe el mensaje correctamente. ### Solicitud de verificación \{#verification-request\} Después de activar la integración de webhook en el Adapty Dashboard, Adapty enviará una solicitud POST de verificación que contiene un objeto JSON vacío `{}` como cuerpo. Configura tu endpoint para que tenga la **cabecera Content-Type** como `application/json`, es decir, el endpoint de tu servidor debe esperar que la solicitud de webhook entrante tenga su carga útil formateada como JSON. Tu servidor debe responder con un código de estado 2xx y enviar cualquier respuesta JSON válida, por ejemplo: ```json title="Json" {} ``` Una vez que Adapty recibe la respuesta de verificación en el formato correcto y con un código de estado 2xx, tu integración de webhook de Adapty está completamente configurada. ### Eventos de suscripción \{#subscription-events\} Los eventos de suscripción se envían con la cabecera **Content-Type** establecida en `application/json` y contienen datos del evento en formato JSON. Para conocer los posibles tipos de eventos y las estructuras de solicitud, consulta [Tipos de eventos y campos del webhook](webhook-event-types-and-fields). ## Configurar la integración de webhook en el Adapty Dashboard \{#configure-webhook-integration-in-the-adapty-dashboard\} En Adapty, puedes configurar flujos separados para los eventos de producción y los eventos de prueba recibidos desde el entorno sandbox de Apple o Stripe, o desde la cuenta de prueba de Google. Para los eventos de producción, usa el campo **Production endpoint URL** especificando la URL a la que se enviarán los callbacks. Además, configura el campo **Authorization header value for production endpoint**: la cabecera que tu servidor usará para autenticar los eventos de Adapty. Ten en cuenta que usaremos el valor especificado en el campo **Authorization header value for production endpoint** como cabecera `Authorization` exactamente como se proporcionó, sin ningún cambio ni adición. Para los eventos de prueba, usa los campos **Sandbox endpoint URL** y **Authorization header value for sandbox endpoint** según corresponda. Para configurar la integración de webhook: 1. Abre [Integrations -> Webhook](https://app.adapty.io/integrations/customwebhook) en tu Adapty Dashboard.
2. Activa el interruptor para iniciar la integración.
4. Rellena los campos de la integración:
| Campo | Descripción |
| ------------------------------------------------------ | ------------------------------------------------------------ |
| **Production endpoint URL** | La URL que Adapty usa para enviar solicitudes HTTP POST de eventos en producción. |
| **Authorization header value for production endpoint** | La cabecera que tu servidor usará para autenticar las solicitudes de Adapty en producción. Ten en cuenta que usaremos el valor especificado en este campo como cabecera `Authorization` exactamente como se proporcionó, sin ningún cambio ni adición.
Aunque no es obligatorio, se recomienda encarecidamente para mayor seguridad.
| Además, para tus necesidades de prueba en el entorno sandbox, hay otros dos campos disponibles: | Campo de prueba | Descripción | | --------------------------------------------------- | ------------------------------------------------------------ | | **Sandbox endpoint URL** | La URL que Adapty usa para enviar solicitudes HTTP POST de eventos en el entorno sandbox. | | **Authorization header value for sandbox endpoint** |La cabecera que tu servidor usará para autenticar las solicitudes de Adapty durante las pruebas en el entorno sandbox. Ten en cuenta que usaremos el valor especificado en este campo como cabecera `Authorization` exactamente como se proporcionó, sin ningún cambio ni adición.
Aunque no es obligatorio, se recomienda encarecidamente para mayor seguridad.
| 4. (Opcional) Elige los eventos que quieres recibir y mapea sus nombres. Consulta nuestros [Flujos de eventos](event-flows) para ver qué eventos se activan en cada situación. Si los IDs de tus eventos difieren de los usados en Adapty, mantén los IDs de tu sistema tal como están y reemplaza los IDs de eventos predeterminados de Adapty con los tuyos en la sección **Events names** de la página [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook). El ID del evento puede ser cualquier cadena; simplemente asegúrate de que el ID del evento en tu servidor de procesamiento de webhooks coincida con el que introdujiste en el Adapty Dashboard. No puedes dejar el ID del evento vacío para los eventos habilitados.
5. Los campos y opciones adicionales no son obligatorios; úsalos según sea necesario:
| Ajuste | Descripción |
| :--------------------------------- | :----------------------------------------------------------- |
| **Send Trial Price** | Cuando está habilitado, Adapty incluirá el precio de la suscripción en los campos `price_local` y `price_usd` para el evento **Trial Started**. |
| **Exclude Historical Events** | Elige excluir los eventos que ocurrieron antes de que el usuario instalara la app con el SDK de Adapty. Esto evita la duplicación de eventos y garantiza un reporting preciso. Por ejemplo, si un usuario activó una suscripción mensual el 10 de enero y actualizó la app con el SDK de Adapty el 6 de marzo, Adapty omitirá los eventos anteriores al 6 de marzo y conservará los eventos posteriores. |
| **Send user attributes** | Activa esta opción para enviar atributos específicos del usuario, como las preferencias de idioma. Estos atributos aparecerán en el campo `user_attributes`. Consulta [Campos del evento](webhook-event-types-and-fields#event-fields) para más información. |
| **Send attribution** | Activa esta opción para incluir información de atribución (por ejemplo, datos de AppsFlyer) en el campo `attributions`. Consulta la sección [Datos de atribución](webhook-event-types-and-fields#attributions) para más detalles. |
| **Send Play Store purchase token** | Activa esta opción para recibir el token de Play Store necesario para la revalidación de compras, si es necesario. Al activarlo, se añadirá el parámetro `play_store_purchase_token` al evento. Para más detalles sobre su contenido, consulta la sección [Token de compra de Play Store](webhook-event-types-and-fields#play-store-purchase-token). |
6. Recuerda hacer clic en el botón **Save** para confirmar los cambios.
En el momento en que hagas clic en el botón **Save**, Adapty enviará una solicitud de verificación y esperará la respuesta de verificación de tu servidor.
### Elegir los eventos a enviar y mapear los nombres de los eventos \{#choose-events-to-send-and-map-event-names\}
Elige los eventos que quieres recibir en tu servidor activando el interruptor correspondiente. Si los nombres de tus eventos difieren de los usados en Adapty y necesitas mantener tus nombres tal como están, puedes configurar el mapeo reemplazando los nombres de eventos predeterminados de Adapty con los tuyos en la sección **Events names** de la página [Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook).
El nombre del evento puede ser cualquier cadena. No puedes dejar los campos vacíos para los eventos habilitados. Si eliminaste accidentalmente el nombre de un evento de Adapty, siempre puedes copiarlo desde el artículo [Eventos para enviar a integraciones de terceros](events).
## Gestionar los eventos de webhook \{#handle-webhook-events\}
Los webhooks suelen entregarse entre 5 y 60 segundos después de que ocurre el evento. Sin embargo, los eventos de cancelación pueden tardar hasta 2 horas en entregarse después de que un usuario cancele su suscripción.
Si el código de estado de respuesta de tu servidor está fuera del rango 200-404, Adapty reintentará enviar el evento hasta 9 veces en 24 horas con retroceso exponencial. Te recomendamos configurar tu webhook para realizar solo una validación básica del cuerpo del evento de Adapty antes de responder. Si tu servidor no puede procesar el evento y no quieres que Adapty reintente, usa un código de estado dentro del rango 200-404. Además, gestiona cualquier tarea que consuma tiempo de forma asíncrona y responde a Adapty rápidamente. Si Adapty no recibe una respuesta en 10 segundos, considerará el intento como fallido y reintentará.
---
# File: test-webhook
---
---
title: "Probar la integración de webhook"
description: "Prueba las integraciones de webhook en Adapty para automatizar el seguimiento de eventos de suscripción."
---
Una vez que hayas configurado tu integración, es momento de probarla. Puedes probar tanto la integración en sandbox como la de producción. Te recomendamos empezar con la de sandbox y validar al máximo en ella:
- Los eventos se envían y se entregan correctamente.
- Configuraste correctamente las opciones para eventos históricos, el precio de la suscripción para el evento **Trial started**, la atribución, los atributos de usuario y el token de compra de Google Play Store para que se envíen o no con un evento.
- Mapeaste los nombres de los eventos correctamente y tu servidor puede procesarlos.
## Cómo probar \{#how-to-test\}
Antes de empezar a probar una integración, asegúrate de haber:
1. Configurado la integración de webhook según se describe en el tema [Configurar la integración de webhook](set-up-webhook-integration).
2. Configurado el entorno según se describe en los temas [Probar compras in-app en Apple App Store](test-purchases-in-sandbox) y [Probar compras in-app en Google Play Store](testing-on-android). Asegúrate de haber compilado tu app de prueba en el entorno sandbox y no en producción.
3. Realizado una compra / iniciado una prueba / solicitado un reembolso que genere el evento que elegiste enviar al webhook. Por ejemplo, para obtener el evento **Subscription started**, realiza una nueva suscripción.
## Validación del resultado \{#validation-of-the-result\}
### Resultado exitoso al enviar eventos \{#successful-sending-events-result\}
En caso de una integración exitosa, el evento aparecerá en la sección **Last sent events** de la integración y tendrá el estado **Success**.
### Resultado fallido al enviar eventos \{#unsuccessful-sending-events-result\}
| Problema | Solución |
|-----|--------|
| El evento no apareció | Tu compra no se realizó y, por lo tanto, el evento no se creó. Consulta el tema [Solución de problemas con compras de prueba](troubleshooting-test-purchases) para encontrar la solución. |
| El evento apareció y tiene el estado **Sending failed** | Determinamos la entregabilidad en función del estado HTTP y consideramos todo lo que esté **fuera del rango 200-399** como un fallo.
Para obtener más información sobre el problema, pasa el cursor sobre el estado **Sending failed** de tu evento fallido como se muestra a continuación.
|
---
# File: handle-integration-errors
---
---
title: "Gestionar errores en integraciones"
description: "Gestionar errores en integraciones"
---
Al usar cualquier integración de atribución, mensajería o analíticas, puede que encuentres algunos errores comunes. Consulta esta guía para los casos de solución de problemas.
## Discrepancia de datos \{#data-discrepancy\}
**Motivo**: Esto puede ocurrir porque no todos tus usuarios usan la versión de la app que tiene el SDK de Adapty.
**Solución**: Para garantizar la consistencia de los datos, puedes obligar a tus usuarios a actualizar la app a una versión con el SDK de Adapty.
## Errores de red \{#network-errors\}
**Motivo**: Lo más probable es que no haya habido conexión a internet entre el servidor de Adapty y el servidor de la integración.
**Solución**: Estos problemas normalmente no duran mucho y solo afectan a un pequeño número de eventos.
## El servidor de integración no pudo procesar el evento \{#integration-server-failed-to-process-the-event\}
**Motivo**: La integración está configurada incorrectamente.
**Solución**: Consulta el artículo sobre la integración en nuestra documentación. Asegúrate de haber completado todos los pasos de configuración tanto en el Adapty Dashboard, como en el lado de la herramienta de terceros y en el código de tu app.
## Datos de integración faltantes \{#missing-integration-data\}
**Motivo**: Al perfil le falta algún ID específico de la integración. Esto puede ocurrir cuando la integración no está configurada correctamente en el código de la app.
**Solución**: Consulta el artículo sobre la integración en nuestra documentación. Asegúrate de haber implementado los métodos de los fragmentos de código en el código de tu app, y de que estos métodos interactúen realmente con los perfiles de tus usuarios.
## Credenciales de integración faltantes \{#missing-integration-credentials\}
**Motivo**: Faltan algunas credenciales de integración o son incorrectas.
**Solución**: Comprueba todas las credenciales de esa integración en el Adapty Dashboard. El problema puede deberse a un desajuste de versión o de entorno.
## El evento ha expirado \{#the-event-has-expired\}
**Motivo**: La opción **Exclude historical events** está habilitada en la configuración de la integración, y la fecha de creación del evento es anterior a la fecha de creación del perfil en nuestro sistema.
Esto puede ocurrir si una cadena de transacciones que comenzó hace muchos años llega a Adapty mediante la validación de recibos para un perfil creado recientemente.
**Solución**: Asegúrate de que esto no ocurra con nuevos eventos. Si quieres enviar eventos históricos a la integración, desactiva **Exclude historical events**.
## Tipo de evento desactivado/no compatible \{#disabledunsupported-event-type\}
**Motivo**: El evento no está soportado por esta integración, o lo desactivaste al configurarla. Por ejemplo, los eventos `access_level_updated` no están soportados por la mayoría de las integraciones.
**Solución**: Consulta en la documentación de la integración si esta soporta ese tipo de evento. Si es así, en el Adapty Dashboard, asegúrate de que ese tipo de evento esté habilitado en la configuración de la integración.
---
# File: test-purchases-in-sandbox
---
---
title: "Pruebas en sandbox"
description: "Prueba compras en el entorno sandbox para garantizar transacciones sin problemas."
---
Una vez que hayas configurado todo en el Adapty Dashboard y en tu aplicación móvil, es hora de realizar pruebas de compras in-app.
**Nota:** ninguna de las herramientas de prueba cobra a los usuarios cuando prueban la compra de un producto. App Store no envía correos electrónicos por compras o reembolsos realizados en entornos de prueba.
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
2. Introduce los datos del usuario de prueba. Asegúrate de definir el **Country or Region** que planeas probar, ya que afecta la disponibilidad del producto para la región y la moneda de compra.
:::tip
- Si usas Gmail o iCloud, puedes reutilizar tu dirección de correo existente con el [subdireccionamiento con signo más](https://www.wikihow.com/Use-Plus-Addressing-in-Gmail).
- Puedes usar una dirección de correo aleatoria que ni siquiera exista, pero asegúrate de rechazar la autenticación de dos factores (2FA) cuando inicies sesión en un dispositivo de prueba más adelante.
:::
3. Haz clic en **Create**.
### Paso 2. Activar el modo Desarrollador \{#step-2-enable-the-developer-mode\}
:::note
Omite este paso si el modo Desarrollador ya está **activado** en tu dispositivo de prueba o si **no tienes un dispositivo Mac**.
:::
Necesitarás un Mac con Xcode instalado y el cable de tu dispositivo de prueba:
1. Abre Xcode en tu Mac. Si vas a probar las compras in-app con TestFlight, solo necesitas tener XCode instalado; no es necesario tener una app ahí.
2. Conecta tu dispositivo de prueba al Mac mediante el cable.
3. Ve a **Settings > Privacy & Security > Developer Mode** en tu dispositivo de prueba y activa el **Developer Mode**.
### Paso 3. Descargar la app desde TestFlight \{#step-3-download-the-app-from-testflight\}
:::info
Este paso solo aplica si estás probando con TestFlight. Si estás compilando la app en Xcode, omite este paso.
:::
Para más detalles sobre cómo enviar tu app a TestFlight, consulta la [documentación de Apple](https://developer.apple.com/documentation/StoreKit/testing-in-app-purchases-with-sandbox#Prepare-for-sandbox-testing).
Antes de descargar la app de TestFlight, en tu dispositivo de prueba, asegúrate de haber iniciado sesión con tu Apple Account de producción. Luego descarga la app que vayas a probar desde TestFlight.
:::danger
No abras la app una vez descargada. Continúa directamente con los siguientes pasos.
Si la abres accidentalmente, elimínala de tu dispositivo de prueba y descárgala de nuevo. De lo contrario, tu historial de compras puede no estar limpio y las pruebas de compras in-app generarán errores.
:::
### Paso 4. Cambiar a la cuenta de prueba Sandbox \{#step-4-switch-to-sandbox-test-account\}
4. Desplázate hacia abajo hasta la sección **Sandbox Apple Account** y toca **Sign In**.
5. Inicia sesión con las credenciales de tu Sandbox Apple Account.
### Paso 5. Borrar el historial de compras \{#step-5-clear-purchase-history\}
Si acabas de crear una nueva cuenta de prueba Sandbox y has cambiado a ella, puedes omitir este paso, ya que solo aplica cuando repites pruebas con la misma cuenta de prueba Sandbox.
1. Ve a **Settings > Developer > Sandbox Apple Account** en tu dispositivo de prueba.
2. Selecciona **Manage** en el menú emergente.
3. Ve a **Account Settings** y toca **Clear Purchase History**.
:::danger
Este paso es necesario cada vez que repitas las pruebas con la misma cuenta de prueba Sandbox. En ese caso, también deberás [cerrar sesión de tu cuenta de prueba Sandbox](#step-4-switch-to-sandbox-test-account) y volver a iniciarla para limpiar la caché del historial de compras en el dispositivo de prueba.
:::
### Paso 6. Compilar en Xcode y ejecutar \{#step-6-build-in-xcode-and-run\}
:::info
Este paso solo aplica si estás probando con una compilación de Xcode. Si usas TestFlight, omite este paso.
:::
1. Conecta tu dispositivo de prueba al Mac.
2. Abre Xcode.
3. Haz clic en **Run** en la barra de herramientas o elige **Product > Run** para compilar y ejecutar la app en el dispositivo conectado.
Si la compilación es exitosa, Xcode lanzará la app en tu dispositivo y abrirá una sesión de depuración en el área de debug.
Tu app ya está lista para pruebas en el dispositivo.
### Paso 7. Realizar una compra de prueba \{#step-7-make-test-purchase\}
Abre la app y realiza tu compra de prueba a través de un paywall.
Una vez hecho, ve al artículo sobre [validar compras de prueba](validate-test-purchases) para revisar los resultados.
### Paso 8. Seguir probando \{#step-8-keep-testing\}
Ahora tu entorno de pruebas está listo. Si quieres volver a probar, [borra el historial de compras de la cuenta sandbox](https://developer.apple.com/help/app-store-connect/test-in-app-purchases/manage-sandbox-apple-account-settings/).
## Problemas de prueba \{#testing-issues\}
A continuación se describen los problemas más comunes que puedes encontrar al probar una app.
### Problemas con TestFlight \{#testflight-issues\}
No puedes borrar tu historial de compras **si usas TestFlight sin la cuenta de prueba Sandbox**, lo que genera varios problemas y resultados de prueba incorrectos.
Si olvidaste accidentalmente [cambiar a la cuenta de prueba Sandbox](#step-4-switch-to-sandbox-test-account) y abriste la app aunque sea una vez, TestFlight asocia tu historial de compras a tu Apple Account de producción, lo que genera problemas inesperados.
Para solucionarlo, sigue estos pasos:
1. Elimina la app del dispositivo de prueba.
2. Sigue los pasos para las [pruebas en sandbox](#sandbox-testing).
:::note
Es importante no solo reinstalar la app, sino también cambiar a la cuenta de prueba Sandbox, borrar el historial de compras y lanzarla con la cuenta de prueba Sandbox.
:::
### Problemas con niveles de acceso compartidos \{#shared-access-levels-issues\}
Si repites las pruebas con la misma cuenta de prueba Sandbox, puedes encontrar comportamiento inesperado con los [niveles de acceso compartidos](sharing-paid-access-between-user-accounts) para el usuario de prueba.
Para verificar si el usuario tiene un nivel de acceso heredado, ve a [Profiles & Segments](https://app.adapty.io/profiles/users) desde el Adapty Dashboard y abre el perfil del usuario.
Si el usuario tiene un nivel de acceso heredado, sigue estos pasos para obtener resultados de prueba precisos:
1. Elimina el perfil principal.
2. Elimina la app del dispositivo de prueba.
3. [Descarga la app desde TestFlight](#step-3-download-the-app-from-testflight).
4. [Cambia a la cuenta de prueba Sandbox](#step-4-switch-to-sandbox-test-account).
5. [Borra el historial de compras](#step-5-clear-purchase-history).
6. [Abre la app y realiza tu compra de prueba](#step-6-make-test-purchase).
### Actualización de la app en TestFlight \{#updating-app-in-testflight\}
Si la app de TestFlight ha sido actualizada:
1. Elimina la app del dispositivo de prueba.
2. [Descarga la app desde TestFlight](#step-3-download-the-app-from-testflight).
3. [Cambia a la cuenta de prueba Sandbox](#step-4-switch-to-sandbox-test-account).
4. [Borra el historial de compras](#step-5-clear-purchase-history).
5. [Abre la app y realiza tu compra de prueba](#step-6-make-test-purchase).
### Autorización durante el proceso de compra \{#authorization-during-the-purchase-process\}
Si has descargado la app de TestFlight y no has [iniciado sesión en la cuenta sandbox desde la configuración del dispositivo](#step-4-switch-to-sandbox-test-account), intentar hacerlo durante el proceso de compra no funcionará. Para que la compra sea exitosa, debes iniciar sesión en tu cuenta sandbox desde la configuración del dispositivo antes de intentar realizar una compra.
## Suscripciones de prueba \{#test-subscriptions\}
Al probar la app con la cuenta de prueba Sandbox, puedes configurar la tasa de renovación de la suscripción para cada tester en sandbox. Consulta más información sobre la edición de las tasas de renovación de suscripciones en la [documentación oficial de Apple](https://developer.apple.com/help/app-store-connect/test-in-app-purchases/manage-sandbox-apple-account-settings).
De forma predeterminada, las suscripciones se renuevan hasta 12 veces antes de detenerse, según el siguiente calendario:
| Duración de la suscripción | 1 semana | 1 mes | 2 meses | 3 meses | 6 meses | 1 año |
| :---------------------------------- | :--------- | :--------- | :--------- | :--------- | :--------- | :--------- |
| Velocidad de renovación | 3 minutos | 5 minutos | 10 minutos | 15 minutos | 30 minutos | 1 hora |
| Duración del reintento de cobro | 10 minutos | 10 minutos | 10 minutos | 10 minutos | 10 minutos | 10 minutos |
| Duración del período de gracia | 3 minutos | 5 minutos | 5 minutos | 5 minutos | 5 minutos | 5 minutos |
:::note
Ten en cuenta que las transacciones de prueba pueden tardar hasta 10 minutos en aparecer en el [Event feed](validate-test-purchases).
:::
## Ofertas de prueba \{#test-offers\}
Para probar ofertas es necesario que todos los recibos del usuario estén eliminados para que la elegibilidad funcione correctamente.
La forma más fiable de probar ofertas es usar una [cuenta de prueba Sandbox](#step-1-create-sandbox-test-account-in-app-store-connect) completamente nueva. Repetir las pruebas con la misma cuenta de prueba Sandbox puede causar comportamiento inesperado.
:::danger
Si repites las pruebas con la misma cuenta de prueba Sandbox, asegúrate de [borrar el historial de compras](#step-5-clear-purchase-history) para evitar problemas relacionados con la elegibilidad.
:::
---
# File: local-sk-files
---
---
title: "Pruebas con StoreKit en Xcode"
description: "Prueba compras en el entorno sandbox para garantizar transacciones fluidas."
---
Las pruebas con StoreKit en Xcode te permiten probar compras in-app de forma local sin necesidad de configurar una cuenta sandbox.
Para este tipo de pruebas, necesitas:
1. [Crear un producto en Adapty](quickstart-products) y asignarle un **App Store product ID**.
2. En Xcode, crea un [archivo de configuración de StoreKit](https://developer.apple.com/documentation/xcode/setting-up-storekit-testing-in-xcode) local y añade un producto. El ID del producto debe coincidir con el **App Store product ID** en Adapty.
3. Añade el archivo de configuración de StoreKit a tu esquema de compilación y compila la app. Ejecútala en el emulador o en tu dispositivo.
## ¿Debería usar las pruebas con StoreKit en Xcode? \{#should-i-use-storekit-testing-in-xcode\}
Esta forma de probar es la más cómoda si eres desarrollador de la app y quieres probar la compilación sobre la marcha o reproducir distintos escenarios de compra usando las herramientas de Xcode.
Sin embargo, ten en cuenta que este tipo de pruebas es local, por lo que ningún cambio aparecerá en el Adapty Dashboard. Antes de lanzar tu app en producción, te recomendamos que pruebes el [trabajo con perfiles](ios-quickstart-identify) usando el [entorno sandbox](test-purchases-in-sandbox).
**Deberías** usar las pruebas con StoreKit si quieres:
- Probar la lógica de compra
- Reproducir distintos escenarios de compra con las herramientas de Xcode (por ejemplo, pago cancelado o reembolso)
- Probar usando el emulador
**No deberías** usar las pruebas con StoreKit si quieres:
- Probar la lógica relacionada con perfiles
- Verificar que tus acciones en la app aparecen en el Adapty Dashboard
- Compartir tu app con equipos que no sean de desarrollo para pruebas
## Paso 1. Crea un archivo de configuración de StoreKit \{#step-1-create-a-storekit-configuration-file\}
Para crear un archivo de configuración de StoreKit en Xcode:
1. Haz clic en **File > New > File from template**. Luego selecciona **StoreKit Configuration File** y haz clic en **Next**.
2. Ponle un nombre. Luego, dependiendo de si ya tienes los productos en App Store Connect:
- Selecciona **Sync this file with an app in App Store Connect**: para crear un archivo de configuración que contendrá todos tus productos de App Store Connect y poder probarlos localmente.
- No selecciones **Sync this file with an app in App Store Connect**: para crear un archivo de configuración vacío donde tendrás que añadir los productos manualmente.
Haz clic en **Next**.
3. No añadas tu app como destino. Continúa. Si estás trabajando con productos sincronizados desde App Store Connect, ve al [Paso 2](#step-2-add-the-configuration-file-to-the-build-scheme).
4. Si tus productos no están sincronizados desde App Store Connect, haz clic en **+** en la parte inferior izquierda y selecciona un tipo de producto.
5. Introduce un nombre para el grupo de suscripción y haz clic en **Next**.
6. Introduce un nombre de referencia. En el campo **Product ID**, introduce el **App Store product ID** de tu producto en Adapty.
7. Configura el precio, las ofertas y otros ajustes del producto en el archivo de configuración. O añade más productos.
## Paso 2. Añade el archivo de configuración al esquema de compilación \{#step-2-add-the-configuration-file-to-the-build-scheme\}
Para compilar la app usando este archivo de configuración, necesitas añadirlo a un esquema de compilación. La buena práctica es separar los esquemas de prueba y de producción, así que te sugerimos crear un nuevo esquema para pruebas:
1. En la parte superior, haz clic en el nombre de tu app y selecciona **New scheme**.
2. Introduce un nombre para el esquema y haz clic en **OK**.
3. Haz clic de nuevo en el nombre de la app y selecciona **Edit scheme**. En **StoreKit configuration**, selecciona tu archivo de configuración local para que se use al compilar.
## Paso 3. Compila y prueba \{#step-3-build--test\}
Ahora puedes compilar la app y probar compras in-app sin conectarte al backend de App Store. Puedes realizar compras y obtener niveles de acceso de forma local. Estos cambios no se reflejarán en el Adapty Dashboard, pero aun así puedes probar el desbloqueo de funciones de pago localmente.
[Lee más](https://developer.apple.com/documentation/xcode/testing-in-app-purchases-with-storekit-transaction-manager-in-code) sobre otras funciones disponibles con las pruebas de StoreKit en Xcode.
---
# File: testing-on-android
---
---
title: "Probar compras in-app en Google Play Store"
description: "Prueba compras de suscripción en Android usando Adapty."
---
Probar las compras in-app (IAPs) en tu app Android es un paso fundamental antes de publicarla. Las pruebas en sandbox son una forma segura y eficiente de probar IAPs sin cobrar dinero real a tus usuarios. En esta guía, te explicamos el proceso de pruebas en sandbox de IAPs en Google Play Store para Android.
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
2. Selecciona una lista de probadores de licencias existente o crea una nueva.
3. Añade la cuenta que usarás para las pruebas a la lista y guarda los cambios. Si los miembros de tu equipo también necesitan probar la app, puedes añadir sus correos electrónicos a la lista para que todo el grupo tenga acceso.
## 3. Crea una pista cerrada y añade la cuenta de prueba \{#3-create-closed-track-and-add-test-account-to-it\}
Para empezar a probar, necesitas publicar una versión firmada de tu app en una pista cerrada:
1. Abre tu app y selecciona **Test and release > Testing > Closed testing** en el menú. Allí, haz clic en **Create track**.
2. Introduce el nombre de la pista de pruebas cerrada y haz clic en **Create track**.
3. Añade una lista de probadores a la pista.
4. En la sección **How testers join your test**, copia el enlace y envíalo al dispositivo que ha iniciado sesión con la cuenta de prueba. Abre el enlace en tu dispositivo de pruebas para convertir al usuario en probador.
:::warning
Ten en cuenta lo siguiente para garantizar que las pruebas funcionen correctamente:
- Abrir la URL de participación marca tu cuenta de Play para pruebas. Si no completas este paso, los productos no se cargarán.
- Con frecuencia, los desarrolladores usan un ID de aplicación diferente para sus versiones de prueba. Esto puede causarte problemas, ya que Google Play Services utiliza el ID de aplicación para encontrar tus compras in-app.
- Hay casos en los que un usuario de prueba puede estar autorizado a comprar consumibles pero no suscripciones si el dispositivo de prueba no tiene PIN. Esto puede manifestarse con un críptico mensaje de "Something went wrong". Asegúrate de que el dispositivo de prueba tenga un PIN y de que esté conectado a Google Play Store.
:::
## 4. Sube un APK firmado a la pista cerrada \{#4-upload-a-signed-apk-to-the-closed-track\}
Genera un APK firmado o usa Android App Bundle para subir un APK firmado a la pista cerrada que acabas de crear. Ni siquiera necesitas lanzar el release. Solo sube el APK. Puedes encontrar más información al respecto en [este](https://support.google.com/googleplay/android-developer/answer/9859348?visit_id=638929100639477968-3849460621&rd=1) artículo de soporte.
:::important
Si tu app es nueva, es posible que tengas que hacerla disponible en tu país o región. Para ello, ve a **Testing > Closed testing**, haz clic en tu pista de pruebas y ve a **Countries/regions** para añadir los países y regiones deseados.
:::
## 5. Prueba las compras in-app \{#5-test-in-app-purchases\}
Después de subir el APK, espera unos minutos para que se procese el release. Luego, abre tu dispositivo de pruebas e inicia sesión con la cuenta de correo electrónico que añadiste a la lista de probadores. A continuación, podrás probar las compras in-app como lo harías en una app de producción.
## Más información \{#read-more\}
Consulta los siguientes recursos para saber más sobre cómo probar compras in-app en apps Android:
- [Períodos de renovación en sandbox](https://developer.android.com/google/play/billing/test#subs)
- [Probar compras únicas](https://developer.android.com/google/play/billing/test#one-time)
---
# File: validate-test-purchases
---
---
title: "Validar compras de prueba"
description: "Valida las compras de prueba en Adapty para garantizar transacciones sin problemas."
---
Antes de publicar tu app en producción, es fundamental probar las compras in-app a fondo. Consulta nuestros artículos [Probar compras in-app en Apple App Store](test-purchases-in-sandbox) y [Probar compras in-app en Google Play Store](testing-on-android) para obtener una guía detallada sobre cómo hacerlo. Una vez que empieces a probar, necesitas verificar que las compras de prueba se hayan completado correctamente.
Cada vez que realices una compra de prueba en tu dispositivo móvil, comprueba la transacción correspondiente en el [**Event Feed**](https://app.adapty.io/event-feed) del Adapty Dashboard. Si la compra no aparece en el **Event Feed**, significa que Adapty no la está registrando.
## La compra de prueba es exitosa \{#test-purchase-is-successful\}
Si la compra de prueba se realiza correctamente, el evento de transacción aparecerá en el **Event Feed**:
Si las transacciones funcionan como se espera, pasa al [Release checklist](release-checklist) y continúa con la publicación de la app.
## La compra de prueba no es exitosa \{#test-purchase-is-not-successful\}
Si no ves ningún evento de transacción en 10 minutos o encuentras un error en la app, consulta el artículo de [Solución de problemas](troubleshooting-test-purchases) y los artículos sobre manejo de errores [para iOS](ios-sdk-error-handling), [para Android](android-sdk-error-handling), [para React Native](react-native-handle-errors), [para Flutter](error-handling-on-flutter-react-native-unity), [para Unity](unity-handle-errors) y [Kotlin Multiplatform](kmp-handle-errors) para encontrar posibles soluciones.
---
# File: troubleshooting-test-purchases
---
---
title: "Solución de problemas con compras de prueba"
description: "Soluciona problemas con compras de prueba en Adapty y resuelve incidencias comunes en transacciones in-app."
---
Si encuentras problemas con las transacciones, asegúrate primero de haber completado todos los pasos del [checklist de lanzamiento](release-checklist). Si ya los completaste y sigues teniendo problemas, sigue las indicaciones a continuación para resolverlos:
## Se devuelve un error en la app móvil \{#an-error-is-returned-in-the-mobile-app\}
Consulta la lista de errores de tu plataforma: [para iOS](ios-sdk-error-handling), [para Android](android-sdk-error-handling), [para React Native](react-native-troubleshoot-purchases), [Flutter](error-handling-on-flutter-react-native-unity) y [Unity](unity-troubleshoot-purchases), y sigue nuestras recomendaciones para resolver el problema.
## La transacción no aparece en el Event Feed aunque no se devuelve ningún error en la app móvil \{#transaction-is-absent-from-the-event-feed-although-no-error-is-returned-in-the-mobile-app\}
Para resolver este problema, verifica lo siguiente:
1. **Para iOS**: Asegúrate de usar un dispositivo real y no un simulador.
2. Asegúrate de que el `Bundle ID`/`Package name` de tu app coincida con el que figura en [**App settings**](https://app.adapty.io/settings/general).
3. Asegúrate de que el `PUBLIC_SDK_KEY` de tu app coincida con la **Public SDK key** del Adapty Dashboard: [**App settings** -> pestaña **General** -> subsección **API keys**](https://app.adapty.io/settings/general).
4. Asegúrate de estar usando una cuenta sandbox y no un [archivo de configuración local de StoreKit](local-sk-files). Si antes usaste un archivo de configuración local de StoreKit para pruebas, verifica que no lo estés usando en la compilación actual.
## No hay ningún evento en mi perfil de prueba \{#no-event-is-present-in-my-testing-profile\}
Esto es un comportamiento normal. En Adapty se crea automáticamente un nuevo registro de perfil de usuario cuando:
- Un usuario ejecuta tu app por primera vez
- Un usuario cierra sesión en tu app
**Por qué ocurre:** Todas las transacciones y eventos están vinculados al perfil que generó la primera transacción. Esto mantiene todo el historial de transacciones (pruebas, compras, renovaciones) asociado al mismo perfil.
**Lo que verás:** Puede que aparezcan nuevos registros de perfil (llamados "perfiles no originales") sin eventos, pero conservarán los niveles de acceso. Es posible que veas eventos `access_level_updated`. Esto es un comportamiento esperado.
**Para pruebas:** Para evitar la creación de múltiples perfiles, crea una nueva cuenta de prueba (Sandbox Apple ID) cada vez que reinstales la app.
Para más detalles, consulta [Creación de perfiles](how-profiles-work#profile-creation).
A continuación se muestra un ejemplo de perfil no original. Observa la ausencia de eventos en **User history** y la presencia de un nivel de acceso.
## Los precios no reflejan los precios reales configurados en App Store Connect \{#prices-do-not-reflect-the-actual-prices-set-in-app-store-connect\}
Tanto en Sandbox como en TestFlight, que usa el entorno sandbox para las compras in-app, lo importante es verificar que el flujo de compra funcione correctamente, no que los precios sean exactos. Cabe destacar que la API de Apple puede proporcionar datos inexactos en ocasiones, especialmente cuando los dispositivos o cuentas tienen distintas regiones configuradas. Como los precios provienen directamente del Store y el backend de Adapty no afecta en ningún modo a los precios de compra, puedes ignorar cualquier inexactitud en los precios durante las pruebas de compras a través de Adapty.
Por tanto, prioriza la prueba del flujo de compra en sí sobre la exactitud de los precios para asegurarte de que funciona como se espera.
## La hora de la transacción en el Event Feed es incorrecta \{#the-transaction-time-in-the-event-feed-is-incorrect\}
El **Event Feed** utiliza la zona horaria configurada en **App Settings**. Para alinear la zona horaria de los eventos con tu hora local, ajusta la **Reporting timezone** en [**App settings** -> pestaña **General**](https://app.adapty.io/settings/general).
## Los paywalls y los productos tardan mucho en cargarse \{#paywalls-and-products-take-a-long-time-to-load\}
Este problema puede ocurrir si tu cuenta de prueba tiene un historial de transacciones muy largo. Te recomendamos encarecidamente crear una nueva cuenta de prueba cada vez, tal como se describe en la sección [Crear una cuenta de prueba en Sandbox (Sandbox Apple ID) en App Store Connect](test-purchases-in-sandbox#step-1-create-sandbox-test-account-in-app-store-connect).
Si no puedes crear una cuenta nueva, puedes borrar el historial de transacciones de tu cuenta actual siguiendo estos pasos en tu dispositivo iOS:
1. Abre **Configuración** y toca **App Store**.
2. Toca tu **Sandbox Apple ID**.
3. En el popup, selecciona **Manage**.
4. En la página **Account Settings**, toca **Clear Purchase History**.
Para más detalles, consulta la [documentación para desarrolladores de Apple](https://developer.apple.com/documentation/storekit/testing-in-app-purchases-with-sandbox).
---
# File: test-devices
---
---
title: "Dispositivos de prueba"
description: "Aprende a gestionar los dispositivos de prueba en Adapty para un testing eficiente."
---
Para hacer pruebas, puedes marcar tu dispositivo como dispositivo de prueba, lo que desactiva el caché y garantiza que los cambios se reflejen de inmediato.
:::note
Los dispositivos de prueba están disponibles a partir de las siguientes versiones del SDK:
- iOS: 2.11.1
- Android: 2.11.3
- React Native: 2.11.1
La compatibilidad con Flutter y Unity se añadirá más adelante.
:::
## Marca tu dispositivo como dispositivo de prueba \{#mark-your-device-as-test\}
1. Abre **[App settings](https://app.adapty.io/settings/general)** en el Adapty Dashboard.
2. Desplázate hacia abajo hasta la sección **Test devices** en la pestaña **General**.
3. Haz clic en el botón **Add test device**.
4. En la ventana **Add test device**, introduce:
| Campo | Descripción |
|:-----------------------------------------| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Test device name** | Nombre del dispositivo o dispositivos de prueba para tu referencia. |
| **ID used to identify this test device** | Elige el tipo de identificador que usarás para identificar el dispositivo o dispositivos de prueba. Consulta nuestras recomendaciones en la sección [Qué identificador deberías usar](test-devices#which-identifier-you-should-use) para elegir la mejor opción. |
| **ID value** | Introduce el valor del identificador. |
5. Recuerda hacer clic en el botón **Add test device** para guardar los cambios.
## Qué identificador deberías usar \{#which-identifier-you-should-use\}
Para identificar un dispositivo puedes usar varios identificadores. Recomendamos los siguientes:
- **Customer User ID** tanto para dispositivos iOS como Android si Un identificador único que tú asignas para identificar a tus usuarios en tu sistema. Puede ser el correo electrónico del usuario, tu ID interno o cualquier otra cadena de texto. Para usar esta opción, debes
Es la mejor opción para identificar un dispositivo de prueba, especialmente si usas varios dispositivos para la misma cuenta. Todos los dispositivos con esa cuenta se considerarán dispositivos de prueba.
| | Adapty profile ID |Un identificador único para el [perfil de usuario](profiles-crm) en Adapty.
Úsalo si no puedes usar el Customer User ID, el IDFA para iOS ni el Advertising ID para Android. Ten en cuenta que el Adapty Profile ID puede cambiar si reinstalar la app o vuelves a iniciar sesión.
| #### Cómo obtener el Customer User ID y el Adapty profile ID \{#how-to-obtain-customer-user-id-and-adapty-profile-id\} Ambos identificadores se pueden obtener en los detalles del **Profile** en el Adapty Dashboard: 1. Busca el perfil del usuario en la pestaña [**Adapty Profiles** -> **Event feed**](https://app.adapty.io/event-feed). :::note Para encontrar el perfil exacto, realiza un tipo de transacción poco frecuente. Cuando la transacción aparezca en el [**Event Feed**](https://app.adapty.io/event-feed), podrás identificarla fácilmente. ::: 2. Copia los valores de los campos **Customer user ID** y **Adapty ID** en los detalles del perfil:
### Identificadores de Apple \{#apple-identifiers\}
| Identificador | Uso |
|----------|-----|
| IDFA | El Identifier for Advertisers (IDFA) es un identificador único de dispositivo que Apple asigna al dispositivo del usuario.
Es ideal para dispositivos iOS, ya que no cambia por sí solo, aunque puedes restablecerlo manualmente.
**Nota**: Desde la introducción de iOS 14.5, los anunciantes deben solicitar el consentimiento del usuario para acceder al IDFA. Asegúrate de pedirlo en tu app y de haberlo concedido en tu dispositivo de prueba.
| | IDFV | El Identifier for Vendors (IDFV) es un identificador alfanumérico único que Apple asigna a todas las apps de un mismo dispositivo pertenecientes al mismo editor o proveedor. Puede cambiar si reinstalar o actualizas tu app. | #### Cómo obtener el IDFA \{#how-to-obtain-the-idfa\} Apple no proporciona el IDFA por defecto. Obtenlo a través de la atribución del perfil en el Adapty Dashboard: 1. Busca el perfil del usuario en la pestaña [**Adapty Profiles** -> **Event feed**](https://app.adapty.io/event-feed). :::note Para encontrar el perfil exacto, realiza un tipo de transacción poco frecuente. Cuando la transacción aparezca en el [**Event Feed**](https://app.adapty.io/event-feed), podrás identificarla fácilmente. ::: 2. Abre los detalles del perfil y copia el valor del campo **IDFA** en la sección **Attributes**:
También puedes [buscar en el App Store una app que te muestre tu IDFA](https://www.apple.com/us/search/idfa?src=globalnav).
#### Cómo obtener el Identifier for Vendors (IDFV) \{#how-to-obtain-the-identifier-for-vendors-idfv\}
Para obtener el IDFV, pide a tu desarrollador que lo solicite usando el siguiente método en tu app y que muestre el identificador recibido en los logs o en el panel de depuración.
```swift showLineNumbers title="Swift"
UIDevice.current.identifierForVendor
```
### Identificadores de Google \{#google-identifiers\}
| Identificador | Uso |
|----------|-----|
| Advertising ID | El Advertising ID es un identificador único de dispositivo que Google asigna al dispositivo del usuario.
Es ideal para dispositivos Android, ya que no cambia por sí solo, aunque puedes restablecerlo manualmente.
**Nota**: Para usarlo, desactiva la opción **Opt out of Ads Personalization** en la configuración de **Ads** si usas Android 12 o superior.
| | Android ID | El Android ID es un identificador único para cada combinación de clave de firma de la app, usuario y dispositivo. Está disponible en Android 8.0 y versiones superiores. | #### Cómo obtener el Advertising ID \{#how-to-obtain-advertising-id\} Para encontrar el Advertising ID de tu dispositivo: 1. Abre la app **Settings** en tu dispositivo Android. 2. Toca **Google**. 3. Selecciona **Ads** en **Services**. Tu Advertising ID aparecerá en la parte inferior de la pantalla. #### Cómo obtener el Android ID \{#how-to-obtain-android-id\} Para obtener el Android ID, pide a tu desarrollador que solicite el [ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID) usando el siguiente método en tu app y que muestre el identificador recibido en los logs o en el panel de depuración. ```kotlin showLineNumbers title="Kotlin/Java" android.provider.Settings.Secure.getString(contentResolver, android.provider.Settings.Secure.ANDROID_ID); ``` --- # File: release-checklist --- --- title: "Lista de verificación para el lanzamiento" description: "Sigue la lista de verificación de Adapty para garantizar un proceso de actualización de tu app sin problemas." --- ¡Nos alegra que hayas elegido Adapty! Esperamos que la implementación haya ido bien. Esta guía te llevará paso a paso para asegurarte de que tu app esté lista para publicarse en los stores y de que el flujo de monetización funcione correctamente. ## Elementos esenciales antes del lanzamiento \{#pre-flight-essentials\} Lo que necesitas antes de empezar la validación: - Un dispositivo real con una cuenta sandbox - Acceso al Adapty Dashboard - Acceso a App Store Connect / Google Play Console :::note Aunque las compras sandbox pueden ejecutarse en simuladores, necesitas dispositivos reales para probar todos los flujos, incluidos los diálogos de pago y las solicitudes biométricas. ::: ## Validaciones universales \{#universal-validations\} - [ ] **Conexión con el store**: Asegúrate de haber conectado Adapty a App Store y/o Google Play: - [ ] [App Store](initial_ios) - [ ] [Google Play](initial-android) - [ ] **Entrega de eventos de suscripción**: Confirma que las notificaciones del servidor estén configuradas: - [ ] [Notificaciones del servidor de App Store](enable-app-store-server-notifications) - [ ] [Notificaciones en tiempo real para desarrolladores (RTDN)](enable-real-time-developer-notifications-rtdn) - [ ] **Identificación de perfiles**: Valida la lógica de identificación de usuarios y asegúrate de que las compras se asignen al perfil correcto: - [ ] [Comprueba que la lógica de identificación en tu código coincide con tu caso de uso](ios-quickstart-identify) - [ ] [Asegúrate de entender la lógica padre/heredero para compartir acceso de pago entre perfiles de usuario](sharing-paid-access-between-user-accounts) - [ ] **Ofertas**: Si tienes ofertas promocionales de App Store en la app, asegúrate de haber [añadido tu clave de compra in-app](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers) tanto en el campo principal como en la sección **App Store promotional offers**. - [ ] **Recopilación de datos**: Garantiza el cumplimiento de la privacidad: - [ ] Si necesitas cumplir con normativas de privacidad como el RGPD o la CCPA, o si tu app está destinada a menores, controla si [habilitas la recopilación y el uso compartido de IDFA e IP](sdk-installation-ios#data-policies). - [ ] Si tu app usa AppTrackingTransparency, asegúrate de [enviar el estado de autorización a Adapty](ios-deal-with-att). - [ ] **Etiquetas de privacidad**: [Más información](apple-app-privacy) sobre los datos que recopila Adapty y qué indicadores debes configurar para la revisión. ## Validaciones de compras \{#purchase-validations\} --- no_index: true --- import Callout from '../../../components/Callout.astro';
2. Selecciona **Product** > **Archive** en la barra de menú superior.
3. Espera a que finalice el proceso de archivado. La ventana **Organizer** se abre automáticamente. Selecciona tu archivo y haz clic en **Distribute App**.
4. Elige **App Store Connect** como método de distribución. Sigue los pasos para completar la subida.
:::note
La subida puede fallar si faltan recursos obligatorios, como el icono de la app o la pantalla de inicio. Consulta el registro de errores de Xcode para más detalles.
:::
### Paso 2. Comprueba el build en App Store Connect \{#step-2-check-the-build-in-app-store-connect\}
1. Ve a [App Store Connect](https://appstoreconnect.apple.com) y abre tu app.
2. Desplázate hasta la sección **Build**. Asegúrate de que el build que acabas de subir aparece ahí.
:::note
Puede tardar unos minutos en aparecer el build en App Store Connect tras la subida.
:::
## Envía tu app y productos a revisión \{#submit-your-app-and-products-for-review\}
Una vez que el build aparezca en la sección **Build**, adjunta tus suscripciones in-app y envía la app para revisión de Apple.
### Paso 1. Adjunta los productos al envío \{#step-1-attach-products-to-the-submission\}
Cada suscripción debe tener el estado **Ready to Submit** en App Store Connect antes de poder adjuntarla. Si una suscripción está en borrador o le falta información, no aparecerá en la lista.
1. En la misma página, desplázate hasta la sección **In-App Purchases and Subscriptions**.
2. Haz clic en **Select in-app purchases or subscriptions**.
3. Selecciona todos los productos que quieras incluir en este envío y haz clic en **Done**.
### Paso 2. Envía para revisión \{#step-2-submit-for-review\}
1. Completa todos los campos obligatorios de la página (descripción, capturas de pantalla, palabras clave, etc.).
2. En la sección **App Store Version Release**, selecciona si quieres publicar tu app automáticamente, manualmente o de forma programada tras su aprobación.
3. Haz clic en **Add for Review** y luego en **Submit to App Review**.
Apple revisa las apps en un plazo de 1 a 2 días, aunque los tiempos pueden variar.
## Verifica tu app en producción \{#verify-your-app-in-production\}
Tras la aprobación de Apple:
1. Realiza una compra real (o espera a que tu primer usuario compre).
2. Abre el [**Event Feed**](https://app.adapty.io/event-feed) en el Adapty Dashboard y confirma que aparecen los eventos de transacciones en producción.
3. Comprueba que los eventos de suscripción (renovaciones, cancelaciones) llegan correctamente; esto depende de que las [notificaciones del servidor de App Store](enable-app-store-server-notifications) estén configuradas.
Si los eventos de producción no aparecen, verifica la [configuración de tu conexión con App Store](app-store-connection-configuration).
## Próximos pasos \{#next-steps\}
Tu app ya está en producción. Empieza a hacer crecer tus ingresos por suscripción:
- **[Pruebas A/B](ab-tests)**: Experimenta con distintos paywalls para encontrar el que mejor convierte.
- **[Analíticas](charts)**: Monitoriza métricas de suscripción como MRR, churn y conversión.
- **Integraciones**: Envía eventos de suscripción a plataformas de [analíticas](analytics-integration) y de [atribución](attribution-integration).
---
# File: general
---
---
title: "Configuración de la app"
description: "Explora la configuración general de Adapty para un uso sin complicaciones."
---
Puedes navegar a la pestaña General de la página App Settings para gestionar el comportamiento, la apariencia y el reparto de ingresos de tu app. Aquí puedes personalizar el nombre e icono de tu app, gestionar las claves del SDK y la API de Adapty, configurar tu estado en el Small Business Program y elegir la zona horaria para los análisis y gráficos de tu app.
## 1. Detalles de la app \{#1-app-details\}
Elige un nombre e icono únicos que representen tu app en la interfaz de Adapty. Ten en cuenta que el nombre y el icono de la app no afectarán al nombre ni al icono en el App Store o Google Play. Además, asegúrate de seleccionar una categoría de app adecuada que refleje con precisión el propósito y el contenido de tu app. Esto ayudará a los usuarios a descubrirla y garantizará que aparezca en las categorías correctas de la store.
## 2\. Miembro del Small Business Program y tarifa de servicio reducida \{#2-member-of-small-business-program-and-reduced-service-fee\}
Si tu organización está inscrita en el [Small Business Program](app-store-small-business-program) de Apple o en el programa de [tarifa de servicio reducida](google-reduced-service-fee) de Google, tus apps están sujetas a una comisión reducida de la store.
Notifica a Adapty si tu app está inscrita en un programa de comisión reducida. Para garantizar cálculos correctos, especifica el estado de estos programas en la sección "Reduced Store Fee".
La configuración de tarifa reducida solo se aplica a las transacciones futuras. Cambia tu estado **antes** de que entre en vigor y Adapty ajustará la tasa de comisión.
:::warning
* Si extiendes tu participación en un programa de tarifa reducida, **añade un período de elegibilidad adicional**.
* Si pierdes la membresía en el programa, **cambia la fecha de vencimiento** de tu período de elegibilidad actual.
:::
Los siguientes artículos profundizan en este tema:
* [App Store Small Business Program](app-store-small-business-program)
* [Google Reduced Service Fee](google-reduced-service-fee)
## 3\. Zona horaria de informes \{#3-reporting-timezone\}
Elige la zona horaria que corresponda a tu ubicación o a la zona donde los análisis y gráficos de tu app sean más relevantes. Recomendamos usar la misma zona horaria que tu cuenta de App Store Connect o Google Play Console para mantener la coherencia. Ten en cuenta que esta configuración de zona horaria no afecta a las integraciones de terceros en el sistema de Adapty, que utilizan la zona horaria UTC.
Puedes acceder a la configuración de zona horaria en la sección "Reported timezone" de la pestaña General en la página App Settings. También puedes aplicar la misma zona horaria a todas las apps de tu cuenta de Adapty marcando la casilla correspondiente.
## 4\. Definición de instalaciones para análisis \{#4-installs-definition-for-analytics\}
Elige qué se considera un nuevo evento de instalación en los análisis:
| Base | Descripción |
|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Nuevos device_ids | (Recomendado) Cada instalación de la app desde la store en un dispositivo se cuenta como una nueva instalación. Esto incluye tanto las instalaciones por primera vez como las reinstalaciones.
Las instalaciones se cuentan por ID de dispositivo y no se ven afectadas por la autenticación del usuario. Crear un perfil (al activar el SDK o al cerrar sesión), iniciar sesión o actualizar la app no genera eventos de instalación adicionales.
Por ejemplo, si la misma app está instalada en 5 dispositivos diferentes, verás 5 instalaciones en los análisis.
| | Nuevos customer_user_ids |Esta opción está pensada para apps que
Para los usuarios con sesión iniciada, solo la primera instalación asociada a un customer user ID se cuenta como instalación. Las instalaciones en dispositivos adicionales no se contabilizan como nuevas instalaciones.
Los usuarios anónimos (usuarios que no han iniciado sesión) no se contabilizan en los análisis.
Reinstalar la app o volver a iniciar sesión no crea instalaciones adicionales.
Las stores y las plataformas de atribución (como App Store Connect, Google Play Console y AppsFlyer) utilizan un enfoque basado en dispositivos para contar instalaciones. Si cuentas instalaciones por customer user IDs en Adapty, los números pueden diferir de los de estos servicios externos.
⚠️ Si no identificas usuarios en Adapty, no se contabilizará ninguna instalación con esta opción activada.
| | Nuevos perfiles en Adapty | (Heredado) Cada instalación, reinstalación de la app y los perfiles anónimos creados durante los cierres de sesión se cuentan como nuevas instalaciones. | Ten en cuenta que esta opción solo afecta a la página [**Analytics**](https://app.adapty.io/analytics) y no tiene impacto en la página [**Overview**](https://app.adapty.io/overview), donde puedes configurar la vista por separado. ## 5. Lógica de aumento de precio en el App Store \{#5-app-store-price-increase-logic\} Para mantener datos precisos y evitar discrepancias entre los análisis de Adapty y los resultados de App Store Connect, es importante seleccionar la opción adecuada al ajustar las configuraciones relacionadas con los aumentos de precio en App Store Connect. Así puedes elegir la lógica que se aplicará a los aumentos de precio de las suscripciones en Adapty:
- **El precio de la suscripción para los usuarios existentes se mantiene:** Al seleccionar esta opción, el precio actual se conservará para tus suscriptores existentes, aunque realices cambios en el precio en App Store Connect. Esto significa que los suscriptores existentes seguirán siendo facturados al precio original de su suscripción.
- **Cuando el precio de la suscripción cambia en App Store Connect, también cambia para los suscriptores existentes:** Si eliges esta opción, cualquier cambio de precio realizado en App Store Connect se aplicará también a tus suscriptores existentes. Esto significa que los suscriptores existentes serán cobrados al nuevo precio que refleja la actualización establecida en App Store Connect.
:::warning
Es importante tener en cuenta que la opción seleccionada no solo afecta a los análisis en Adapty, sino que también impacta en las integraciones y en el comportamiento general del procesamiento de transacciones.
:::
Asegúrate de seleccionar la opción adecuada que se alinee con tu enfoque deseado para gestionar los precios de las suscripciones para los suscriptores existentes. Esto ayudará a mantener datos precisos y la sincronización entre los análisis de Adapty y los resultados obtenidos de App Store Connect.
## 6. Compartir el acceso de pago entre cuentas de usuario \{#6-sharing-paid-access-between-user-accounts\}
:::link
Artículo principal: [Compartir el acceso de pago entre cuentas de usuario](sharing-paid-access-between-user-accounts)
:::
La configuración **Sharing paid access between user accounts** determina qué hace Adapty cuando más de un [perfil de usuario](identifying-users) intenta acceder a la misma compra. Puedes especificar una configuración de compartición de acceso independiente para el [entorno sandbox](test-purchases-in-sandbox).
---
no_index: true
---
**Habilitado (predeterminado)**
Los usuarios identificados (aquellos con un [Customer User ID](identifying-users#set-customer-user-id-on-configuration)) pueden compartir el mismo [nivel de acceso](access-level) proporcionado por Adapty si su dispositivo está vinculado al mismo Apple/Google ID. Esto es útil cuando un usuario reinstala la app e inicia sesión con un correo diferente: seguirá teniendo acceso a su compra anterior. Con esta opción, varios usuarios identificados pueden compartir el mismo nivel de acceso.
Aunque el nivel de acceso se comparte, todas las transacciones pasadas y futuras se registran como eventos en el Customer User ID original para mantener análisis coherentes y conservar un historial completo de transacciones, incluyendo períodos de prueba, compras de suscripción, renovaciones y más, vinculados al mismo perfil.
**Transferir acceso al nuevo usuario**
Los usuarios identificados pueden seguir accediendo al [nivel de acceso](access-level) proporcionado por Adapty, incluso si inician sesión con un [Customer User ID](identifying-users#set-customer-user-id-on-configuration) diferente o reinstalan la app, siempre que el dispositivo esté vinculado al mismo Apple/Google ID.
A diferencia de la opción anterior, Adapty transfiere la compra entre usuarios identificados. Esto garantiza que el contenido adquirido esté disponible, pero solo un usuario puede tener acceso a la vez. Por ejemplo, si UserA compra una suscripción y UserB inicia sesión en el mismo dispositivo y restaura las transacciones, UserB obtendrá acceso a la suscripción y se le revocará a UserA.
Si uno de los usuarios (ya sea el nuevo o el anterior) no está identificado, el nivel de acceso seguirá compartiéndose entre esos perfiles en Adapty.
Aunque el nivel de acceso se transfiere, todas las transacciones pasadas y futuras se registran como eventos en el Customer User ID original para mantener análisis coherentes y conservar un historial completo de transacciones, incluyendo períodos de prueba, compras de suscripción, renovaciones y más, vinculados al mismo perfil.
Después de cambiar a **Transferir acceso al nuevo usuario**, los niveles de acceso no se transferirán entre perfiles de inmediato. El proceso de transferencia para cada nivel de acceso específico se activa solo cuando Adapty recibe un evento del store, como la renovación de una suscripción, una restauración o al validar una transacción.
**Deshabilitado**
El primer perfil de usuario identificado que obtenga un nivel de acceso lo conservará para siempre. Esta es la mejor opción si la lógica de negocio de tu app requiere que las compras estén vinculadas a un único Customer User ID.
Ten en cuenta que los niveles de acceso siguen compartiéndose entre usuarios anónimos.
Puedes "desvincular" una compra [eliminando el perfil del usuario propietario](ss-delete-profile). Tras la eliminación, el nivel de acceso queda disponible para el primer perfil de usuario que lo reclame, ya sea anónimo o identificado.
Deshabilitar el uso compartido solo afecta a los nuevos usuarios. Las suscripciones que ya se comparten entre usuarios seguirán compartiéndose incluso después de deshabilitar esta opción.
:::warning
Apple y Google exigen que las compras in-app se compartan o transfieran entre usuarios porque se basan en el Apple/Google ID para asociar la compra. Sin el uso compartido, restaurar compras podría no funcionar tras reinstalaciones posteriores.
Deshabilitar el uso compartido puede impedir que los usuarios recuperen el acceso al iniciar sesión.
Recomendamos deshabilitar el uso compartido solo si tus usuarios **deben iniciar sesión** antes de realizar una compra. De lo contrario, un usuario identificado podría comprar una suscripción, iniciar sesión en otra cuenta y perder el acceso de forma permanente.
:::
### ¿Qué opción debo elegir? \{#which-setting-should-i-choose\}
| Mi app... | Opción a elegir |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| No tiene sistema de inicio de sesión y solo usa los IDs de perfil anónimos de Adapty. | Usa la opción predeterminada, ya que los niveles de acceso siempre se comparten entre IDs de perfil anónimos en las tres opciones. |
| Tiene un sistema de inicio de sesión opcional y permite a los clientes realizar compras antes de crear una cuenta. | Elige **Transferir acceso al nuevo usuario** para garantizar que los clientes que compren sin una cuenta puedan restaurar sus transacciones más adelante. |
| Requiere que los clientes creen una cuenta antes de comprar, pero permite que las compras estén vinculadas a varios Customer User IDs. | Elige **Transferir acceso al nuevo usuario** para garantizar que solo un Customer User ID tenga acceso a la vez, permitiendo a los usuarios iniciar sesión con un Customer User ID diferente sin perder su acceso de pago. |
| Requiere que los clientes creen una cuenta antes de comprar, con reglas estrictas que vinculan las compras a un único Customer User ID. | Elige **Deshabilitado** para garantizar que las transacciones nunca se transfieran entre cuentas. |
## 7. Claves del SDK y la API \{#7-sdk-and-api-keys\}
Usa una clave SDK pública para integrar los SDK de Adapty en tu app, y una clave secreta para acceder a la API del servidor de Adapty. Puedes generar nuevas claves o revocar las existentes según sea necesario. Para crear tokens para el Developer CLI, ve a **Settings → Developer API**. Consulta [Authentication](developer-cli-authentication).
## 8. Dispositivos de prueba \{#8-test-devices\}
Especifica los dispositivos que se usarán para pruebas para asegurarte de que reciben actualizaciones instantáneas de los cambios en paywalls o placements, sin demoras de caché. Para más información, consulta [Testing devices](test-devices).
## 9. Persistencia de variante entre placements \{#9-cross-placement-variation-stickiness\}
Define cuánto tiempo después de finalizar una prueba un usuario sigue viendo las variantes de esa prueba. Esto afecta a la precisión de los análisis y a la experiencia del usuario, ya que mostrarle una oferta diferente a la que vio anteriormente puede influir en su decisión de compra.
El período máximo y predeterminado de persistencia es de 90 días.
:::warning
Ten en cuenta lo siguiente:
- Cambiar esta configuración afectará a todos los usuarios que previamente recibieron una variante. Inmediatamente podrán ver un nuevo paywall cuando accedan a un placement, lo que puede distorsionar los resultados de tus pruebas A/B en curso.
- Si el período de persistencia ha expirado para un usuario, puede recibir un nuevo paywall o prueba A/B. Sin embargo, incluso en ese caso, no podrá formar parte de ninguna otra prueba entre placements en ningún momento futuro.
:::
## 10. Eliminar la app \{#10-delete-the-app\}
Si ya no necesitas una app, puedes eliminarla de Adapty.
:::warning
Ten en cuenta que esta acción es irreversible y no podrás restaurar la app ni sus datos.
:::
---
# File: ios-settings
---
---
title: "Credenciales de Apple App Store"
description: "Configura los ajustes de iOS en Adapty para una gestión de suscripciones sin interrupciones."
---
Para configurar las credenciales de App Store y garantizar el funcionamiento óptimo del SDK de iOS de Adapty, ve a la pestaña [iOS SDK](https://app.adapty.io/settings/ios-sdk) dentro de la página App Settings del Adapty Dashboard. Luego, configura los siguientes parámetros:
| Campo | Descripción |
|----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Bundle ID** | El [bundle ID de tu app](app-store-connection-configuration#step-1-provide-bundle-id-and-apple-app-id). |
| **In-app purchase API (StoreKit 2)** | [Claves](app-store-connection-configuration#step-2-provide-issuer-id-and-key-id) para habilitar la autenticación segura y la validación del historial de transacciones de compras in-app. |
| **App Store Server Notifications** | URL que se utiliza para habilitar las [notificaciones server2server](enable-app-store-server-notifications) de App Store y monitorizar los cambios en el estado de suscripción de los usuarios. |
| **App Store Promotional Offers** | Claves de suscripción para crear [ofertas promocionales](generate-in-app-purchase-key) en Adapty para productos específicos. |
| **Apple app ID** | El ID de tu app en App Store. Para encontrarlo, abre la página de tu app en App Store Connect, accede a la página **App Information** desde el menú izquierdo y copia el **Apple ID**. |
| **App Store Connect shared secret (LEGACY)** | **Clave heredada para el SDK de Adapty anterior a v.2.9.0**
[Una clave](app-store-connection-configuration#step-5-enter-app-store-shared-secret) para la validación de recibos y la prevención de fraude en tu app.
| --- # File: google-play-store-connection-configuration --- --- title: "Configurar la integración con Google Play Store" description: "Configura la conexión con Google Play Store en Adapty para gestionar las compras in-app sin problemas." --- Esta sección describe el proceso de integración de tu aplicación móvil distribuida a través de Google Play con Adapty. Tendrás que introducir los datos de configuración de tu app desde la Play Store en el Adapty Dashboard. Este paso es fundamental para validar las compras y recibir actualizaciones de suscripciones desde la Play Store dentro de Adapty. Puedes completar este proceso durante el onboarding inicial o realizar cambios posteriormente en los **App Settings** del Adapty Dashboard. :::danger Los cambios de configuración solo son válidos antes de publicar tu aplicación móvil con los paywalls de Adapty integrados. Modificar la configuración tras el lanzamiento romperá la integración y los paywalls dejarán de mostrarse en tu aplicación. ::: ## Paso 1. Proporciona el Package name \{#step-1-provide-package-name\} El Package name es el identificador único de tu app en Google Play Store. Es necesario para el funcionamiento básico de Adapty, como el procesamiento de suscripciones. 1. Abre la [Google Play Developer Console](https://play.google.com/console/u/0/developers). 2. Selecciona la app cuyo ID necesitas. Se abrirá la ventana **Dashboard**.
3. Busca el ID del producto bajo el nombre de la aplicación y cópialo.
4. Abre los [**App settings**](https://app.adapty.io/settings/android-sdk) desde el menú superior de Adapty.
5. En la pestaña **Android SDK** de la ventana **App settings**, pega el **Package name** copiado.
## Paso 2. Sube el archivo de clave de cuenta \{#step-2-upload-the-account-key-file\}
1. Sube el archivo de clave privada de cuenta de servicio en formato JSON que creaste en el paso [Crear archivo de clave de cuenta de servicio](create-service-account) en el área **Service account key file**.
No olvides hacer clic en el botón **Save** para confirmar los cambios.
**Próximos pasos**
- [Activar las notificaciones en tiempo real para desarrolladores (RTDN) en la Google Play Console](enable-real-time-developer-notifications-rtdn)
---
# File: enable-real-time-developer-notifications-rtdn
---
---
title: "Habilitar notificaciones en tiempo real para desarrolladores (RTDN) en Google Play Console"
description: "Mantente informado sobre eventos críticos y garantiza la exactitud de los datos habilitando las Notificaciones en Tiempo Real para Desarrolladores (RTDN) en Google Play Console para Adapty. Aprende a configurar RTDN para recibir actualizaciones instantáneas sobre reembolsos y otros eventos importantes de la Play Store"
---
Configurar las notificaciones en tiempo real para desarrolladores (RTDN) es fundamental para garantizar la exactitud de los datos, ya que te permite recibir actualizaciones al instante desde la Play Store, incluyendo información sobre reembolsos y otros eventos.
## Habilitar notificaciones \{#enable-notifications\}
1. Asegúrate de tener **Google Cloud Pub/Sub** habilitado. Abre [este enlace](https://console.cloud.google.com/flows/enableapi?apiid=pubsub) y selecciona el proyecto de tu app. Si todavía no has habilitado **Google Cloud Pub/Sub**, debes hacerlo aquí.
2. Ve a [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) desde el menú superior de Adapty y copia el contenido del campo **Enable Pub/Sub API** que aparece junto al título **Google Play RTDN topic name**.
:::note Si el contenido del campo **Enable Pub/Sub API** tiene un formato incorrecto (el formato correcto empieza por `projects/...`), consulta la sección [Corregir el formato incorrecto en el campo Enable Pub/Sub API](enable-real-time-developer-notifications-rtdn#fixing-incorrect-format-in-enable-pubsub-api-field) para obtener ayuda. ::: 3. Abre la [Google Play Console](https://play.google.com/console/), elige tu app y ve a **Monetize with Play** -> **Monetization setup**. En la sección **Google Play Billing**, marca la casilla **Enable real-time notifications**. 4. Pega el contenido del campo **Enable Pub/Sub API** que copiaste en los **App Settings** de Adapty en el campo **Topic name**. 5. Haz clic en **Save changes** en la Google Play Console.
## Probar las notificaciones \{#test-notifications\}
Para comprobar si te has suscrito correctamente a las notificaciones en tiempo real para desarrolladores:
1. Guarda los cambios en la configuración de Google Play Console.
2. Debajo del campo **Topic name** en Google Play Console, haz clic en **Send test notification**.
3. Ve a [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) en Adapty. Si se ha enviado una notificación de prueba, verás su estado encima del nombre del topic.
## Corregir el formato incorrecto en el campo Enable Pub/Sub API \{#fixing-incorrect-format-in-enable-pubsub-api-field\}
Si el contenido del campo **Enable Pub/Sub API** tiene un formato incorrecto (el formato correcto empieza por `projects/...`), sigue estos pasos para solucionar el problema:
### 1. Verificar la habilitación de la API y los permisos \{#1-verify-api-enablement-and-permissions\}
Comprueba detenidamente que todas las APIs necesarias estén habilitadas y que los permisos estén correctamente concedidos a la cuenta de servicio. Aunque ya hayas completado estos pasos, es importante revisarlos de nuevo para asegurarte de que no se omitió ninguno. Repite los pasos de las siguientes secciones:
1. [Habilitar las APIs de desarrollador en Google Play Console](enabling-of-devepoler-api)
2. [Crear una cuenta de servicio en Google Cloud Console](create-service-account)
3. [Conceder permisos a la cuenta de servicio en Google Play Console](grant-permissions-to-service-account)
4. [Generar el archivo de clave de la cuenta de servicio en Google Play Console](create-service-account-key-file)
5. [Configurar la integración con Google Play Store](google-play-store-connection-configuration)
### 2. Ajustar las políticas de dominio \{#2-adjust-domain-policies\}
Cambia las políticas **Domain restricted contacts** y **Domain restricted sharing**:
1. Abre la [Google Cloud Console](https://console.cloud.google.com/) y selecciona el proyecto donde creaste la cuenta de servicio para gestionar tu app.
2. En la sección **Quick Access**, elige **IAM & Admin**.
3. En el panel izquierdo, elige **Organization Policies**.
4. Busca la política **Domain restricted contacts**.
5. Haz clic en el botón de puntos suspensivos en la columna **Actions** y elige **Edit policy**.
6. En la ventana de edición de la política:
1. En **Policy source**, selecciona el botón de opción **Override parent's policy**.
2. En **Policy enforcement**, selecciona el botón de opción **Replace**.
3. En **Rules**, haz clic en el botón **ADD A RULE**.
4. En **New rule** -> **Policy values**, elige **Allow All**.
5. Haz clic en **SET POLICY**.
7. Repite los pasos 4-6 para la política **Domain restricted sharing**.
Por último, vuelve a generar el contenido del campo **Enable Pub/Sub API** situado junto al título **Google Play RTDN topic name**. El campo tendrá ahora el formato correcto.
Asegúrate de cambiar **Policy source** de vuelta a **Inherit parent's policy** para las políticas actualizadas una vez que hayas habilitado correctamente las Notificaciones en Tiempo Real para Desarrolladores (RTDN).
## Reenvío de eventos sin procesar \{#raw-events-forwarding\}
En algunos casos, puede que quieras seguir recibiendo eventos S2S sin procesar de Google. Para continuar recibiéndolos mientras usas Adapty, simplemente añade tu endpoint en el campo **URL for forwarding raw Google events** y enviaremos los eventos tal cual los recibimos de Google.
---
**Próximos pasos**
Configura el SDK de Adapty para:
- [Android](sdk-installation-android)
- [React Native](sdk-installation-reactnative)
- [Flutter](sdk-installation-flutter)
- [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform)
- [Unity](sdk-installation-unity)
---
# File: apple-search-ads
---
---
title: "Apple Ads"
description: "Integra Apple Ads con Adapty para optimizar las conversiones de suscripción."
---
:::important
La integración de Apple Ads en **App settings** se usa únicamente para análisis básicos y para las integraciones de SplitMetrics Acquire y Asapty.
[Apple Ads Manager](adapty-ads-manager) utiliza una conexión independiente. Conecta tu cuenta de Apple Ads en los [ajustes de Apple Ads Manager](adapty-ads-manager-get-started).
:::
Adapty puede ayudarte a obtener datos de atribución de Apple Ads y analizar tus métricas con segmentación por campaña y palabra clave. Adapty recopila automáticamente los datos de atribución de Apple Ads a través de su SDK y el framework AdServices.
Una vez que hayas configurado la integración con Apple Ads, Adapty comenzará a recibir datos de atribución de Apple Ads. Puedes acceder a estos datos fácilmente y consultarlos en la página de perfiles.
## Configurar la integración \{#set-up-integration\}
### Conectar Adapty al framework AdServices \{#connect-adapty-to-the-adservices-framework\}
Apple Ads a través de [AdServices](https://developer.apple.com/documentation/adservices) requiere cierta configuración en el Adapty Dashboard, y también deberás habilitarlo en la parte de la app. Para configurar Apple Ads usando el framework AdServices a través de Adapty, sigue estos pasos:
#### Paso 1: Configurar Info.plist \{#step-1-configure-infoplist\}
Añade `AdaptyAppleSearchAdsAttributionCollectionEnabled` al archivo `Info.plist` de la app y establece su valor en `YES` (booleano).
#### Paso 2: Obtener la clave pública \{#step-2-obtain-public-key\}
En el Adapty Dashboard, ve a [Settings -> Apple Ads.](https://app.adapty.io/settings/apple-search-ads)
Localiza la clave pública pregenerada (Adapty te proporciona un par de claves) y cópiala.
:::note
Si usas un servicio alternativo o tu propia solución para la atribución de Apple Ads, puedes subir tu propia clave privada.
:::
#### Paso 3: Configurar la gestión de usuarios en Apple Ads \{#step-3-configure-user-management-on-apple-ads\}
En tu [cuenta de Apple Ads](https://ads.apple.com/app-store), ve a la página **Settings > User Management**. Para que Adapty pueda obtener los datos de atribución, debes invitar a otra cuenta de Apple ID y concederle acceso como API Account Manager. Puedes usar cualquier cuenta a la que tengas acceso o crear una nueva específicamente para este fin. Lo importante es que debes poder iniciar sesión en Apple Ads con ese Apple ID.
#### Paso 4: Generar las credenciales de API \{#step-4-generate-api-credentials\}
A continuación, inicia sesión en Apple Ads con la cuenta recién añadida. Ve a Settings -> API en la interfaz de Apple Ads. Pega la clave pública que copiaste anteriormente en el campo correspondiente. Genera nuevas credenciales de API.
#### Paso 5: Configurar Adapty con las credenciales de Apple Ads \{#step-5-configure-adapty-with-apple-ads-credentials\}
Copia los campos Client ID, Team ID y Key ID de los ajustes de Apple Ads. En el Adapty Dashboard, pega estas credenciales en los campos correspondientes.
### Conectar tu app a la red AdServices \{#connect-your-app-to-the-adservices-network\}
Una vez que completes [la configuración del framework AdServices](#connect-the-adservices-framework), Adapty empieza a recopilar automáticamente los datos de atribución de Apple Search Ads. No necesitas añadir ningún código al SDK.
En aplicaciones iOS, estos datos de atribución **siempre** tendrán prioridad sobre los datos de otras fuentes. Si este comportamiento no es el deseado, *desactiva* la atribución de ASA siguiendo las instrucciones a continuación.
## Desactivar la integración \{#disable-integration\}
Para desactivar la atribución de Apple Search Ads, abre la pestaña [**App Settings** -> **Apple Search Ads**](https://app.adapty.io/settings/apple-search-ads) y desactiva el interruptor **Receive Apple Search Ads attribution**.
:::warning
Ten en cuenta que desactivar esto detendrá completamente la recepción de análisis de ASA. Como resultado, ASA dejará de usarse en los análisis y no se enviará a las integraciones. Además, SplitMetrics Acquire y Asapty dejarán de funcionar, ya que dependen de la atribución de ASA para operar correctamente.
La atribución recibida antes de este cambio no se verá afectada.
:::
## Subir tus propias claves \{#uploading-your-own-keys\}
:::note
Opcional
Estos pasos no son necesarios para la atribución de Apple Ads, solo para trabajar con otros servicios como Asapty o tu propia solución.
:::
Puedes usar tu propio par de claves pública-privada si estás utilizando otros servicios o una solución propia para la atribución de ASA.
### Paso 1 \{#step-1\}
Genera la clave privada en el Terminal
```text showLineNumbers title="Text"
openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem
```
Súbela en Adapty Settings -> Apple Ads (botón Upload private key)
### Paso 2 \{#step-2\}
Genera la clave pública en el Terminal
```text showLineNumbers title="Text"
openssl ec -in private-key.pem -pubout -out public-key.pem
```
Puedes usar esta clave pública en los ajustes de Apple Ads de la cuenta con el rol API Account Manager. Así podrás usar los valores generados de Client ID, Team ID y Key ID tanto en Adapty como en otros servicios.
---
# File: account
---
---
title: "Detalles de la cuenta y facturación"
description: "Gestiona tu cuenta de Adapty y optimiza la configuración para un mejor seguimiento de suscripciones."
---
La página **Account** te permite gestionar tu perfil, los miembros del equipo y la facturación.
La página tiene tres pestañas:
- [General](#general-settings)
- [Subscription & Billing](#billing-info)
- [Members](#members)
Para acceder a la configuración de tu cuenta, haz clic en **Account** en la parte superior derecha o ve a [app.adapty.io/account](https://app.adapty.io/account).
## Configuración general \{#general-settings\}
La pestaña General contiene tu perfil, la configuración de la cuenta, las preferencias de visualización y la configuración de informes.
- **Profile**: Introduce tu nombre, apellidos y nombre de empresa. El nombre de empresa puede tener hasta 256 caracteres.
- **Account settings**: Consulta tu dirección de correo electrónico registrada y cambia tu contraseña.
- **Date & Time formats**: Elige cómo se muestran las fechas y horas en Adapty:
- **American format**: January 31, 2022 y hora en formato de 12 horas (AM/PM)
- **European format**: 31 January, 2022 y hora en formato de 24 horas (16:00)
- **Email reports**: Configura informes diarios, semanales o mensuales para una o todas tus apps. Recibe informes resumidos de todas las apps a la vez, o un informe detallado de cada app seleccionada.
## Suscripción y facturación \{#billing-info\}
La pestaña **Subscription & Billing** te permite gestionar tu información de pago y el acceso a funciones:
- Añadir o actualizar los datos de pago
- Revisar la información de facturación
- Adquirir funciones adicionales de pago
Más información sobre [funciones y precios](https://adapty.io/pricing).
## Miembros \{#members\}
Puedes gestionar los miembros de tu equipo desde la configuración de la cuenta. Para añadir miembros, invítalos por su correo electrónico y asígnales un rol.
Lee más sobre cómo gestionar los miembros del equipo y sus permisos de acceso [aquí](members-settings).
---
# File: members-settings
---
---
title: "Members"
description: "Gestiona la configuración y los permisos de los miembros en el dashboard de Adapty."
---
:::note
Esta página trata sobre los miembros del Adapty Dashboard
Si quieres otorgar distintos niveles de acceso a los usuarios de tu app, consulta [Nivel de acceso](access-level).
:::
El sistema de miembros del Adapty Dashboard te permite conceder diferentes niveles de acceso a Adapty y especificar las aplicaciones para cada miembro.
## Roles \{#roles\}
Los siguientes roles están disponibles para los miembros en el Adapty Dashboard:
| Rol | Acceso a Facturación | Añadir nuevos miembros | Modificar cualquier cosa | Acceso a todas las secciones |
|-------------|----------------------|------------------------|--------------------------|------------------------------|
| Owner | ✅ | ✅ | ✅ | ✅ |
| Admin | ❌ | ✅ | ✅ | ✅ |
| Developer | ❌ | ❌ | ✅ | ❌ |
| Viewer | ❌ | ❌ | ❌ | ✅ |
| Support | ❌ | ❌ | ❌ | ❌ |
| ASA manager | ❌ | ❌ | ❌ | ❌ |
- **Owner:** El Owner es el creador original de la cuenta de Adapty y tiene el nivel más alto de acceso y control. Los Owners tienen acceso completo a la facturación de Adapty, lo que les permite gestionar la información de pago y los planes de suscripción. Además, solo los Owners y los Admins pueden especificar el acceso a aplicaciones para los nuevos miembros. Solo puede haber un Owner por cuenta de Adapty.
- **Admin:** Los miembros con el rol Admin tienen acceso completo a las aplicaciones seleccionadas. Pueden realizar diversas tareas de gestión, como crear y modificar paywalls, realizar pruebas A/B, analizar métricas y gestionar miembros dentro de esas aplicaciones.
- **Developer:** Los miembros con el rol Developer tienen acceso completo a todas las entidades, excepto a las métricas y a los miembros de la cuenta. No pueden acceder a ninguna configuración de facturación. Este rol está pensado para quienes configuran paywalls, pruebas A/B y otras entidades e integran Adapty en tu app, pero no deben ver datos financieros.
- **Viewer:** Los miembros con el rol Viewer tienen acceso de solo lectura a las aplicaciones seleccionadas. Pueden ver la información, pero no pueden crear ni modificar paywalls, pruebas A/B u otras funciones, invitar a nuevos usuarios, crear nuevas apps ni cambiar la configuración de la app.
- **Support:** Los miembros con el rol Support solo tienen acceso a los perfiles de usuario en las aplicaciones seleccionadas. Sin embargo, no pueden añadir nuevos miembros ni acceder a ninguna otra sección de Adapty. Este rol es especialmente adecuado para equipos de soporte o personas que necesitan ayudar a los clientes con consultas o problemas relacionados con suscripciones.
- **ASA manager:** Los miembros con el rol ASA manager solo tienen acceso al dashboard de [Apple Ads Manager](adapty-ads-manager).
## Añadir un miembro \{#add-a-member\}
En Adapty puedes invitar hasta 256 miembros del equipo. Añadir nuevos miembros es gratuito.
:::note
Solo puedes invitar direcciones de correo electrónico que aún no estén registradas en Adapty. Si tu colega tiene una cuenta independiente, invita a una dirección de correo diferente o contacta con el soporte de Adapty para eliminar su cuenta existente.
:::
Para añadir un miembro del equipo:
1. Haz clic en **Account** en la parte superior derecha y abre la pestaña **Members**.
2. Haz clic en **Invite member**.
3. Introduce la dirección de correo electrónico del miembro.
4. Selecciona un [rol](#roles) de la lista.
5. Selecciona las apps a las que quieres dar acceso.
6. (Opcional) Activa **Always allow access to new apps** para conceder acceso automáticamente a las apps futuras.
7. Haz clic en **Save**.
## Transferir la propiedad de la cuenta \{#transfer-account-ownership\}
Si necesitas transferir la **propiedad completa de la cuenta**, contacta con nuestro equipo de soporte en [support@adapty.io](mailto:support@adapty.io).
Si necesitas transferir la **propiedad de la app**, consulta la [guía específica](transfer-apps) para más información.
---
# File: set-up-app-store-connect
---
---
title: "Configurar App Store Connect"
description: "Guía para desarrolladores primerizos sobre cómo inscribirse en el Apple Developer Program y configurar App Store Connect para las compras in-app."
---
Si estás **creando tu primera app para iOS**, debes configurar tu cuenta de Apple Developer y App Store Connect antes de integrar Adapty.
:::note
Si ya tienes una cuenta de Apple Developer y una app registrada en App Store Connect, puedes saltarte esta guía e ir directamente a [Integración inicial con el App Store](initial_ios).
:::
## Paso 1. Inscríbete en el Apple Developer Program \{#step-1-enroll-in-apple-developer-program\}
Para distribuir apps en el App Store y vender compras in-app, debes unirte al [Apple Developer Program](https://developer.apple.com/programs/).
### Elige el tipo de inscripción \{#choose-enrollment-type\}
Apple ofrece dos tipos de inscripción:
| | Individual | Organización |
|----------------------------------------|------------------------|------------------------------------|
| **Para quién es** | Desarrolladores solos | Empresas, equipos, organizaciones sin ánimo de lucro |
| **Requiere número D-U-N-S** | No | Sí |
| **Apps publicadas bajo** | Tu nombre personal | El nombre de tu organización |
| **Gestión de equipo** | No disponible | Disponible |
:::tip
Si te inscribes como organización, necesitas un **número D-U-N-S** — un identificador único de nueve dígitos emitido por Dun & Bradstreet. Puedes [comprobar si tu organización ya tiene uno](https://developer.apple.com/enroll/duns-lookup/) o solicitar uno nuevo — el enlace está al final de la página de búsqueda. Un número D-U-N-S puede tardar hasta 5 días hábiles en llegar.
:::
### Inscríbete \{#enroll\}
1. Ve a la [página de inscripción del Apple Developer Program](https://developer.apple.com/programs/enroll/).
2. Inicia sesión con tu Apple ID. Si no tienes uno, créalo primero.
3. Sigue los pasos según tu tipo de inscripción (individual u organización).
4. Paga la cuota anual.
Una vez que Apple procese tu inscripción, tendrás acceso a [App Store Connect](https://appstoreconnect.apple.com). La inscripción suele tardar hasta 48 horas. Para las organizaciones, puede tardar más si se requiere verificación del D-U-N-S.
## Paso 2. Configura tu app en App Store Connect \{#step-2-set-up-your-app-in-app-store-connect\}
Antes de poder vender compras in-app, completa la configuración inicial en App Store Connect. Esto incluye firmar acuerdos, añadir datos de pago y registrar tu app.
### Firma el Paid Applications Agreement \{#sign-the-paid-applications-agreement\}
Apple requiere que firmes el Paid Applications Agreement antes de poder vender en el App Store. Esto aplica tanto a apps de pago como a compras in-app en apps gratuitas.
1. Ve a la página **Business** en [App Store Connect](https://appstoreconnect.apple.com/business).
2. Encuentra el acuerdo **Paid Apps** y haz clic en **Review and Agree**.
3. Completa la información requerida:
- **Banking information**: Añade una cuenta bancaria donde Apple enviará tus ingresos.
- **Tax information**: Rellena los formularios fiscales de los países donde quieres vender.
- **Contact information**: Proporciona tus datos de contacto.
:::important
Debes completar las tres secciones (banking, tax, contact) para que el acuerdo entre en vigor. Hasta que el acuerdo esté activo, no podrás vender compras in-app.
:::
### Crea un Bundle ID \{#create-a-bundle-id\}
Un Bundle ID identifica tu app de forma única en todo el ecosistema de Apple. Lo necesitas para registrar tu app en App Store Connect y para configurar la integración con Adapty.
1. Abre el [portal de Apple Developer](https://developer.apple.com/account).
2. Ve a **Certificates, Identifiers & Profiles** → **Identifiers**.
3. Haz clic en **+** para registrar un nuevo identificador.
4. Selecciona **App IDs** y haz clic en **Continue**.
5. Selecciona **App** como tipo y haz clic en **Continue**.
6. Rellena los campos:
- **Description**: Un nombre para identificar este Bundle ID (p. ej., "My Subscription App").
- **Bundle ID**: Elige **Explicit** e introduce un identificador único en formato de dominio invertido (p. ej., `com.yourcompany.yourapp`).
7. En la sección **Capabilities**, desplázate hacia abajo y marca **In-App Purchase**.
8. Haz clic en **Continue** y luego en **Register**.
### Registra tu app en App Store Connect \{#register-your-app-in-app-store-connect\}
1. Ve a la página **Apps** en [App Store Connect](https://appstoreconnect.apple.com/apps).
2. Haz clic en **+** → **New App**.
3. Rellena los campos obligatorios:
- **Platforms**: Selecciona **iOS**.
- **Name**: El nombre de tu app tal como aparecerá en el App Store.
- **Primary language**: El idioma predeterminado para los metadatos de tu app.
- **Bundle ID**: Selecciona el Bundle ID que creaste en el paso anterior.
- **SKU**: Un identificador único para tu app (no visible para los usuarios). Por ejemplo, `my_subscription_app_2025`.
4. Haz clic en **Create**.
Tu app ya está registrada en App Store Connect y lista para la integración con Adapty.
## Qué hacer a continuación \{#whats-next\}
- [Integración inicial con el App Store](initial_ios): Conecta tu app del App Store a Adapty
- [Integración del SDK](quickstart-sdk): Integra el SDK de Adapty en el código de tu app
- [Pruebas en sandbox](test-purchases-in-sandbox): Prueba tus compras in-app antes del lanzamiento
- [Envía tu app iOS al App Store](submit-app-to-app-store): Sube tu build y envíala para revisión de Apple
- [App Store Small Business Program](app-store-small-business-program): Reduce tu comisión del App Store del 30% al 15%
---
# File: app-store-products
---
---
title: "Producto en App Store"
description: "Gestiona los productos de App Store de forma eficiente con las herramientas de suscripción de Adapty."
---
Esta página explica cómo crear un producto en App Store Connect. Aunque esta información no está directamente relacionada con la funcionalidad de Adapty, puede servirte de ayuda si tienes problemas al crear productos en tu cuenta de App Store Connect.
Para crear un producto que se vinculará a Adapty:
1. Abre **App Store Connect**. Ve a la sección [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) en el menú lateral izquierdo.
2. Si aún no has creado un grupo de suscripciones, haz clic en el botón **Create** bajo el título **Subscription Groups** para iniciar el proceso. Los [Subscription Groups](https://developer.apple.com/help/app-store-connect/manage-subscriptions/offer-auto-renewable-subscriptions) en App Store Connect organizan y gestionan tus productos, lo que permite a los usuarios cambiar entre diferentes ofertas sin problemas. Ten en cuenta que no es posible crear una suscripción fuera de un grupo.
3. En la ventana **Create Subscription Group** que se abre, introduce un nombre para el nuevo grupo de suscripciones en el campo **Reference Name**. El nombre de referencia es una etiqueta o identificador que tú defines para distinguir y gestionar los distintos grupos de suscripciones dentro de tu app.
El nombre de referencia no es visible para los usuarios; es exclusivamente para tu uso interno y organización. Te permite identificar y referirte fácilmente a grupos de suscripciones específicos al gestionarlos en la interfaz de App Store Connect. Esto resulta especialmente útil si tienes varias ofertas de suscripción o quieres categorizarlas de una forma que tenga sentido para la estructura de tu app.
4. Haz clic en el botón **Create** para confirmar la creación del grupo de suscripciones.
5. El grupo de suscripciones se crea y se abre. Ahora puedes crear suscripciones dentro del grupo. Haz clic en el botón **Create** bajo el título **Subscriptions**. Si añades una nueva suscripción a un grupo existente, haz clic en el botón **Plus** junto al título **Subscriptions**.
6. En la ventana **Create Subscription** que se abre, introduce el nombre en el campo **Reference Name** y el código único de la suscripción en el campo **Product ID**.
El Reference Name actúa como identificador exclusivo dentro de App Store Connect para tu suscripción in-app. No es visible para los usuarios en el App Store. Recomendamos usar una descripción clara y legible que represente con precisión la suscripción que quieres crear. Ten en cuenta que este nombre no puede superar los 64 caracteres.
El Product ID es un identificador alfanumérico único imprescindible para acceder a tu producto durante la fase de desarrollo y para sincronizarlo con Adapty. En el Product ID solo se permiten caracteres alfanuméricos, puntos y guiones bajos.
7. Haz clic en el botón **Create** para confirmar la creación de la suscripción.
8. La suscripción se crea y se abre. Ahora selecciona la duración de la suscripción en la lista **Subscription Duration**. Aunque la duración ya esté indicada en el nombre de la suscripción, recuerda completar el campo **Subscription Duration**.
9. Ahora toca configurar el precio de la suscripción. Para ello, haz clic en el botón **Add Subscription Price** bajo el título Subscription Prices. Es posible que tengas que desplazarte hacia abajo para encontrarlo.
10. En la ventana **Subscription Price** que se abre, selecciona el país base en la lista **Country or Region** y la moneda base en la lista **Price**. Más adelante, Apple calculará automáticamente los precios para los 175 países o regiones basándose en este precio base y los tipos de cambio más recientes.
11. Haz clic en el botón **Next**. En la ventana **Price by Country or Region** que se abre, verás los precios recalculados automáticamente para todos los países. Puedes modificarlos si lo deseas.
12. Tras actualizar los precios regionales, continúa haciendo clic en el botón **Next** en la parte inferior de la ventana.
13. En la ventana **Confirm Subscription Price?** que se abre, revisa detenidamente los precios finales. Si necesitas corregirlos, puedes hacer clic en el botón **Back** para volver a la ventana **Price by Country or Region** y actualizarlos. Cuando estés conforme con los precios, haz clic en el botón **Confirm**.
14. Después de cerrar la ventana **Confirm Subscription Price?**, recuerda hacer clic en el botón **Save** en la ventana de tu suscripción. Sin este paso, la suscripción no se creará y todos los datos introducidos se perderán.
Ten en cuenta que los pasos descritos hasta ahora se centran en configurar una suscripción de renovación automática. Sin embargo, si quieres configurar otros tipos de compras in-app, puedes hacer clic en la pestaña **In-App Purchases** en la barra lateral, en lugar de "Subscriptions". Esto te llevará a la sección donde puedes gestionar y crear distintos tipos de compras in-app.
### Añadir productos a Adapty \{#add-products-to-adapty\}
Una vez que hayas terminado de añadir tus compras in-app, suscripciones y ofertas en App Store Connect, el siguiente paso es [añadir estos productos a Adapty](create-product).
---
# File: apple-app-privacy
---
---
title: "Privacidad de aplicaciones de Apple"
description: "Entiende las políticas de privacidad de aplicaciones de Apple y su impacto en tu app de suscripciones."
---
Apple exige una declaración de privacidad para todas las apps nuevas y actualizaciones tanto en la sección **App Privacy** de App Store Connect como en el archivo de manifiesto de la app. Adapty es una dependencia de terceros en tu app, por lo que debes declarar cómo usas Adapty en relación con los datos de usuario.
## Manifiesto de privacidad de aplicaciones de Apple \{#apple-app-privacy-manifest\}
El [archivo de manifiesto de privacidad](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests), llamado `PrivacyInfo.xcprivacy`, describe qué datos privados utiliza tu app y por qué. Como propietario de la app, debes crear un archivo de manifiesto para ella. Además, si integras SDKs adicionales, asegúrate de que los archivos de manifiesto de aquellos incluidos en la lista de [SDKs que requieren manifiesto de privacidad y firma](https://developer.apple.com/support/third-party-SDK-requirements/) estén incluidos. Al compilar la app, Xcode tomará todos estos archivos de manifiesto y los fusionará en uno solo.
Aunque Adapty no figura en la lista de [SDKs que requieren manifiesto de privacidad y firma](https://developer.apple.com/support/third-party-SDK-requirements/), las versiones 2.10.2 y superiores del SDK de Adapty lo incluyen para tu comodidad. Asegúrate de actualizar el SDK para obtener el manifiesto.
Si bien Adapty no requiere que se incluya ningún dato en el archivo de manifiesto (también llamado informe de privacidad de la app), si usas el `customerUserId` de Adapty para el seguimiento, es necesario especificarlo en tu archivo de manifiesto de la siguiente manera:
1. Añade un diccionario al array `NSPrivacyCollectedDataTypes` en tu archivo de información de privacidad.
2. Añade las claves `NSPrivacyCollectedDataType`, `NSPrivacyCollectedDataTypeLinked` y `NSPrivacyCollectedDataTypeTracking` al diccionario.
3. Añade la cadena `NSPrivacyCollectedDataTypeUserID` (identificador del tipo de dato `UserID` en la [lista de categorías y tipos de datos que se deben declarar en el archivo de manifiesto](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests#Describe-the-data-your-app-or-third-party-SDK-collects)) para la clave `NSPrivacyCollectedDataType` en tu diccionario `NSPrivacyCollectedDataTypes`.
4. Añade `true` para las claves `NSPrivacyCollectedDataTypeTracking` y `NSPrivacyCollectedDataTypeLinked` en tu diccionario `NSPrivacyCollectedDataTypes`.
5. Usa la cadena `NSPrivacyCollectedDataTypePurposeProductPersonalization` como valor para la clave `NSPrivacyCollectedDataTypePurposes` en tu diccionario `NSPrivacyCollectedDataTypes`.
Si segmentas tus paywalls a audiencias con atributos personalizados, considera detenidamente qué atributos personalizados usas y si coinciden con las [categorías y tipos de datos que se deben declarar en el archivo de manifiesto](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests). En ese caso, repite los pasos anteriores para cada tipo de dato.
Una vez que hayas declarado todos los tipos y categorías de datos que recopilas, crea el informe de privacidad de tu app tal como se describe en la [documentación de Apple](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests#Create-your-apps-privacy-report).
## Declaración de privacidad de aplicaciones de Apple en App Store Connect \{#apple-app-privacy-disclosure-in-app-store-connect\}
1. En [App Store Connect](https://appstoreconnect.apple.com/), abre tu app y ve a **App Privacy**. Haz clic en **Get Started**.
2. Selecciona **Yes, we collect data from this app** y haz clic en **Next**.
### Tipos de datos \{#data-types\}
La tabla siguiente lista los tipos de datos que Apple exige declarar e indica cuáles necesita Adapty. **Esto solo cubre Adapty.** Si tu app recopila datos adicionales a través de otros SDKs o tu propio código, selecciona también esos tipos de datos.
✅ = Requerido por Adapty
👀 = Puede ser requerido \(consulta los detalles a continuación\)
❌ = No requerido por Adapty — selecciona si tu app recopila estos datos por otros medios
| Tipo de dato | Requerido | Nota |
|-----------------------------------------------------------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Identifiers | ✅ | Si identificas usuarios con un customerUserId, selecciona 'User ID'.
Adapty recopila IDFA, por lo que debes seleccionar 'Device ID'.
| | Purchases | ✅ | Adapty recopila el historial de compras de los usuarios. | | Contact Info, incluyendo nombre, número de teléfono o dirección email | 👀 | Requerido si pasas datos personales como nombre, número de teléfono o dirección de email usando el método **`updateProfile`**. | | Usage Data | 👀 | Si usas SDKs de analítica como Amplitude, Mixpanel, AppMetrica o Firebase, puede ser necesario. | | Location | ❌ | Adapty no recopila datos de ubicación precisa. Selecciona si tu app los recopila. | | Health & Fitness | ❌ | Adapty no recopila datos de salud ni actividad física. Selecciona si tu app los recopila. | | Sensitive Info | ❌ | Adapty no recopila información sensible. Selecciona si tu app la recopila. | | User Content | ❌ | Adapty no recopila contenido de usuario. Selecciona si tu app lo recopila. | | Diagnostics | ❌ | Adapty no recopila datos de diagnóstico. Selecciona si tu app los recopila. | | Browsing History | ❌ | Adapty no recopila el historial de navegación. Selecciona si tu app lo recopila. | | Search History | ❌ | Adapty no recopila el historial de búsqueda. Selecciona si tu app lo recopila. | | Contacts | ❌ | Adapty no recopila listas de contactos. Selecciona si tu app las recopila. | | Financial Info | ❌ | Adapty no recopila información financiera. Selecciona si tu app la recopila. | ### Tipos de datos requeridos \{#required-data-types\} #### Purchases \{#purchases\} Al usar Adapty, debes declarar que tu app recopila **Purchase History**.
#### Identifiers \{#identifiers\}
Al usar Adapty, debes declarar los siguientes identificadores:
- **Device ID** — Adapty recopila IDFA.
- **User ID** — requerido si identificas usuarios con **`customerUserId`**.
### Uso de datos \{#data-usage\}
Después de guardar los **Data types**, deberás indicar cómo se usan los datos:
1. Haz clic en **Set up purchase history** dentro del bloque **Purchases**.
2. Cuando Apple pregunte cómo se usan los datos del historial de compras, selecciona lo siguiente para Adapty:
- **Analytics** — Adapty usa el historial de compras para analíticas de ingresos, cohortes y métricas.
- **Product Personalization** — Adapty usa los datos de compras para la segmentación de audiencias y la segmentación de paywalls.
- **App Functionality** — Adapty valida las compras, gestiona los niveles de acceso y hace seguimiento del estado de la suscripción.
Selecciona propósitos adicionales si tu app usa los datos de compras de otras formas (por ejemplo, si envías eventos de compra a plataformas publicitarias mediante integraciones de Adapty).
3. Haz clic en **Next**.
4. Para **Device ID** y **User ID** (si se usa):
1. Haz clic en **Set up user/device ID** dentro del bloque **User/Device ID**.
2. Cuando Apple pregunte cómo se usan los datos de identificadores, selecciona lo siguiente para Adapty:
- **App Functionality** — Adapty usa los identificadores para gestionar perfiles de usuario, vincular compras y hacer seguimiento de los niveles de acceso.
Si envías datos de atribución a plataformas de terceros mediante integraciones de Adapty (como AppsFlyer o Adjust), selecciona también **Third-Party Advertising**. Selecciona propósitos adicionales si tu app usa los identificadores de otras formas.
5. Haz clic en **Next**.
---
# File: apple-family-sharing
---
---
title: "Apple Family Sharing"
description: "Habilita Apple Family Sharing en Adapty para admitir suscripciones compartidas."
---
La función de Family Sharing de Apple permite distribuir compras in-app entre los miembros de una familia, lo que ofrece a los usuarios de apps orientadas a grupos —como servicios de streaming de vídeo o apps para niños— una forma cómoda de compartir suscripciones sin tener que compartir su Apple ID. Al permitir que hasta cinco miembros de la familia usen una suscripción, [Family Sharing](https://developer.apple.com/documentation/storekit/supporting-family-sharing-in-your-app) puede mejorar la fidelización y el engagement de los usuarios en tu app.
En esta guía, explicamos cómo activar el uso compartido familiar para suscripciones y cómo Adapty gestiona las compras compartidas dentro de una familia.
Para empezar a habilitar Family Sharing para un producto concreto, ve a [App Store Connect](https://appstoreconnect.apple.com/). Family Sharing está desactivado por defecto tanto para las compras in-app nuevas como para las existentes, por lo que es necesario habilitarlo individualmente para cada compra in-app. Puedes hacerlo fácilmente accediendo a la **página de tu app**, navegando a la página de la compra in-app correspondiente y seleccionando la opción **Turn On** en la sección Family Sharing.
Ten en cuenta que una vez que actives Family Sharing para un producto, **no podrás desactivarlo**, ya que esto interrumpiría la experiencia de los usuarios que ya han compartido la suscripción con sus familiares.
Además, ten en cuenta que solo los productos no consumibles y las suscripciones pueden compartirse.
En el modal que aparece, haz clic en el botón **Confirm** para finalizar el proceso. Tras hacerlo, la sección Family Sharing debería actualizarse y mostrar el mensaje "This subscription can be shared by everyone in a family group." Esto confirma que la suscripción ya está habilitada para Family Sharing y puede compartirse con hasta cinco miembros de la familia.
Adapty facilita la compatibilidad con Family Sharing sin ningún esfuerzo adicional. Solo tienes que [configurar tus productos](app-store-products) desde App Store y, una vez que lo **actives** desde App Store Connect, **Family Sharing** estará disponible automáticamente en **Adapty** y se recibirá como un evento en el webhook.
:::note
Ten en cuenta que Family Sharing no es compatible con el entorno sandbox.
:::
Ten en cuenta que cuando un usuario adquiere una suscripción y la comparte con sus familiares, puede haber un **retraso de hasta una hora** antes de que esté disponible para ellos. Apple diseñó este retraso para dar al usuario tiempo de cambiar de opinión y retirar el acceso si lo desea. Sin embargo, si la suscripción se renueva, los familiares reciben acceso sin ningún retraso.
Cuando un usuario compra un producto in-app de Family Sharing, la transacción aparecerá en su recibo como de costumbre, pero con un nuevo campo llamado `in_app_ownership_type` con el valor `PURCHASED.` Además, se creará una nueva transacción para todos los miembros de la familia, que tendrá un `web_order_line_item_id` y un `original_transaction_id` diferentes a los de la compra original, así como un campo `in_app_ownership_type` con el valor `FAMILY_SHARED.`
Para garantizar un cálculo de ingresos preciso, solo se contabilizan en los análisis de Adapty las transacciones con un `in_app_ownership_type` de `PURCHASED`. Las transacciones `FAMILY_SHARED` quedan excluidas de las métricas de ingresos y conversión.
**Eventos enviados para transacciones de Family Sharing.**
Las transacciones `FAMILY_SHARED` solo activan el evento **Access level updated**. Los eventos de suscripción por producto no se activan para los miembros de la familia.
| Evento | `FAMILY_SHARED` | `PURCHASED` |
| --- | --- | --- |
| **Nivel de acceso actualizado** | Sí | Sí |
| **Suscripción iniciada** | No | Sí |
| **Prueba iniciada** | No | Sí |
| **Suscripción renovada** | No | Sí |
| **Suscripción expirada** | No | Sí |
| **Suscripción reembolsada** | No | Sí |
| **Problema de facturación detectado** | No | Sí |
Si tu analítica downstream se basa en **Suscripción iniciada**, los miembros familiares no aparecerán ahí. Usa **Nivel de acceso actualizado** para detectar miembros familiares activos.
Para identificar a los demás miembros de la familia en Adapty, puedes encontrarlos en los detalles del evento. Primero, localiza la transacción de compra familiar original. Luego, examina los detalles del evento para esa transacción, buscando específicamente el mismo producto, fecha de compra y fecha de vencimiento. Analizando los detalles del evento, puedes identificar otras transacciones de membresía familiar asociadas a la compra original.
---
# File: app-store-small-business-program
---
---
title: "App Store Small Business Program"
description: "Comprende el Small Business Program de Apple, su impacto en tus ingresos y los análisis de Adapty"
---
:::link
Para el programa equivalente en Play Store, consulta [Google Reduced Service Fee](google-reduced-service-fee).
:::
Las organizaciones que reciben hasta 1 millón de USD en ingresos anuales del App Store pueden participar en el [programa Small Business](https://developer.apple.com/app-store/small-business-program/) de Apple. Si te inscribes, la comisión estándar del 30% se reduce al **15%**.
Los miembros del programa deben **cambiar su configuración en Adapty** para garantizar cálculos de ingresos correctos y el manejo adecuado de los eventos de integración.
Este artículo describe:
* [Cómo configurar Adapty](#configure-adapty) si tu app está inscrita en el Small Business Program
* [Cómo inscribirte en el programa](#apply-for-the-program) si quieres reducir tu comisión del store
## Configurar Adapty \{#configure-adapty\}
Adapty puede aplicar la comisión reducida a tus [análisis](analytics) y [eventos de integración](analytics-integration). Para activarlo, especifica tu estado en el Small Business Program por app.
:::warning
Configura tu estado en el SBP en Adapty **en cuanto recibas la aprobación**. Los cambios tardíos no pueden reescribir los eventos de webhook ya entregados ([detalles](#retroactive-setting-changes)).
:::
1. Abre [**App Settings** → **General**](https://app.adapty.io/account)
2. Busca la sección **Small Business Program**.
3. Haz clic en **Add period**.
4. Selecciona la fecha de inicio de la membresía.
5. Selecciona una fecha de fin, o activa la casilla **At the current moment** para extender este estado indefinidamente. Si en el futuro [pierdes la elegibilidad](#losing-eligibility), puedes modificar la fecha de fin.
6. Haz clic en **Apply**.
Si tu organización sigue siendo elegible para el programa, la membresía se renueva automáticamente al siguiente año natural. Sin embargo, el estado de membresía solo se aplica **al rango de fechas que especifiques**.
* Haz clic en **Add period** para añadir un nuevo período de membresía.
* Para extender este estado indefinidamente, activa la casilla **At the current moment**.
Para verificar tu configuración, abre el [gráfico de Revenue](revenue) y selecciona **Proceeds after store commission**. Confirma que los ingresos mostrados reflejan la comisión reducida.
## Inscribirse en el programa \{#apply-for-the-program\}
### Requisitos de elegibilidad \{#eligibility-requirements\}
Apple determina la elegibilidad para el SBP en función de tus **ingresos anuales** — las ventas del año natural anterior **después** de la comisión del store e impuestos.
Para ser elegible, los ingresos anuales de tu organización y sus
2. Haz clic en el botón **Create subscription**.
3. En la ventana **Create subscription** que se abre, introduce el ID de la suscripción en el campo **Product ID** y el nombre de la suscripción en el campo **Name**.
El ID del producto debe ser único, comenzar con un número o letra minúscula, y puede contener guiones bajos (\_) y puntos (.). Se utiliza para acceder a tu producto durante el desarrollo y sincronizarlo con Adapty. Una vez que se asigna un Product ID a un producto en Google Play Console, no puede reutilizarse en ninguna otra app, incluso si el producto se elimina.
Al elegir el ID del producto, es recomendable seguir un formato estandarizado. Te recomendamos usar un enfoque más conciso y nombrar el producto `
3. Una vez que se abran los detalles de la suscripción, haz clic en el botón **Add base plan** que aparece bajo el título **Base plans and offers**. Es posible que tengas que desplazarte hacia abajo para encontrarlo.
4. En la ventana **Add base plan** que se abre, introduce un identificador único para el plan base en el campo **Plan ID**. Debe comenzar con un número o letra minúscula, y puede contener números (0-9), letras minúsculas (a-z) y guiones (-). Completa también los campos obligatorios.
5. Especifica los precios por región.
6. Haz clic en el botón **Save** para finalizar la configuración.
7. Haz clic en el botón **Activate** para activar el plan base.
Ten en cuenta que los productos de suscripción solo pueden tener un único plan base con duración y tipo de renovación consistentes en Adapty.
### Productos de respaldo \{#fallback-products\}
:::warning
Compatibilidad con planes base no retrocompatibles
Las versiones antiguas de los SDK de Adapty no son compatibles con las funciones de Google Billing Library v5+, concretamente con múltiples planes base por producto de suscripción y ofertas. Solo los planes base marcados como **[backwards compatible](https://support.google.com/googleplay/android-developer/answer/12124625?hl=en#backwards_compatible)** en Google Play Console son accesibles con estas versiones del SDK. Ten en cuenta que solo un plan base por suscripción puede marcarse como retrocompatible.
:::
Para aprovechar al máximo las configuraciones y funciones mejoradas de suscripciones de Google en Adapty, ofrecemos la posibilidad de configurar un producto de respaldo retrocompatible. Este producto de respaldo se utiliza exclusivamente para apps que usan versiones antiguas del SDK de Adapty. Al crear productos de Google Play, ahora tienes la opción de indicar si el producto debe marcarse como retrocompatible en Play Console. Adapty utiliza esta información para determinar si el producto puede ser comprado por versiones antiguas del SDK (versiones 2.5 e inferiores).
Supongamos que tienes una suscripción llamada `subscription.premium` que ofrece dos planes base: semanal (retrocompatible) y mensual. Si añades el producto `subscription.premium:weekly` a Adapty, no necesitas indicar un producto retrocompatible. Sin embargo, en el caso del producto `subscription.premium:monthly`, deberás especificar un producto retrocompatible. No hacerlo podría provocar una compra no deseada del producto `subscription.premium:weekly` en la biblioteca de facturación 4 de Google. Para resolver este escenario, debes crear un producto separado donde el plan base también sea mensual y esté marcado como retrocompatible. Esto garantiza que los usuarios que seleccionen la opción `subscription.premium:monthly` sean facturados correctamente con la frecuencia prevista.
## Añadir productos a Adapty \{#add-products-to-adapty\}
Una vez que hayas completado la incorporación de tus compras in-app, suscripciones y ofertas en App Store Connect, el siguiente paso es [añadir estos productos a Adapty](create-product).
---
# File: google-play-data-safety
---
---
title: "Seguridad de datos de Google Play"
description: "Garantiza el cumplimiento de las políticas de seguridad de datos de Google Play en Adapty."
---
La sección de seguridad de datos disponible en Google Play ofrece a los desarrolladores un método sencillo para informar a los usuarios sobre los datos que su app recopila o comparte, así como destacar las medidas críticas de privacidad y seguridad. Esta información permite a los usuarios tomar decisiones más informadas al elegir qué apps descargar y usar.
Aquí tienes una guía breve sobre los datos que Adapty recopila para ayudarte a proporcionar la información requerida a Google Play.
## Recopilación y seguridad de datos \{#data-collection-and-security\}
**¿Tu app recopila o comparte alguno de los tipos de datos de usuario requeridos?**
Selecciona 'Sí', ya que Adapty recopila el historial de compras del cliente.
**¿Todos los datos de usuario recopilados por tu app están cifrados en tránsito?**
Selecciona 'Sí', ya que Adapty cifra los datos en tránsito.
**¿Ofreces a los usuarios una forma de solicitar la eliminación de sus datos?**
Si seleccionas 'Sí', asegúrate de que tus clientes tengan una forma de contactar con tu equipo de soporte para solicitar la eliminación de sus datos. Podrás eliminar al cliente directamente desde el Adapty Dashboard o mediante la API REST.
## Tipos de datos \{#data-types\}
A continuación encontrarás la lista de tipos de datos que Google requiere para el reporte, junto con la especificación de si Adapty recopila cada tipo de dato en particular.
| Tipo de dato | Detalles |
| :----------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Ubicación | Adapty no lo recopila |
| Salud y fitness | Adapty no lo recopila |
| Fotos y vídeos | Adapty no lo recopila |
| Archivos y documentos | Adapty no lo recopila |
| Calendario | Adapty no lo recopila |
| Contactos | Adapty no lo recopila |
| Contenido del usuario | Adapty no lo recopila |
| Historial de navegación | Adapty no lo recopila |
| Historial de búsqueda | Adapty no lo recopila |
| Información y rendimiento de la app | Adapty no lo recopila |
| Navegación web | Adapty no lo recopila |
| Información de contacto | Adapty no lo recopila |
| Información financiera | Adapty recopila el historial de compras de los usuarios |
| Información personal e identificadores | Adapty recopila el ID de usuario y otra información de contacto identificable, como nombre, dirección de correo electrónico, número de teléfono, etc., si los pasas explícitamente al SDK de Adapty. |
| Identificadores de dispositivo y otros | Adapty recopila datos sobre el ID del dispositivo. |
## Uso y tratamiento de datos \{#data-usage-and-handling\}
### IDs de usuario \{#user-ids\}
**1. ¿Estos datos se recopilan, se comparten o ambas cosas?**
Adapty recopila estos datos. Si usas integraciones entre Adapty y terceros que no se consideran proveedores de servicios, puede que también tengas que indicar "Compartido" aquí.
**2. ¿Estos datos se procesan de forma efímera?**
Selecciona 'No'.
**3. ¿Estos datos son obligatorios para tu app o los usuarios pueden elegir si se recopilan?**
La recopilación de estos datos es obligatoria y no se puede desactivar.
**4. ¿Por qué se recopilan estos datos de usuario? / ¿Por qué se comparten estos datos de usuario?**
Marca las casillas 'Funcionalidad de la app' y 'Análisis'.
### Información financiera \{#financial-info\}
Si usas Adapty, debes declarar que tu app recopila información sobre el 'Historial de compras' en la sección de tipos de datos de Google Play Console.
### Identificadores de dispositivo u otros \{#device-or-other-ids\}
## Pasos siguientes \{#next-steps\}
Una vez que hayas completado las selecciones de seguridad de datos, Google mostrará una vista previa de la sección de privacidad de tu app. Si has seleccionado "Información financiera" e "Identificadores de dispositivo u otros" como se mencionó anteriormente, la información de privacidad debería aparecer de forma similar al siguiente ejemplo.
Si estás listo para enviar tu app a revisión, consulta nuestro documento [Lista de verificación para el lanzamiento](release-checklist) para obtener más orientación sobre cómo preparar tu app para el envío.
---
# File: google-reduced-service-fee
---
---
title: "Tarifa de Servicio Reducida de Google"
description: "Comprende la Tarifa de Servicio Reducida de Google, su impacto en tus ingresos y los análisis de Adapty"
---
:::link
Para el programa equivalente en App Store, consulta el [Programa para Pequeñas Empresas de App Store](app-store-small-business-program).
:::
El [programa de Tarifa de Servicio Reducida](https://support.google.com/googleplay/android-developer/answer/112622?hl=en) de Google Play reduce la comisión sobre tu primer millón de USD en ganancias anuales del 30% al **15%**. Las ganancias que superen el millón de USD en el mismo año calendario se cobran a la tarifa estándar del 30%.
:::note
Desde el 1 de enero de 2022, Google cobra el 15% en todas las suscripciones de renovación automática independientemente de este programa. La Tarifa de Servicio Reducida beneficia principalmente a las compras in-app que no son suscripciones y a las apps de pago.
:::
Los miembros del programa deben **cambiar su configuración en Adapty** para garantizar cálculos de ingresos correctos y el manejo adecuado de los eventos de integración.
Este artículo describe:
* [Cómo configurar Adapty](#configure-adapty) si tu app está inscrita en el programa de Tarifa de Servicio Reducida
* [Cómo inscribirse en el programa](#enroll-in-the-program) si quieres reducir tu comisión del store
## Configurar Adapty \{#configure-adapty\}
Adapty puede aplicar la tarifa de comisión reducida a tus [análisis](analytics) y [eventos de integración](analytics-integration). Para habilitarlo, especifica tu estado en la Tarifa de Servicio Reducida para cada app por separado.
:::warning
Configura tu estado de Tarifa de Servicio Reducida en Adapty **en cuanto te inscribas**. Los cambios posteriores no pueden reescribir los eventos de webhook ya entregados ([detalles](#retroactive-setting-changes)).
:::
1. Abre [**App Settings** → **General**](https://app.adapty.io/account).
2. Busca la sección **Reduced Service Fee**.
3. Haz clic en **Add period**.
4. Selecciona la fecha de inicio de la membresía.
5. Selecciona una fecha de fin, o activa la casilla **At the current moment** para extender este estado indefinidamente. Si tus [ganancias anuales superan el millón de USD](#exceeding-the-threshold), puedes modificar la fecha de fin.
6. Haz clic en **Apply**.
El estado de membresía solo se aplica **al rango de fechas que especifiques**. El programa se reinicia cada año calendario.
* Haz clic en **Add period** para añadir un nuevo período de membresía.
* Para extender este estado indefinidamente, activa la casilla **At the current moment**.
Para verificar tu configuración, abre el [gráfico de Ingresos](revenue) y selecciona **Proceeds after store commission**. Confirma que los ingresos mostrados reflejan la tarifa de comisión reducida.
## Inscribirse en el programa \{#enroll-in-the-program\}
### Requisitos de elegibilidad \{#eligibility-requirements\}
Google determina la elegibilidad en función de tus **ganancias anuales** en todas las cuentas de tu
## ¿Qué es el Refund Saver? \{#what-is-the-refund-saver\}
Cuando los usuarios solicitan reembolsos en la App Store, Apple evalúa los datos de consumo relacionados con la compra in-app para decidir si aprobar o denegar la solicitud. Por ejemplo, si un usuario compra una suscripción, la usa intensamente durante la mayor parte del período de suscripción y luego solicita un reembolso, es probable que Apple lo apruebe a menos que aportes datos de uso que demuestren que la suscripción se consumió activamente. Apple [anima a los desarrolladores](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information-v1) a compartir estos datos para garantizar que las decisiones sobre reembolsos sean justas.
El Refund Saver de Adapty automatiza este proceso cumpliendo plenamente con las [directrices](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information-v1) de la App Store.
Así es como funciona:
- Cuando un usuario inicia una solicitud de reembolso, la App Store envía una notificación pidiendo detalles sobre la transacción y el uso.
- Si ignoras o demoras la respuesta, es probable que Apple apruebe el reembolso por defecto.
- Adapty procesa automáticamente estas notificaciones y proporciona a Apple los datos necesarios.
Esta automatización reduce la probabilidad de reembolsos innecesarios, ahorrando tiempo y protegiendo tus ingresos.
:::info
Con el Refund Saver puedes recuperar hasta el 40% de los ingresos procedentes de solicitudes de reembolso.
:::
## Requisitos para usar el Refund Saver \{#requirements-to-use-refund-saver\}
Para usar esta función, asegúrate de cumplir los siguientes requisitos previos:
1. **Actualiza tu Política de Privacidad en App Store Connect:**
La Política de Privacidad de tu app debe revelar la recopilación y el uso de datos de consumo. Esto garantiza que los usuarios entiendan las prácticas de privacidad de tu app antes de descargarla. Consulta los [detalles de privacidad de apps de Apple](https://developer.apple.com/app-store/app-privacy-details/) como referencia.
2. **Obtén el consentimiento del usuario para compartir datos en tu app:**
Apple exige que obtengas un consentimiento válido del usuario antes de compartir sus datos personales con Apple. Como desarrollador, eres responsable de obtener ese consentimiento, ya que serás tú quien comparta los datos del usuario con Apple. Consulta las [directrices](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information) de Apple para más detalles.
3. **Activa las notificaciones de servidor V2:**
Asegúrate de que las notificaciones de servidor V2 estén activadas en tu cuenta de Apple Developer y configuradas correctamente en Adapty, ya que las notificaciones V1 no son compatibles. Si aún no las has activado, sigue los pasos de la guía [Activar notificaciones de servidor de App Store](enable-app-store-server-notifications).
## Activar el Refund Saver \{#turn-on-refund-saver\}
1. Abre la sección [Refund Saver](https://app.adapty.io/refund-saver) en el Adapty Dashboard.
2. Haz clic en **Turn on Refund Saver** para activar la función.
## Configurar el comportamiento predeterminado de reembolso \{#set-a-default-refund-behavior\}
Apple permite a los desarrolladores especificar un resultado preferido para cada solicitud de reembolso al responderla. El propósito de esta configuración es encontrar el equilibrio adecuado entre rechazar y aceptar solicitudes de reembolso, de modo que solo se concedan los reembolsos justos. Ten en cuenta que esta configuración solo sirve para influir en el resultado, pero la decisión final sigue siendo de Apple.
Adapty permite configurar esta preferencia, aunque se usará el mismo valor para todas las solicitudes de reembolso.
1. Para cambiar tu preferencia, haz clic en **Edit refund preference**.
2. En la ventana **Edit refund preference**, elige tu opción de **Default refund request preference**:
| Opción | Descripción |
| ----------------------------------------------------- | ------------------------------------------------------------ |
| Always decline | (predeterminado) Esta es la opción predeterminada y suele dar los mejores resultados para minimizar los reembolsos. |
| Decline first refund request, grant all next | Para cada transacción que encuentre el Refund Saver, inicialmente pedirá a Apple que rechace el reembolso. Sin embargo, si la misma transacción vuelve a aparecer, el Refund Saver siempre recomendará conceder el reembolso. Este enfoque ayuda a minimizar la frustración de los usuarios por rechazos injustos: simplemente pueden volver a solicitar el reembolso y probablemente lo recibirán. |
| Always refund | Sugiere que Apple apruebe todas las solicitudes de reembolso. |
| No preference | No proporciona ninguna recomendación a Apple. En este caso, Apple determinará el resultado del reembolso basándose en sus políticas internas y el historial del usuario, sin ninguna influencia de tu configuración. Esta opción ofrece el enfoque más neutral. |
## Configurar el comportamiento de reembolso para un usuario específico en el dashboard \{#set-refund-behavior-for-a-specific-user-in-the-dashboard\}
Aunque hayas configurado el comportamiento predeterminado del Refund Saver para toda la app, es posible que quieras establecer preferencias individuales para usuarios concretos. En el Adapty Dashboard, puedes hacerlo desde el perfil del usuario. Usa la sección **Refund Saver Preferences** que se encuentra en la parte inferior izquierda.
## Configurar el comportamiento de reembolso para un usuario específico en el SDK \{#set-refund-behavior-for-a-specific-user-in-the-sdk\}
Puedes establecer la preferencia de reembolso en el código de tu app de forma individual para cada instalación según las acciones del usuario. Usa el fragmento de código siguiente para configurar la preferencia:
| Opción | Descripción | | ------- | ------------------------------------------------------------ | | Opt-out | (predeterminado) Si Adapty no conoce el estado de consentimiento del usuario, asume que el consentimiento **fue dado** y el Refund Saver **compartirá** los datos relacionados con el reembolso con Apple. | | Opt-in | Si Adapty no conoce el estado de consentimiento del usuario, asume que el consentimiento **no fue dado** y el Refund Saver **no compartirá** ningún dato con Apple. Este es el enfoque recomendado por Apple. | ## Actualizar el consentimiento del usuario en el SDK \{#update-user-consent-in-the-sdk\} Para indicarle a Adapty si un usuario específico ha dado su consentimiento, usa el método `updateCollectingRefundDataConsent`:
:::note
También puedes usar la API del lado del servidor para [obtener las preferencias individuales de reembolso y uso compartido](api-adapty/operations/getRefundSaverSettings).
:::
## Limitaciones \{#limitations\}
- **Solo para la App Store de Apple:** El Refund Saver solo está disponible para solicitudes de reembolso realizadas en la App Store de Apple. Google Play no ofrece análisis de datos de consumo para reembolsos. Las decisiones de reembolso en Google Play se basan únicamente en las políticas de Google y en la información proporcionada por el usuario.
- **Solo para suscripciones de renovación automática y consumibles:** El Refund Saver funciona con suscripciones de renovación automática y compras in-app consumibles, ya que Apple solo proporciona la información necesaria para estos tipos de compra.
- **Requiere notificaciones de servidor V2:** El Refund Saver no es compatible con las notificaciones de servidor de App Store V1. Si actualmente usas V1 en Adapty, debes cambiar a V2; consulta la guía [Enviar notificaciones de servidor de App Store a Adapty](enable-app-store-server-notifications) para más detalles. Cambiar a V2 también mejorará tu análisis en Adapty al proporcionar datos más precisos y completos.
---
# File: meta-create-campaign
---
---
title: "Publicita tu app en Meta Ads"
---
En esta guía paso a paso aprenderás cómo crear y configurar anuncios para tu app en Meta, para optimizarlos y hacer un seguimiento de su rendimiento fácilmente.
## Cómo se estructuran los anuncios en Meta \{#how-ads-in-meta-are-structured\}
Al anunciarte en Meta Ads, necesitas configurar tres niveles jerárquicos:
- **Campaign**: Las campañas definen tus objetivos publicitarios.
- **Ad set**: Los conjuntos de anuncios especifican tu audiencia objetivo y los placements, determinando dónde y a quién se mostrarán tus anuncios. Cada campaña puede contener varios conjuntos de anuncios.
- **Ads**: Los anuncios son los creativos reales que los usuarios ven e interactúan con ellos. Cada conjunto de anuncios puede contener varios anuncios; sin embargo, se recomienda limitarlo a no más de cinco anuncios por conjunto para un rendimiento óptimo.
## Paso 1. Crea una cuenta en Meta Ads Manager \{#step-1-create-meta-ads-manager-account\}
Para empezar con Meta Ads, necesitas tener una página de Facebook Business, ya que no puedes publicar anuncios desde tu cuenta personal.
Por lo tanto, debes vincular tu página de empresa a tu portfolio de negocio de Meta Ads:
1. Ve a [business.facebook.com](https://business.facebook.com/). Si todavía no tienes una página de empresa en el portfolio de negocio, tendrás que añadirla. Haz clic en **Go to settings**.
2. Ve a **Account > Pages** en la barra lateral izquierda. Haz clic en **Add** y selecciona **Add an existing Facebook page** o **Create a new Facebook page**. Consulta la [guía para crear una página de empresa](https://www.facebook.com/business/help/473994396650734) si todavía no tienes una.
3. Opcionalmente, vincula tu cuenta de Instagram en la página **Account > Instagram accounts** dentro de los ajustes.
Una vez conectada tu página de empresa, ya puedes continuar.
## Paso 2. Añade el píxel de Meta \{#step-2-add-meta-pixel\}
Necesitarás un píxel de Meta para conectar los datos de tu campaña con los ingresos y obtener mejores resultados.
Antes de conectar datos y crear un píxel, necesitarás:
- Una página de empresa: añádela a tu portfolio de negocio en [**Settings > Accounts > Pages**](https://business.facebook.com/latest/settings/pages)
- Una cuenta de Business Manager: debes tener control total sobre el portfolio de negocio
- Un correo electrónico empresarial: configúralo en [**Settings > Business info**](https://business.facebook.com/latest/settings/business_info)
- Una cuenta publicitaria: añádela a tu portfolio de negocio en [**Settings > Accounts > Ad accounts**](https://business.facebook.com/latest/settings/ad_accounts)
Cuando estés listo, crea un píxel:
1. Ve al [**Events Manager**](https://www.facebook.com/events_manager2). Haz clic en **Connect data**.
2. Selecciona **Web** como tipo de fuente de datos.
3. Dale un nombre a tu dataset y haz clic en **Create**.
4. Para [Adapty User Acquisition](adapty-user-acquisition), no necesitarás completar la instalación completa del píxel. Por lo tanto, cuando te pregunten sobre la integración, puedes hacer clic en **x** en la ventana de configuración y tu píxel seguirá apareciendo en la lista tras actualizar la página.
5. Cuando tu dataset aparezca en la lista, puedes continuar con la creación de una campaña.
## Paso 3. Crea una campaña \{#step-3-create-campaign\}
Para crear una campaña en Meta Ads Manager:
1. Ve al [Meta Ads Manager](https://adsmanager.facebook.com/adsmanager/manage). En la pestaña **Campaign**, haz clic en **Create**.
2. Selecciona **Sales** como objetivo de la campaña y haz clic en **Continue**.
3. Ponle nombre a tu campaña en la sección **Campaign name**.
4. En la sección **Budget**, dentro de **Budget strategy**, selecciona cómo quieres controlar el presupuesto:
- **Campaign budget**: La opción más sencilla si no tienes claro qué oportunidades funcionarán mejor. Si la seleccionas, Meta Ads detectará automáticamente los mejores resultados para asignar más presupuesto a los conjuntos de anuncios con mejor rendimiento.
A continuación, elige entre presupuesto **Daily** o **Lifetime** e introduce el límite en tu moneda. El presupuesto **Daily** te da más flexibilidad mientras estás aprendiendo, para que puedas empezar con cantidades pequeñas e irlas ajustando sobre la marcha. También puedes seleccionar **Schedule budget increase** y establecer reglas para aumentar automáticamente el presupuesto por un importe o porcentaje determinado.
- **Ad set budget**: Selecciona esta opción si quieres definir manualmente qué audiencias recibirán más o menos presupuesto de la campaña. Si no tienes muy claro cómo hacerlo, puedes seleccionar **Share some of your budget with other ad sets** para permitir que Meta ajuste automáticamente los presupuestos de los conjuntos de anuncios hasta en un 20% si esto beneficia el rendimiento del anuncio.
5. En **Campaign bid strategy**, selecciona la mejor opción para tus objetivos:
- **Highest volume (default)**: La opción más sencilla para empezar. Si la seleccionas, dejas que Meta optimice el coste por clic para obtener los mejores resultados con tu presupuesto.
- **Cost per result goal**: Apunta a un coste por resultado concreto si ya conoces tus referencias.
- **Bid cap**: Establece el coste máximo que estás dispuesto a pujar.
6. Adapty te permite llevar a cabo [pruebas A/B](ab-tests) completas. Sin embargo, también puedes activar pruebas A/B en Meta Ads si lo necesitas. Lee más sobre las pruebas A/B en Meta Ads Manager [aquí](https://www.facebook.com/business/help/1159714227408868).
7. Ahora toca añadir el primer conjunto de anuncios a tu campaña. Haz clic en **Next** para continuar.
## Paso 4. Crea un conjunto de anuncios \{#step-4-create-ad-set\}
Para crear un conjunto de anuncios:
1. Dale un nombre a tu conjunto de anuncios en el campo **Ad set name**.
2. En el desplegable **Conversion location**, selecciona **Website**.
3. En el campo **Performance goal**, selecciona **Maximize number of landing page views** si tienes una landing page, o **Maximize number of link clicks** si usas un enlace inteligente que dirige a los usuarios directamente a la store.
4. En el campo **Dataset**, selecciona el dataset que creaste en el [Paso 2](#step-2-add-meta-pixel).
5. Selecciona un **Conversion event**. En nuestro caso, probablemente será **Purchase** o **Start trial**. No te preocupes si ves un aviso indicando que tu dataset aún no tiene eventos: simplemente significa que el dataset es nuevo.
6. Si al configurar la campaña seleccionaste **Ad set budget**, elige entre presupuesto **Daily** o **Lifetime** e introduce el límite en tu moneda. El presupuesto **Daily** te da más flexibilidad mientras estás aprendiendo, para que puedas empezar con cantidades pequeñas e irlas ajustando sobre la marcha.
Establece las fechas de inicio y, si aplica, de fin del conjunto de anuncios. Por ejemplo, si quieres publicitar una oferta promocional en tu app, es fundamental que el período del conjunto de anuncios coincida con el de la oferta.
7. En la sección **Audience controls**, configura los ajustes de audiencia:
- **Location**: Las ubicaciones pueden ser tan amplias o específicas como necesites. Puedes limitar las **Locations** en el conjunto de anuncios para adaptarte a las características de cada región en tus anuncios.
- **Minimum age**: Selecciona la edad mínima de los usuarios que verán tu anuncio. Para algunos anuncios puede ser un requisito legal. No puedes seleccionar una edad mínima inferior a 18 años a nivel global ni inferior a 20 en Tailandia.
- **Language**: Configura el **Language** solo si no es el idioma más común en los países seleccionados. Por ejemplo, no necesitarás seleccionar **English** en Estados Unidos, pero si te diriges a personas hispanohablantes que viven allí, puede que quieras seleccionar **Spanish**.
8. Por defecto, Meta encuentra automáticamente grupos de personas más pequeños a los que tu anuncio puede resultar relevante. Sin embargo, si añades una sugerencia de audiencia, puedes orientar a Meta hacia las personas que crees que tienen más probabilidades de responder. En la sección **Advantage+ audience**, puedes ajustar:
- **Age**: Establece un rango de edad específico para orientar mejor tu anuncio a los distintos grupos de edad.
- **Gender**: Muestra tu anuncio a todos los usuarios o segméntalos por género.
- **Detailed targeting**: Este ajuste te da el control más específico sobre la audiencia para tu anuncio y/o app. Aquí puedes formar grupos basándote en **Demographics**, **Interests** o **Behaviors**. Dependiendo de lo que haga tu app, por ejemplo, puedes centrarte en distintas profesiones, seguidores de bandas de música concretas, padres de recién nacidos o personas con hábitos de compra online frecuentes.
:::note
Los ajustes de **Detailed targeting** se aplican con el operador **Or**. Si quieres aplicar condiciones con el operador **And**, haz clic en **Define further** y selecciona nuevas condiciones.
:::
9. En la sección **Placements**, puedes seleccionar dónde aparecerá tu anuncio. Por defecto, se selecciona **Advantage+**, lo que permite a Meta distribuir el presupuesto de tu conjunto de anuncios entre varios placements en función de dónde es más probable que rindan mejor. Te recomendamos usar esta opción si no tienes claro dónde colocar tu anuncio. Si quieres seleccionar placements específicos manualmente, elige **Manual placements** y personalízalos. Lee más [aquí](https://www.facebook.com/business/help/965529646866485).
10. **Recomendado**: La segmentación por dispositivo te ayuda a optimizar tu gasto. En la sección **Placements**, haz clic en **Show more settings**. En la subsección **Devices and operating system**, selecciona qué dispositivos, sistemas operativos y versiones de SO deben incluirse en tu audiencia. Esto garantiza que tus anuncios solo se muestren a usuarios relevantes. Por ejemplo, los usuarios de escritorio no verán tu anuncio y se excluirá a los usuarios con versiones de SO antiguas que tu app no admite.
11. Cuando estés listo, haz clic en **Next** para continuar.
## Paso 5. Crea anuncios \{#step-5-create-ads\}
Para crear un anuncio en Meta Ads Manager:
1. Dale un nombre a tu anuncio en el campo **Ad name**.
2. En la sección **Identity**, selecciona la página de Facebook que se usará para publicar los anuncios. Si tienes una cuenta de Instagram específica para tu app y la has conectado en Meta Business Suite en el [Paso 1](#step-1-create-meta-ads-manager-account), selecciónala en el desplegable **Instagram account**. De lo contrario, selecciona **Use Facebook page** para que los anuncios de Instagram se publiquen usando la página de Facebook.
3. En **Ad setup**, selecciona cómo quieres publicar tu anuncio. Al publicitar apps, recomendamos seleccionar **Create ad** para que tu publicación redirija a los usuarios a tu app en lugar de a la página de Facebook. En el campo **Format**, selecciona una opción según los creativos que tengas y cómo quieras mostrarlos.
4. En la sección **Destination**, mantén **Website** seleccionado como **Main destination**. En el campo **Website URL**, pega `https://api-ua.adapty.io/api/v1/attribution/click`. En [Adapty User Acquisition](adapty-user-acquisition), [crea una campaña web](ua-facebook) y pega el contenido de **Click link** después de `https://api-ua.adapty.io/api/v1/attribution/click` en el campo **URL parameters** de la sección **Tracking**.
5. En la sección **Ad creative**, haz clic en **Set up creative** y selecciona **Image ad** o **Video ad**. Se abrirá una nueva ventana donde podrás subir archivos multimedia, recortarlos y añadir textos.
6. Si quieres traducir automáticamente los textos de tu anuncio, en la sección **Languages**, haz clic en **Add languages**. Luego, añade un idioma principal: extraerá automáticamente los textos de tu creativo. Después, añade los idiomas de traducción para la traducción automática.
7. Cuando estés listo, haz clic en **Publish** para lanzar tu anuncio.
## Qué viene después \{#whats-next\}
Para activar tu anuncio, necesitarás añadir un método de pago si todavía no lo has hecho.
Después, puedes [explorar cómo la campaña afecta a los ingresos de tu app en el dashboard de Adapty User Acquisition](adapty-user-acquisition).
¿Todavía no usas Adapty User Acquisition? [Reserva una llamada con nosotros](https://calendly.com/tnurutdinov-adapty/30min) para descubrir cómo puede ayudarte a hacer seguimiento y optimizar tus campañas publicitarias.
---
# File: tiktok-create-campaign
---
---
title: "Anuncia tu app en TikTok for Business"
---
En esta guía paso a paso aprenderás a crear y configurar anuncios para tu app en TikTok for Business, para que puedas optimizarlos y hacer seguimiento de su rendimiento fácilmente.
## Paso 1. Añade la información de tu negocio \{#step-1-add-business-info\}
Si estás empezando con TikTok for Business, primero tienes que añadir la información de tu negocio:
1. Ve a [https://ads.tiktok.com](https://ads.tiktok.com/business/) y haz clic en **Get started**.
2. Regístrate con tu correo electrónico o tu cuenta de TikTok.
3. Introduce los datos de tu negocio y sigue las instrucciones en pantalla.
Una vez aprobada tu cuenta de negocio, serás redirigido a la creación de tu primera campaña.
## Paso 2. Crea un píxel \{#step-2-create-a-pixel\}
Necesitarás un píxel de TikTok para conectar los datos de tu campaña con los ingresos y obtener mejores resultados:
1. Ve al [**Events Manager**](https://ads.tiktok.com/i18n/events_manager/home). Haz clic en **Connect data source**.
2. Selecciona **Web** como tipo de fuente de datos.
3. En la ventana **Add your website**, haz clic en **Skip**.
4. Selecciona **Manual setup** y haz clic en **Next**.
5. Selecciona **TikTok pixel + Events API** y haz clic en **Next**.
6. Dale un nombre a tu píxel y haz clic en **Create**.
7. En [Adapty User Acquisition](adapty-user-acquisition), no necesitarás completar la instalación completa del píxel. Puedes cerrar la ventana de configuración y tu píxel aparecerá en la lista.
8. Para que este píxel esté disponible en las campañas, tienes que enviarle un evento de prueba desde [Adapty User Acquisition](adapty-user-acquisition):
1. [Crea una nueva campaña de TikTok](ua-tiktok).
2. Despliega la sección específica de la plataforma, por ejemplo, iOS.
3. Selecciona un píxel en el desplegable.
4. Haz clic en **Send test event**.
5. En el desplegable, selecciona el evento que usarás para optimización en el anuncio.
6. En TikTok for Business, abre tu píxel y ve a la pestaña **Test events**. Copia el `test_event_code`.
7. Pégalo en el campo **Test event code** de Adapty y haz clic en **Send**.
9. El evento de prueba aparecerá en TikTok en unos minutos. Cuando lo veas en los detalles de tu píxel, podrás continuar con la configuración de la campaña en TikTok Ads Manager.
## Paso 3. Selecciona el objetivo de la campaña \{#step-3-select-the-campaign-objective\}
:::important
Este tutorial usa la vista Quick setup de TikTok Ads Manager. Algunas configuraciones recomendadas solo aparecen en la vista Full, lo cual indicamos en los pasos correspondientes.
:::
Ve a la [página de creación de anuncios](https://ads.tiktok.com/i18n/nb_creation/create/objectives) en el Ads Manager.
En la primera pantalla, selecciona el objetivo publicitario y haz clic en **Continue**.
Selecciona **Sales > Website conversion**.
## Paso 4. Rellena la información de la campaña \{#step-4-fill-in-the-campaign-info\}
A continuación, rellena la información de la campaña:
1. Ponle nombre a tu campaña en el campo **Campaign name**.
2. En el campo **Optimization goal**, selecciona **Conversion**.
3. Selecciona tu píxel activo en el desplegable y elige un **Optimization event**. Ten en cuenta que solo los eventos activos están disponibles para seleccionar. Si el evento que necesitas no está disponible, envía un evento de prueba siguiendo las instrucciones del [Paso 2](#step-2-create-a-pixel).
4. Tu anuncio se mostrará en el feed y la búsqueda de TikTok. Para una configuración adicional, haz clic en **Advanced settings**. En **Placements**, configura los ajustes de placement:
- **User comment**: Selecciónalo si quieres mostrar tu anuncio también en la sección de comentarios. TikTok recomienda mantener los comentarios activados para que tus anuncios consigan más impresiones.
- **Allow video download**: Permite que los espectadores descarguen tu anuncio.
- **Allow video sharing**: Permite que los espectadores compartan tu anuncio.
5. Haz clic en **Continue**.
## Paso 5. Añade el contenido del anuncio \{#step-5-add-ad-content\}
Ahora es el momento de configurar tus creatividades y la URL de destino:
1. En el campo **TikTok account**, selecciona la cuenta que se usará para publicar.
2. En [Adapty User Acquisition](adapty-user-acquisition), [crea una campaña web](ua-tiktok) y pega el **Click link** en el campo **Destination URL**.
3. En la sección **Creatives**, haz clic en **+ Videos and images**.
4. Si quieres usar tus publicaciones de TikTok como creatividades, selecciónalas en la pestaña **TikTok post**. De lo contrario, cambia a la pestaña **Creative library** y haz clic en **Upload**. Los archivos que subas allí estarán accesibles desde esta pestaña más adelante, para que puedas reutilizarlos en otras campañas.
5. Recorta las creatividades para que se adapten al formato de TikTok y elige si se usarán como anuncios individuales o como un carrusel.
6. Despliega la creatividad subida y haz clic en **+** junto a **No music selected**. Puedes subir tus propios archivos mp3. Añadir música es obligatorio.
7. En el campo **Add text**, introduce el texto que se usará como descripción.
8. Selecciona **Place the ads on this TikTok account as a post** si quieres publicar este anuncio en tu cuenta de TikTok.
9. En el campo **Call to action**, selecciona o elimina las llamadas a la acción relevantes para tu anuncio. TikTok las añadirá automáticamente a tu anuncio.
10. Haz clic en **Continue**.
## Paso 6. Configura la segmentación y el presupuesto \{#step-6-configure-targeting-and-budget\}
Por último, define quién debe ver tu anuncio y cuánto planeas pagar por él:
1. En la sección **Targeting**, selecciona **Automatic** o **Custom**. La opción **Automatic** es la más sencilla si todavía no conoces bien a tu audiencia. Sin embargo, si seleccionas **Custom**, puedes optimizar tu gasto eligiendo los grupos de usuarios que tienen más probabilidades de responder a tu anuncio.
2. Si has seleccionado **Custom**, configura:
- **Location**: La ubicación predeterminada es la de tu cuenta publicitaria. Si seleccionas más de un país o región, los resultados de revisión del anuncio se devolverán por separado para cada ubicación. La entrega real de los anuncios también puede variar según las ubicaciones compatibles con los distintos placements.
- **Languages**: Por defecto, todos los idiomas están seleccionados. Elige el idioma de segmentación según el que se use con más frecuencia en la ubicación seleccionada.
- **Gender**: Por defecto, todos los géneros están seleccionados.
:::tip
Si cambias al modo Full, encontrarás una sección adicional **Device** bajo **Targeting**. Aquí puedes limitar tu audiencia por tipo de dispositivo, sistema operativo y versión del SO, algo útil si tu app requiere una versión mínima.
:::
3. En la sección **Budget**, selecciona una de las opciones sugeridas o elige **Custom**.
4. Si has seleccionado **Custom**, elige si necesitas un presupuesto **Daily** o **Lifetime** e introduce el límite en tu moneda. El presupuesto **Daily** te da más flexibilidad mientras todavía estás aprendiendo, así que puedes empezar con importes más pequeños e irlos ajustando sobre la marcha.
5. En la sección **Schedule**, selecciona **Continue for at least 7 days** o **Custom**. Te recomendamos establecer un horario **Custom** si tu anuncio es sensible al tiempo, para no perder el momento en que necesitas detenerlo.
6. Si has seleccionado **Custom**, establece la fecha y hora de inicio, o de inicio y fin, de los anuncios. Ten en cuenta que se usará la zona horaria de tu cuenta.
7. Haz clic en **Publish**.
Cuando termines, se creará una nueva campaña con un grupo de anuncios. El grupo de anuncios contendrá un anuncio si has configurado un carrusel, o varios anuncios si has añadido las creatividades como anuncios separados.
## Paso 7. Introduce los datos de pago \{#step-7-enter-payment-details\}
Para empezar a publicar el anuncio, tras configurar la segmentación y el presupuesto, introduce tus datos de pago. ¡Y ya está todo listo!
## Qué hacer a continuación \{#whats-next\}
Ahora puedes [explorar cómo la campaña afecta a los ingresos de tu app en el dashboard de Adapty User Acquisition](adapty-user-acquisition).
¿Todavía no usas Adapty User Acquisition? [Reserva una llamada con nosotros](https://calendly.com/tnurutdinov-adapty/30min) para conocer cómo puede ayudarte a hacer seguimiento y optimizar tus campañas publicitarias.
---
# File: getting-started-with-server-side-api
---
---
title: "API del servidor"
description: "Primeros pasos con la API del servidor de Adapty para la gestión de suscripciones."
---
Con la API puedes:
1. Consultar el estado de suscripción de un usuario.
2. Activar la suscripción de un usuario con un nivel de acceso.
3. Recuperar los atributos de un usuario.
4. Establecer los atributos de un usuario.
5. Obtener y actualizar configuraciones de paywalls.
:::note Para hacer seguimiento de eventos de suscripción, usa la integración de [Webhook](webhook) en Adapty o intégralo directamente con tu servicio existente. ::: ## Caso 1: Sincronizar suscriptores entre web y móvil \{#case-1-sync-subscribers-between-web-and-mobile\} Si usas proveedores de pago web como Stripe, ChargeBee u otros, puedes sincronizar tus suscriptores fácilmente. Así es cómo: 1.
La biblioteca de Adapty mantiene tu paywall actualizado con los últimos productos de tu Adapty Dashboard. [Obtiene los datos de los productos](ff-action-flow) y [los muestra en tu paywall](ff-add-variables-to-paywalls), [gestiona las compras](ff-make-purchase) y [comprueba el nivel de acceso del usuario](ff-check-subscription-status) para determinar si debe recibir contenido de pago.
Para empezar, solo tienes que [añadir la biblioteca de Adapty](ff-getting-started#add-the-adapty-library-as-a-dependency) a tu proyecto de FlutterFlow e [inicializarla](ff-getting-started#initiate-adapty-plugin) como se muestra a continuación.
:::warning
Antes de comenzar, ten en cuenta las siguientes limitaciones:
- La biblioteca de Adapty para FlutterFlow no es compatible con aplicaciones web. Evita compilar aplicaciones web con ella.
- La biblioteca de Adapty para FlutterFlow no es compatible con paywalls creados con el Paywall Builder de Adapty. Tienes que diseñar tu propio paywall en FlutterFlow antes de habilitar las compras con Adapty.
:::
## Añadir la biblioteca de Adapty como dependencia \{#add-the-adapty-library-as-a-dependency\}
1. En el [FlutterFlow Dashboard](https://app.flutterflow.io/dashboard), abre tu proyecto y haz clic en **Settings and Integrations** en el menú de la izquierda. En la sección **Project setup** a la izquierda, selecciona **Project dependencies**.
2. En la sección **FlutterFlow Libraries**, haz clic en **Add Library** e introduce `adapty-xtuel0`. Haz clic en **Add**.
3. Ahora debes asociar tu clave SDK con la biblioteca. Haz clic en **View details** junto a la biblioteca.
4. Copia la **Public SDK key** desde la pestaña [**App Settings** -> **General**](https://app.adapty.io/settings/general) en el Adapty Dashboard.
5. Pega la clave en **AdaptyApiKey** en FlutterFlow.
La biblioteca de Adapty FF se añadirá como dependencia a tu proyecto. En la ventana de la biblioteca **Adapty** FF encontrarás todos los recursos de Adapty que se han importado a tu proyecto.
## Llamar a la nueva acción de activación al iniciar la aplicación \{#call-the-new-activation-action-at-application-launch\}
1. Ve a la sección **Custom Code** en el menú de la izquierda y abre `main.dart`.
2. Haz clic en **+** y selecciona `activate (Adapty)`.
3. Haz clic en **Save**.
## Inicializar el plugin de Adapty \{#initiate-adapty-plugin\}
Para que el Adapty Dashboard reconozca tu app, deberás proporcionar una clave especial en FlutterFlow.
1. En tu proyecto de FlutterFlow, ve a **Settings and Integrations > Permissions** en el menú de la izquierda.
2. En la ventana **Permissions** que se abre, haz clic en el botón **Add Permission**.
3. En los campos **iOS Permission Key** y **Android Permission Key**, pega `AdaptyPublicSdkKey`.
4. Para el campo **Permission Message**, copia la **Public SDK key** desde la pestaña [**App Settings** -> **General**](https://app.adapty.io/settings/general) en el Adapty Dashboard. Cada app tiene su propia clave SDK, así que si tienes varias apps, asegúrate de coger la correcta.
Tras completar estos pasos, podrás mostrar tu paywall en tu app de FlutterFlow y habilitar las compras a través de él.
## ¿Qué sigue? \{#whats-next\}
1. [Crea un flujo de acción](ff-action-flow) para gestionar los productos del paywall de Adapty y sus datos en FlutterFlow.
2. [Mapea los datos recibidos en el paywall](ff-add-variables-to-paywalls) que diseñaste en FlutterFlow.
3. [Configura el botón de compra](ff-make-purchase) en tu paywall para procesar las transacciones a través de Adapty cuando se pulse.
4. Por último, [añade comprobaciones del estado de la suscripción](ff-check-subscription-status) para determinar si mostrar contenido de pago al usuario.
---
# File: ff-action-flow
---
---
title: "Paso 1. Crear el flujo para mostrar los datos del paywall"
description: "Configura los flujos de acción de feature flags en Adapty para personalizar los journeys de suscripción de los usuarios."
---
:::important
Al usar el plugin de FlutterFlow, no puedes usar paywalls creados en el Paywall Builder de Adapty. Debes implementar tu propia página de paywall en FlutterFlow y conectarla a Adapty.
:::
Después de añadir la librería de Adapty como dependencia a tu proyecto de FlutterFlow, es momento de construir el flujo que **recupera los datos del paywall y los productos de Adapty, y los muestra en el paywall que has diseñado en FlutterFlow**.
Primero necesitamos recibir los datos del paywall desde Adapty. Empezaremos solicitando el paywall de Adapty, luego sus productos asociados, y finalmente comprobaremos si los datos se recibieron correctamente. Si es así, mostraremos el título y el precio del producto en la página del paywall. En caso contrario, mostraremos un mensaje de error.
Antes de continuar, asegúrate de haber hecho lo siguiente:
1. [Crear al menos un paywall y añadir al menos un producto](create-paywall) en el Adapty Dashboard.
2. [Crear al menos un placement](create-placement) y [añadir tu paywall](add-audience-paywall-ab-test) en el Adapty Dashboard.
¡Empecemos!
## Paso 1.1. Solicitar el paywall de Adapty \{#step-11-request-adapty-paywall\}
Como se mencionó, para mostrar datos en tu paywall de FlutterFlow, primero necesitamos recuperarlos desde Adapty. El primer paso es obtener el paywall de Adapty. Así se hace:
1. Abre tu pantalla de paywall y cambia a la sección **Actions** en el panel derecho. Ahí, abre el **Action Flow Editor**.
2. En la ventana **Select Action Trigger**, selecciona **On Page Load**.
3. Haz clic en **Add Action**. Luego, busca la acción personalizada `getPaywall` y selecciónala.
4. En la sección **Set Actions Arguments**, introduce el ID real del [placement que has creado](create-placement) en el Adapty Dashboard que incluye el paywall. En este ejemplo es `monthly`. ¡Asegúrate de usar tu ID de placement real!
5. Si has [localizado](localizations-and-locale-codes) tu paywall en el dashboard de Adapty, también puedes configurar el argumento **locale**.
6. En **Action Output Variable Name**, crea una nueva variable y nómbrala `getPaywallResult`. La usaremos en el siguiente paso para referenciar el paywall de Adapty y solicitar sus productos.
## Paso 1.2. Solicitar los productos del paywall de Adapty \{#step-12-request-adapty-paywall-products\}
¡Genial! Ya hemos recuperado el paywall de Adapty. Ahora, obtengamos los productos asociados a este paywall:
1. Haz clic en **+** bajo la acción creada y selecciona **Add Action**. Esta acción recibirá los productos del paywall de Adapty. Para ello, busca y selecciona `getPaywallProducts`.
2. En la sección **Set Actions Arguments**, selecciona la variable `getPaywallResult` creada anteriormente.
3. Rellena los demás campos de la siguiente manera:
- **Available Options**: Data Structured Field
- **Select Field**: value
- **Available Options**: No further changes
4. Haz clic en **Confirm**.
5. En **Action Output Variable Name**, crea una nueva variable y nómbrala `getPaywallProductsResult`. La usaremos para vincular el paywall que diseñaste en FlutterFlow con los datos del paywall de Adapty.
## Paso 1.3. Añadir comprobación de si el paywall se cargó correctamente \{#step-13-add-check-if-the-paywall-uploaded-successfully\}
Antes de continuar, verifiquemos que el paywall de Adapty se recibió correctamente. Si es así, podemos actualizar el paywall con los datos de los productos. Si no, gestionaremos el error. Así se añade la comprobación:
1. Haz clic en **+** y luego en **Add Conditional**.
2. En la sección **Action Output**, selecciona la variable de salida de acción creada anteriormente (`getPaywallResult` en nuestro ejemplo).
3. Para verificar que el paywall de Adapty se recibió, comprueba la presencia de un campo con valor. Rellena los campos de la siguiente manera:
- **Available Options**: Has Field
- **Field (AdaptyGetPaywallResult)**: value
4. Haz clic en **Confirm** para finalizar la condición.
## Paso 1.4. Registrar la visualización del paywall \{#step-14-log-the-paywall-review\}
Para asegurarte de que los análisis de Adapty registran la visualización del paywall, necesitamos registrar este evento. Sin este paso, la visualización no se contabilizará en los análisis. Así se hace:
1. Haz clic en **+** bajo la etiqueta **TRUE** y haz clic en **Add Action**.
2. En el campo **Select Action**, busca y elige **logShowPaywall**.
3. Haz clic en **Value** en el área **Set Action Arguments** y elige la variable `getPaywallResult` que hemos creado. Esta variable contiene los datos del paywall.
4. Rellena los campos de la siguiente manera:
- **Available Options**: Data Structured Field
- **Select Field**: value
5. Haz clic en **Confirm**.
## Paso 1.5. Mostrar error si el paywall no se recibe \{#step-15-show-error-if-paywall-not-received\}
Si el paywall de Adapty no se recibe, necesitas [gestionar el error](error-handling-on-flutter-react-native-unity#system-storekit-codes). En este ejemplo, simplemente mostraremos un mensaje de alerta.
1. Añade una acción **Informational Dialog** a la etiqueta **FALSE**.
2. En el campo **Title**, añade el texto que quieras ver como título del diálogo. En este ejemplo, es **Error**.
3. Haz clic en **Value** en el cuadro **Message**.
4. Rellena los campos de la siguiente manera:
- **Set Variable**: variable `getPaywallProductResult` que hemos creado
- **Available Options**: Data Structure Field
- **Select Field**: error
- **Available Options**: Data Structure Field
- **Select Field**: errorMessage
5. Haz clic en **Confirm**.
6. Añade una acción **Terminate action** al flujo **FALSE**.
7. Haz clic en **Close** en la esquina superior derecha.
¡Felicidades! Has recibido correctamente los datos del producto. Ahora, [vincúlalos al paywall que has diseñado en FlutterFlow](ff-add-variables-to-paywalls).
---
# File: ff-add-variables-to-paywalls
---
---
title: "Paso 2. Añadir datos a la página del paywall"
description: "Añade variables de Feature Flag a los paywalls en Adapty."
---
Una vez que hayas [recibido todos los datos de producto necesarios](ff-action-flow), es hora de mapearlos al bonito paywall que diseñaste en FlutterFlow. En este ejemplo, mapearemos el título del producto y su precio.
## Paso 2.1. Añadir el título del producto a la página del paywall \{#step-21-add-product-title-to-paywall-page\}
1. Haz doble clic en el texto del producto en tu página del paywall. En la ventana **Set from Variable**, busca la variable `getPaywallProductResult` y selecciónala.
2. Rellena los campos de la siguiente manera:
- **Available Options**: Data Structured Field
- **Select Field**: value
- **Available Options**: Item at Index
- **List Index Options**: First
- **Available Options**: Data Structured Field
- **Select Field**: localizedTitle
- **Default Variable Value**: null
- **UI Builder Display Value**: Cualquier valor; en el ejemplo es `product.title`
3. Haz clic en **Confirm** para guardar los cambios.
## Paso 2.2. Añadir el texto del precio a la página del paywall \{#step-22-add-price-text-to-paywall-page\}
Repite los pasos del Paso 2.1 para el texto del precio como se muestra a continuación:
1. Haz doble clic en el texto del precio en tu página del paywall. En la ventana **Set from Variable**, busca la variable `getPaywallProductResult` y selecciónala.
2. Rellena los campos de la siguiente manera:
- **Available Options**: Data Structured Field
- **Select Field**: value
- **Available Options**: Item at Index
- **List Index Options**: First
- **Available Options**: Data Structured Field
- **Select Field**: price
- **Default Variable Value**: null
- **UI Builder Display Value**: Cualquier valor; en el ejemplo es `product.price`
3. Haz clic en el botón **Confirm** para guardar los cambios.
### Añadir el precio en moneda local a la página del paywall \{#add-price-in-local-currency-to-paywall-page\}
1. Haz doble clic en el precio en tu página del paywall. En la ventana **Set from Variable**, busca la variable `getPaywallProductResult` y selecciónala.
2. Rellena los campos de la siguiente manera:
- **Available Options**: Data Structured Field
- **Select Field**: value
- **Available Options**: Item at Index
- **List Index Options**: First
- **Available Options**: Data Structured Field
- **Select Field**: price
- **Available Options**: Data Structured Field
- **Select Field**: amount
- **Available Options**: Decimal
- **Decimal Type**: Automatic
- **Default Variable Value**: null
- **UI Builder Display Value**: Cualquier valor; en el ejemplo es `price.amount`
3. Haz clic en **Confirm** para guardar los cambios.
¡Y voilà! Ahora, al lanzar tu app, mostrará los datos del producto del paywall de Adapty directamente en tu página del paywall.
Es hora de [permitir que tus usuarios compren este producto](ff-make-purchase).
---
# File: ff-make-purchase
---
---
title: "Paso 3. Habilitar la compra"
description: "Aprende a realizar compras usando el sistema de Feature Flags de Adapty."
---
¡Enhorabuena! Ya has [configurado tu paywall para mostrar datos de productos de Adapty](ff-add-variables-to-paywalls), incluyendo el título y el precio del producto.
Ahora vamos al paso final: permitir que los usuarios realicen una compra a través del paywall.
## Paso 3.1. Permitir que los usuarios realicen compras \{#step-31-enable-users-to-make-purchases\}
1. Haz doble clic en el botón de compra de tu página del paywall. En el panel derecho, abre la sección **Actions** si no está ya abierta.
2. Abre el **Action Flow Editor**.
3. En la ventana **Select Action Trigger**, elige **On Tap**.
4. En la ventana **No Actions Created**, haz clic en **Add Action**. Busca la acción `makePurchase` y selecciónala.
5. En la sección **Set Actions Arguments**, selecciona la variable `getPaywallProductsResult` creada anteriormente.
6. Rellena los campos de la siguiente manera:
- **Available Options**: Data Structure Field
- **Select Field**: value
- **Available Options**: Item at Index
- **List Index Options**: First
7. Haz clic en `subscriptionUpdateParameters`, busca `AdaptySubscriptionUpdateParameters` y selecciónalo. Haz clic en **Confirm**.
:::info
Por defecto, puedes dejar todos los campos del objeto vacíos. Necesitarás rellenarlos para reemplazar una suscripción por otra en apps de Android. Lee más [aquí](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/).
:::
8. Haz clic en **Confirm**.
9. En **Action Output Variable Name**, crea una nueva variable y nómbrala `makePurchaseResult`; se usará más adelante para confirmar que la compra fue exitosa.
## Paso 3.2. Comprobar si la compra fue exitosa \{#step-32-check-if-the-purchase-was-successful\}
Ahora configuremos una comprobación para ver si la compra se realizó correctamente.
1. Haz clic en **+** y luego en **Add Conditional**.
2. En **Set Condition for Action**, selecciona la variable `makePurchaseResult`.
3. En la ventana **Set Variable**, rellena los campos de la siguiente manera:
- **Available Options**: Has Field
- **Select Field**: profile
4. Haz clic en **Confirm**.
## Paso 3.3. Abrir el contenido de pago \{#step-33-open-paid-content\}
Si la compra es exitosa, puedes desbloquear el contenido de pago. Aquí te explicamos cómo configurarlo:
1. Haz clic en **+** bajo la etiqueta **TRUE** y haz clic en **Add Action**.
2. En el campo **Define Action**, busca y selecciona la página que quieres abrir en la lista **Navigate To**. En este ejemplo, la página es **Questions**.
## Paso 3.4. Mostrar un mensaje de error si la compra falla \{#step-34-show-error-message-if-purchase-failed\}
Si la compra falla, vamos a mostrar una alerta al usuario.
1. Añade una acción **Informational Dialog** a la etiqueta **FALSE**.
2. En el campo **Title**, introduce el texto que quieras para el título del diálogo, como **Purchase Failed**.
3. Haz clic en **Value** en el cuadro **Message**. En la ventana **Set from Variable**, busca `makePurchaseResult` y selecciónalo. Rellena los campos de la siguiente manera:
- **Available Options**: Data Structure Field
- **Select Field**: error
- **Available Options**: Data Structure Field
- **Select Field**: errorMessage
4. Haz clic en **Confirm**.
5. Añade una acción **Terminate** al flujo **FALSE**.
6. Por último, haz clic en **Close** en la esquina superior derecha.
¡Enhorabuena! Tus usuarios ya pueden comprar tus productos. Como paso adicional, vamos a [configurar una comprobación del acceso del usuario al contenido de pago](ff-check-subscription-status) en otros puntos de la app para decidir si mostrarles el contenido de pago o el paywall.
---
# File: ff-check-subscription-status
---
---
title: "Paso 4. Verificar el acceso al contenido de pago"
description: "Aprende a verificar el estado de la suscripción usando los feature flags de Adapty para una mejor segmentación de usuarios."
---
Para determinar si un usuario tiene acceso a contenido de pago específico, debes verificar su nivel de acceso. Esto implica comprobar si el usuario tiene al menos un nivel de acceso y si ese nivel es el requerido.
Puedes hacerlo consultando el perfil del usuario, que contiene todos los niveles de acceso disponibles.
Ahora, vamos a permitir que los usuarios compren tu producto:
1. Haz doble clic en el botón que debe mostrar el contenido de pago y abre la sección **Actions** en el panel derecho si no está ya abierta.
2. Abre el **Action Flow Editor**.
3. En la ventana **Select Action Trigger**, elige **On Tap**.
4. En la ventana **No Actions Created**, haz clic en el botón **Add Conditional Action**.
5. Haz clic en **UNSET** para establecer los argumentos de la acción y elige la variable `currentProfile`. Esta es la variable de Adapty que almacena los datos del perfil del usuario actual.
6. Rellena los campos de la siguiente manera:
- **Available Options**: Data Structure Field
- **Select Field**: accessLevels
- **Available Options**: Filter List Items
- **Filter Conditions**:
1. Selecciona **Conditions -> Single Condition** y haz clic en **UNSET**.
2. En el campo **First value**, selecciona **Item in list** como **Source** y rellena los campos así:
- **Available Options**: Data Structure Field
- **Select Field**: accessLevelIdentifier
3. Establece el operador de filtro en **Equal to**.
4. Haz clic en **UNSET** junto a **Second value** y en el campo **Value**, introduce el ID de tu nivel de acceso; en nuestro ejemplo usamos `premium`.
5. Haz clic en **Confirm** y continúa rellenando los demás campos.
- **Available Options**: Item at Index
- **List Index Options**: First
- **Available Options**: Data Structure Field
- **Select Field**: accessLevel
- **Available Options**: Data Structure Field
- **Select Field**: isActive
7. Haz clic en **Confirm**.
Ahora, añade las acciones para lo que ocurre a continuación: si el usuario tiene la suscripción correcta o no. Llévalo a la página disponible para suscriptores premium o abre la página del paywall para que pueda comprar el acceso.
---
# File: ff-resources
---
---
title: "Adapty FlutterFlow plugin actions and data types"
description: "Access Adapty's feature flag resources to streamline subscription-based features."
---
## Custom Actions
Below are Adapty methods delivered to FlutterFlow with Adapty plugin. They can be used as custom actions in FlutterFlow.
| Custom Action | Description | Action Arguments | Adapty Data Types - Action Output Variable |
|---|----|--------|----|
| activate | Initializes the Adapty SDK | None ||
| getPaywall
| Retrieves a paywall. It does not return paywall products. Use the `getPaywallProducts` action to get the actual products |getPaywallProducts
| Returns a list of actual paywall products | [AdaptyPaywall](ff-resources#adaptypaywall) | [AdaptyGetProductsResult](ff-resources#adaptygetproductsresult) | |getProductsIntroductoryOfferEligibility
| Checks if the user qualifies for an introductory iOS subscription offer | [AdaptyPaywallProduct](product) | [AdaptyGetIntroEligibilitiesResult](ff-resources#adaptygetintroeligibilitiesresult) | |makePurchase
| Completes a purchase and unlocks content. If a paywall has a promotional offer, Adapty automatically applies it at checkout|getProfile
|Retrieves the current app user's profile. This allows you to set access levels and other parameters
If it fails (e.g., due to no internet), cached data will be returned. Adapty regularly updates the profile cache to ensure the information stays as current as possible
| None| [AdaptyGetProfileResult](ff-resources#adaptygetprofileresult) | | updateProfile | Changes optional attributes of the current user profile such as email, phone number, etc. You can later use attributes to create user [segments](segments) or just view them in CRM | The ID and any parameters that need to be updated for the [AdaptyProfile](ff-resources#adaptyprofile) | [AdaptyError](ff-resources#adaptyerror) (Optional) | | restorePurchases | Restores any purchases the user has made | None | [AdaptyGetProfileResult](ff-resources#adaptygetprofileresult) | | logShowPaywall | Logs when a specific paywall is shown to the user | [AdaptyPaywall](ff-resources#adaptypaywall) | [AdaptyError](ff-resources#adaptyerror) (Optional) | | identify | Identifies the user using your system's `customerUserId` | customerUserId | [AdaptyError](ff-resources#adaptyerror) (Optional) | | logout | Logs the current user out of your app | None | [AdaptyError](ff-resources#adaptyerror) (Optional)| | presentCodeRedemptionSheet | Displays a sheet that allows users to redeem codes (iOS only) | None | None | ## Data Types Adapty data types (collections of data values) delivered to FlutterFlow with Adapty plugin. ### AdaptyAccessLevel Information about the user's [access level](access-level). | Field Name | Type | Description | |--------------------------|----------|-------------| | activatedAt | DateTime | The time when this access level was activated | | activeIntroductoryOfferType | String | The type of an active introductory offer. If set, it means an offer was applied during this subscription period | | activePromotionalOfferId | String | The ID of an active promotional offer (purchased from iOS) | | activePromotionalOfferType | String | The type of an active promotional offer (purchased from iOS). If set, it means an offer was applied during this subscription period | | billingIssueDetectedAt | DateTime | The time when a billing issue was detected. The subscription can still be active. Set to null if payment is successfully processed | | cancellationReason | String | The reason why the subscription was canceled | | expiresAt | DateTime | The access level expiration time (could be in the past or not set for lifetime access) | | id | String | The identifier of the access level | | isActive | Boolean | True if this access level is active. Generally, you can check this property to determine if a user has an access to premium features | | isInGracePeriod | Boolean | True if this auto-renewable subscription is in the [grace period](https://developer.apple.com/help/app-store-connect/manage-subscriptions/enable-billing-grace-period-for-auto-renewable-subscriptions) | | isLifetime | Boolean | True if this access level is active for a lifetime (no expiration date) | | isRefund | Boolean | True if this purchase was refunded | | offerId | String | The ID of an active promotional offer (purchased from Android) | | renewedAt | DateTime | The time when the access level was last renewed | | startsAt | DateTime | The start time of this access level (could be in the future) | | store | String | The store where the purchase was made | | unsubscribedAt | DateTime | The time when auto-renewal was turned off for the subscription. The subscription can still be active. If not set, the user reactivated the subscription | | vendorProductId | String | The product ID from the store that unlocked this access level | | willRenew | Boolean | True if this auto-renewable subscription is set to renew | ### AdaptyAccessLevelIdentifiers This struct is intended to replace key-value pair for `Map
2. Descarga e importa el [plugin External Dependency Manager](https://github.com/googlesamples/unity-jar-resolver).
3. El SDK usa el plugin "External Dependency Manager" para gestionar las dependencias de iOS Cocoapods y las dependencias de Android gradle. Tras la instalación, puede que necesites invocar el gestor de dependencias:
`Assets -> External Dependency Manager -> Android Resolver -> Force Resolve`
y
`Assets -> External Dependency Manager -> iOS Resolver -> Install Cocoapods`
4. Al compilar tu proyecto de Unity para iOS, obtendrás el archivo `Unity-iPhone.xcworkspace`, que debes abrir en lugar de `Unity-iPhone.xcodeproj`; de lo contrario, las dependencias de Cocoapods no se usarán.
## Activar el módulo Adapty del SDK de Adapty \{#activate-adapty-module-of-adapty-sdk\}
Activa el SDK de Adapty en el código de tu app.
:::note
El SDK de Adapty solo necesita activarse una vez en tu app.
:::
Para obtener tu **Public SDK Key**:
1. Ve al Adapty Dashboard y navega a [**App settings → General**](https://app.adapty.io/settings/general).
2. En la sección **Api keys**, copia la **Public SDK Key** (NO la Secret Key).
3. Reemplaza `"YOUR_PUBLIC_SDK_KEY"` en el código.
:::important
- Asegúrate de usar la **Public SDK key** para inicializar Adapty; la **Secret key** solo debe usarse para la [API del servidor](getting-started-with-server-side-api).
- Las **SDK keys** son únicas para cada app, así que si tienes varias apps asegúrate de elegir la correcta.
:::
```csharp showLineNumbers title="C#"
using UnityEngine;
using AdaptySDK;
public class AdaptyListener : MonoBehaviour, AdaptyEventListener {
void Start() {
DontDestroyOnLoad(this.gameObject);
Adapty.SetEventListener(this);
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY");
Adapty.Activate(builder.Build(), (error) => {
if (error != null) {
// handle the error
return;
}
});
}
public void OnLoadLatestProfile(AdaptyProfile profile) { }
public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { }
public void OnInstallationDetailsFail(AdaptyError error) { }
}
```
:::important
Espera al callback de finalización de `Activate` antes de llamar a cualquier otro método del SDK de Adapty. Consulta [Orden de llamadas en el SDK de Unity](unity-sdk-call-order) para ver la secuencia completa.
:::
## Configurar la escucha de eventos \{#set-up-event-listening\}
Crea un script para escuchar los eventos de Adapty. Nómbralo `AdaptyListener` en tu escena. Te recomendamos usar el método `DontDestroyOnLoad` para este objeto, de modo que persista durante toda la vida útil de la aplicación.
Adapty usa el namespace `AdaptySDK`. Al principio de los archivos de script que usen el SDK de Adapty, puedes añadir:
```csharp showLineNumbers title="C#"
using AdaptySDK;
```
Suscríbete a los eventos de Adapty:
```csharp showLineNumbers title="C#"
using UnityEngine;
using AdaptySDK;
public class AdaptyListener : MonoBehaviour, AdaptyEventListener {
public void OnLoadLatestProfile(AdaptyProfile profile) {
// handle updated profile data
}
public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { }
public void OnInstallationDetailsFail(AdaptyError error) { }
}
```
Te recomendamos ajustar el Script Execution Order para colocar el AdaptyListener antes de Default Time. Esto garantiza que Adapty se inicialice lo antes posible.
## Añadir el plugin de Kotlin a tu proyecto \{#add-kotlin-plugin-to-your-project\}
:::warning
Este paso es obligatorio. Si lo omites, tu app móvil puede fallar cuando se muestre el paywall.
:::
1. En **Player Settings**, asegúrate de que las opciones **Custom Launcher Gradle Template** y **Custom Base Gradle Template** estén seleccionadas.
2. Añade la siguiente línea a `/Assets/Plugins/Android/launcherTemplate.gradle`:
```groovy showLineNumbers
apply plugin: 'com.android.application'
// highlight-next-line
apply plugin: 'kotlin-android'
apply from: 'setupSymbols.gradle'
apply from: '../shared/keepUnitySymbols.gradle'
```
3. Añade la siguiente línea a `/Assets/Plugins/Android/baseProjectTemplate.gradle`:
```groovy showLineNumbers
plugins {
// If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity
// See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html
// See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
// To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version
id 'com.android.application' version '8.3.0' apply false
id 'com.android.library' version '8.3.0' apply false
// highlight-next-line
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
**BUILD_SCRIPT_DEPS**
}
```
Ahora configura los paywalls en tu app:
- Si usas el [Adapty Paywall Builder](adapty-paywall-builder), primero [activa el módulo AdaptyUI](#activate-adaptyui-module-of-adapty-sdk) a continuación y luego sigue la [guía de inicio rápido del Paywall Builder](unity-quickstart-paywalls).
- Si construyes tu propia UI de paywall, consulta la [guía de inicio rápido para paywalls personalizados](unity-quickstart-manual).
## Activar el módulo AdaptyUI del SDK de Adapty \{#activate-adaptyui-module-of-adapty-sdk\}
Si planeas usar el [Paywall Builder](adapty-paywall-builder) y has instalado el módulo AdaptyUI, necesitas que AdaptyUI esté activo. Puedes activarlo durante la configuración:
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetActivateUI(true);
```
## Configuración opcional \{#optional-setup\}
### Registro de logs \{#logging\}
#### Configurar el sistema de logs \{#set-up-the-logging-system\}
Adapty registra errores y otra información importante para ayudarte a entender qué ocurre. Estos son los niveles disponibles:
| Nivel | Descripción |
| ---------- | ------------------------------------------------------------ |
| `error` | Solo se registrarán los errores |
| `warn` | Se registrarán los errores y los mensajes del SDK que no causan errores críticos pero merecen atención |
| `info` | Se registrarán los errores, advertencias y varios mensajes informativos |
| `verbose` | Se registrará cualquier información adicional que pueda ser útil durante la depuración, como llamadas a funciones, consultas a la API, etc. |
Puedes establecer el nivel de log en tu app durante la configuración de Adapty:
```csharp showLineNumbers title="C#"
// 'verbose' is recommended for development and the first production release
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY");
builder.LogLevel = AdaptyLogLevel.Verbose;
```
También puedes cambiar el nivel de log en tiempo de ejecución:
```csharp showLineNumbers title="C#"
Adapty.SetLogLevel(AdaptyLogLevel.Verbose, (error) => {
// handle result
});
```
### Políticas de datos \{#data-policies\}
Adapty no almacena datos personales de tus usuarios a menos que los envíes explícitamente, pero puedes implementar políticas adicionales de seguridad de datos para cumplir con las directrices del store o del país.
#### Deshabilitar la recopilación y el uso compartido de la dirección IP \{#disable-ip-address-collection-and-sharing\}
Al activar el módulo Adapty, establece `SetIPAddressCollectionDisabled` en `true` para deshabilitar la recopilación y el uso compartido de la dirección IP del usuario. El valor predeterminado es `false`.
Usa este parámetro para mejorar la privacidad del usuario, cumplir con las regulaciones regionales de protección de datos (como el RGPD o la CCPA), o reducir la recopilación de datos innecesaria cuando las funciones basadas en IP no son necesarias para tu app.
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetIPAddressCollectionDisabled(true);
```
#### Deshabilitar la recopilación y el uso compartido del ID publicitario \{#disable-advertising-id-collection-and-sharing\}
Al activar el módulo Adapty, establece `SetAppleIDFACollectionDisabled` y/o `SetGoogleAdvertisingIdCollectionDisabled` en `true` para deshabilitar la recopilación de identificadores publicitarios. El valor predeterminado es `false`.
Usa este parámetro para cumplir con las políticas de App Store/Google Play, evitar activar el prompt de App Tracking Transparency, o si tu app no requiere atribución publicitaria ni analíticas basadas en IDs publicitarios.
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetAppleIDFACollectionDisabled(true)
.SetGoogleAdvertisingIdCollectionDisabled(true);
```
#### Configurar la caché de medios para AdaptyUI \{#set-up-media-cache-configuration-for-adaptyui\}
Por defecto, AdaptyUI almacena en caché los medios (como imágenes y vídeos) para mejorar el rendimiento y reducir el uso de red. Puedes personalizar la configuración de la caché proporcionando una configuración personalizada.
Usa `SetAdaptyUIMediaCache` para sobreescribir la configuración predeterminada de la caché:
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetAdaptyUIMediaCache(
100 * 1024 * 1024, // MemoryStorageTotalCostLimit 100MB
null, // MemoryStorageCountLimit
100 * 1024 * 1024 // DiskStorageSizeLimit 100MB
);
```
Parámetros:
| Parámetro | Obligatorio | Descripción |
|-----------------------------|-------------|----------------------------------------------------------------------------------|
| memoryStorageTotalCostLimit | opcional | Tamaño total de la caché en memoria en bytes. Por defecto, valor específico de la plataforma. |
| memoryStorageCountLimit | opcional | El límite de número de elementos en el almacenamiento en memoria. Por defecto, valor específico de la plataforma. |
| diskStorageSizeLimit | opcional | El límite de tamaño de archivo en disco en bytes. Por defecto, valor específico de la plataforma. |
### Habilitar niveles de acceso locales (Android) \{#enable-local-access-levels-android\}
Por defecto, los [niveles de acceso locales](local-access-levels) están habilitados en iOS y deshabilitados en Android. Para habilitarlos también en Android, establece `SetGoogleLocalAccessLevelAllowed` en `true`:
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetGoogleLocalAccessLevelAllowed(true);
```
### Limpiar datos al restaurar desde copia de seguridad \{#clear-data-on-backup-restore\}
Cuando `SetAppleClearDataOnBackup` se establece en `true`, el SDK detecta cuándo la app se restaura desde una copia de seguridad de iCloud y elimina todos los datos del SDK almacenados localmente, incluida la información de perfil en caché, los detalles del producto y los paywalls. El SDK se inicializa entonces con un estado limpio. El valor predeterminado es `false`.
:::note
Solo se elimina la caché local del SDK. El historial de transacciones con Apple y los datos de usuario en los servidores de Adapty permanecen sin cambios.
:::
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetAppleClearDataOnBackup(true);
```
## Solución de problemas \{#troubleshooting\}
#### Reglas de copia de seguridad de Android (configuración de Auto Backup) \{#android-backup-rules-auto-backup-configuration\}
Algunos SDKs (incluido Adapty) incluyen su propia configuración de Android Auto Backup. Si utilizas varios SDKs que definen reglas de copia de seguridad, el fusionador de manifiestos de Android puede fallar con un error relacionado con `android:fullBackupContent`, `android:dataExtractionRules` o `android:allowBackup`.
Síntomas típicos del error: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules)
is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)`
:::note
Estos cambios deben realizarse en el directorio de la plataforma Android (normalmente en la carpeta `android/` de tu proyecto).
:::
Para resolverlo, necesitas:
- Indicar al fusionador de manifiestos que use los valores de tu app para los atributos relacionados con la copia de seguridad.
- Crear archivos de reglas de copia de seguridad que combinen las reglas de Adapty con las de otros SDKs.
#### 1. Añade el namespace `tools` a tu manifiesto \{#1-add-the-tools-namespace-to-your-manifest\}
En tu archivo `AndroidManifest.xml`, asegúrate de que la etiqueta raíz `
### Durante el inicio de sesión/registro \{#during-loginsignup\}
Si identificas a los usuarios después del arranque de la app (por ejemplo, después de que inicien sesión o se registren), usa el método `identify` para establecer su customer user ID.
- Si **no has usado este customer user ID antes**, Adapty lo vinculará automáticamente al perfil actual.
- Si **ya has usado este customer user ID para identificar al usuario**, Adapty cambiará al perfil asociado a ese customer user ID.
:::important
Los customer user IDs deben ser únicos para cada usuario. Si hardcodeas el valor del parámetro, todos los usuarios se considerarán como uno solo.
:::
Espera el callback de finalización de `Identify` antes de llamar a otros métodos del SDK. Las llamadas concurrentes producen `#3006 profileWasChanged` o aterrizan en el perfil anónimo. Consulta [Orden de llamadas en el SDK de Unity](unity-sdk-call-order).
```csharp showLineNumbers
Adapty.Identify("YOUR_USER_ID", (error) => { // Único para cada usuario
if(error == null) {
// identificación correcta
}
});
```
### Durante la activación del SDK \{#during-the-sdk-activation\}
Si ya conoces un customer user ID cuando activas el SDK, puedes enviarlo en el método `activate` en lugar de llamar a `identify` por separado.
Si conoces un customer user ID pero lo estableces solo después de la activación, eso significará que, al activarse, Adapty creará un nuevo perfil anónimo y cambiará al existente solo después de que llames a `identify`.
Puedes pasar un customer user ID existente (uno que hayas usado antes) o uno nuevo. Si pasas uno nuevo, el nuevo perfil creado al activarse se vinculará automáticamente al customer user ID.
:::note
Por defecto, la creación de perfiles anónimos no afecta a los dashboards de analíticas, ya que las instalaciones se cuentan por IDs de dispositivo.
Un ID de dispositivo representa una única instalación de la app desde el store en un dispositivo y solo se regenera tras reinstalar la app.
No depende de si es una primera instalación o una reinstalación, ni de si se usa un customer user ID existente.
Crear un perfil (al activar el SDK o al cerrar sesión), iniciar sesión o actualizar la app sin reinstalarla no genera eventos de instalación adicionales.
Si quieres contar las instalaciones por usuarios únicos en lugar de dispositivos, ve a **App settings** y configura [**Installs definition for analytics**](general#4-installs-definition-for-analytics).
:::
```csharp showLineNumbers
using UnityEngine;
using AdaptySDK;
var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY")
.SetCustomerUserId("YOUR_USER_ID"); // Los customer user IDs deben ser únicos para cada usuario. Si hardcodeas el valor del parámetro, todos los usuarios se considerarán como uno solo.
Adapty.Activate(builder.Build(), (error) => {
if (error != null) {
// handle the error
return;
}
});
```
### Cerrar sesión de usuarios \{#log-users-out\}
Si tienes un botón para cerrar la sesión de los usuarios, usa el método `logout`.
:::important
Cerrar la sesión de los usuarios crea un nuevo perfil anónimo para el usuario.
:::
```csharp showLineNumbers
Adapty.Logout((error) => {
if(error == null) {
// cierre de sesión correcto
}
});
```
:::info
Para volver a iniciar sesión en la app, usa el método `identify`.
:::
### Permitir compras sin inicio de sesión \{#allow-purchases-without-login\}
Si tus usuarios pueden realizar compras tanto antes como después de iniciar sesión en tu app, debes asegurarte de que mantengan el acceso tras iniciar sesión:
1. Cuando un usuario sin sesión iniciada realiza una compra, Adapty la vincula a su ID de perfil anónimo.
2. Cuando el usuario inicia sesión en su cuenta, Adapty cambia al perfil identificado.
- Si es un nuevo customer user ID (por ejemplo, la compra se realizó antes del registro), Adapty asigna el customer user ID al perfil actual, por lo que se mantiene todo el historial de compras.
- Si es un customer user ID existente (el customer user ID ya está vinculado a un perfil), necesitas obtener el nivel de acceso actual tras el cambio de perfil. Puedes llamar a [`getProfile`](unity-check-subscription-status) justo después de la identificación, o [escuchar las actualizaciones del perfil](unity-check-subscription-status) para que los datos se sincronicen automáticamente.
## Próximos pasos \{#next-steps\}
¡Enhorabuena! Has implementado la lógica de pago in-app en tu app. ¡Te deseamos todo el éxito con la monetización de tu app!
Para sacar aún más partido a Adapty, puedes explorar estos temas:
- [**Pruebas**](troubleshooting-test-purchases): Asegúrate de que todo funciona como se espera
- [**Onboardings**](onboardings): Engancha a los usuarios con onboardings e impulsa la retención
- [**Integraciones**](configuration): Intégrate con servicios de atribución de marketing y analíticas con solo una línea de código
- [**Establecer atributos de perfil personalizados**](unity-setting-user-attributes): Añade atributos personalizados a los perfiles de usuario y crea segmentos para lanzar pruebas A/B o mostrar diferentes paywalls a distintos usuarios
---
# File: adapty-cursor-unity
---
---
title: "Integra Adapty en tu app de Unity con IA"
description: "Una guía paso a paso para integrar Adapty en tu app de Unity usando Cursor, Context7, ChatGPT, Claude u otras herramientas de IA."
---
Esta página describe dos formas de integrar Adapty en tu app de Unity. Usa la skill de integración del SDK para un flujo automatizado de extremo a extremo, o sigue el recorrido manual más abajo.
## Usa la skill de integración del SDK (beta) \{#use-the-sdk-integration-skill-beta\}
La [skill adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza la integración de principio a fin: configuración del dashboard, instalación del SDK, paywall y verificación por etapas. El recorrido manual más abajo es el plan B si tu herramienta no admite el formato Claude Skills.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
### Instalación \{#install\}
Elige el formato según tu herramienta. La lista completa está en el [README de la skill](https://github.com/adaptyteam/adapty-sdk-integration-skill).
- **Claude Code**: Ejecuta `claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill` y luego `claude plugin install adapty-sdk-integration@adapty` desde tu terminal.
- **GitHub Copilot CLI**: Ejecuta `gh skill install adaptyteam/adapty-sdk-integration-skill`.
- **Gemini CLI**: Ejecuta `gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill`.
- **OpenAI Codex u otra herramienta**: Clona el repositorio y copia `plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` en el directorio de skills de tu herramienta.
### Ejecución \{#run\}
En tu proyecto, ejecuta `/adapty-sdk-integration`. La skill detecta tu plataforma y hace algunas preguntas de configuración. Luego te guía por la configuración del dashboard, la instalación del SDK, el paywall y la verificación, consultando la documentación de Adapty en cada etapa.
:::note
La skill está en beta. Si se detiene o se comporta de forma inesperada, el recorrido manual de más abajo cubre cada etapa paso a paso.
:::
## Antes de empezar: configuración del dashboard \{#before-you-start-dashboard-setup\}
Adapty requiere cierta configuración en el dashboard antes de escribir código. Puedes hacerlo con una skill interactiva de LLM o manualmente desde el Dashboard.
### Con la skill (recomendado) \{#skill-approach-recommended\}
La skill de la CLI de Adapty permite que tu LLM configure tu app, productos, niveles de acceso, paywalls y placements directamente, sin abrir el Dashboard en cada paso. Solo necesitas [conectar tus stores](integrate-payments) en el Dashboard.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Una vez añadida la skill, ejecuta `/adapty-cli` en tu agente. Te guiará por cada paso, incluido cuándo abrir el Dashboard para conectar tus stores.
### Con el Dashboard \{#dashboard-approach\}
Si prefieres configurar todo manualmente, esto es lo que necesitas antes de escribir código. Tu LLM no puede buscar los valores del dashboard por ti — tendrás que proporcionárselos.
1. **Conecta tus app stores**: En el Adapty Dashboard, ve a **App settings → General**. Conecta tanto App Store como Google Play si tu app de Unity apunta a ambas plataformas. Esto es obligatorio para que las compras funcionen.
[Conectar app stores](integrate-payments)
2. **Copia tu clave pública del SDK**: En el Adapty Dashboard, ve a **App settings → General** y busca la sección **API keys**. En el código, es la cadena que pasas al constructor de configuración de Adapty.
3. **Crea al menos un producto**: En el Adapty Dashboard, ve a la página **Products**. No haces referencia a los productos directamente en el código — Adapty los entrega a través de los paywalls.
[Añadir productos](quickstart-products)
4. **Crea un paywall y un placement**: En el Adapty Dashboard, crea un paywall en la página **Paywalls** y asígnalo a un placement en la página **Placements**. En el código, el ID del placement es la cadena que pasas a `Adapty.GetPaywall("YOUR_PLACEMENT_ID")`.
[Crear paywall](quickstart-paywalls)
5. **Configura los niveles de acceso**: En el Adapty Dashboard, configúralos por producto en la página **Products**. En el código, la cadena que se comprueba en `profile.AccessLevels["premium"]?.IsActive`. El nivel de acceso `premium` predeterminado funciona para la mayoría de las apps. Si los usuarios de pago acceden a funciones distintas según el producto (por ejemplo, un plan `basic` frente a un plan `pro`), [crea niveles de acceso adicionales](assigning-access-level-to-a-product) antes de empezar a programar.
:::tip
Con estos cinco elementos listos, ya puedes escribir código. Dile a tu LLM: "Mi clave pública del SDK es X, mi ID de placement es Y" para que pueda generar el código correcto de inicialización y obtención del paywall.
:::
### Configura cuando estés listo \{#set-up-when-ready\}
Estos elementos no son necesarios para empezar a programar, pero los querrás a medida que tu integración madure:
- **Pruebas A/B**: Configúralas en la página **Placements**. No requieren cambios en el código.
[Pruebas A/B](ab-tests)
- **Paywalls y placements adicionales**: Añade más llamadas a `GetPaywall` con distintos IDs de placement.
- **Integraciones de analíticas**: Configúralas en la página **Integrations**. La configuración varía según la integración. Consulta [integraciones de analíticas](analytics-integration) e [integraciones de atribución](attribution-integration).
## Proporciona la documentación de Adapty a tu LLM \{#feed-adapty-docs-to-your-llm\}
### Usa Context7 (recomendado) \{#use-context7-recommended\}
[Context7](https://context7.com) es un servidor MCP que da a tu LLM acceso directo a la documentación actualizada de Adapty. El LLM obtiene automáticamente la documentación adecuada según lo que le preguntes — sin necesidad de pegar URLs manualmente.
Context7 funciona con **Cursor**, **Claude Code**, **Windsurf** y otras herramientas compatibles con MCP. Para configurarlo, ejecuta:
```
npx ctx7 setup
```
Esto detecta tu editor y configura el servidor Context7. Para la configuración manual, consulta el [repositorio de Context7 en GitHub](https://github.com/upstash/context7).
Una vez configurado, haz referencia a la biblioteca de Adapty en tus prompts:
```
Use the adaptyteam/adapty-docs library to look up how to install the Unity SDK
```
:::warning
Aunque Context7 elimina la necesidad de pegar enlaces de documentación manualmente, el orden de implementación sigue siendo importante. Sigue el [recorrido de implementación](#implementation-walkthrough) paso a paso para asegurarte de que todo funciona correctamente.
:::
### Usa la documentación en texto plano \{#use-plain-text-docs\}
Puedes acceder a cualquier artículo de Adapty en texto plano Markdown. Añade `.md` al final de su URL o haz clic en **Copy for LLM** debajo del título del artículo. Por ejemplo: [adapty-cursor-unity.md](https://adapty.io/docs/es/adapty-cursor-unity.md).
Cada etapa del [recorrido de implementación](#implementation-walkthrough) incluye un bloque "Envía esto a tu LLM" con enlaces `.md` para pegar.
Para acceder a más documentación a la vez, consulta los [archivos índice y subconjuntos por plataforma](#plain-text-doc-index-files) más abajo.
## Recorrido de implementación \{#implementation-walkthrough\}
El resto de esta guía recorre la integración de Adapty en orden de implementación. Cada etapa incluye la documentación que debes enviar a tu LLM, lo que deberías ver al terminar y los problemas más comunes.
### Planifica tu integración \{#plan-your-integration\}
Antes de ponerte a programar, pide a tu LLM que analice tu proyecto y cree un plan de implementación. Si tu herramienta de IA admite un modo de planificación (como el de Cursor o Claude Code), úsalo para que el LLM pueda leer tanto la estructura de tu proyecto como la documentación de Adapty antes de escribir código.
Indica a tu LLM qué enfoque usas para las compras — esto determina las guías que debe seguir:
- [**Adapty Paywall Builder**](adapty-paywall-builder): Creas paywalls en el editor no-code de Adapty y el SDK los renderiza automáticamente.
- [**Paywalls creados manualmente**](unity-making-purchases): Construyes tu propia interfaz de paywall en código, pero usas Adapty para obtener los productos y gestionar las compras.
- [**Modo Observer**](observer-vs-full-mode): Mantienes tu infraestructura de compras existente y usas Adapty solo para analíticas e integraciones.
¿No sabes cuál elegir? Lee la [tabla comparativa del quickstart](unity-quickstart-paywalls).
### Instala y configura el SDK \{#install-and-configure-the-sdk\}
Añade el paquete del SDK de Adapty a través del Unity Package Manager y actívalo con tu clave pública del SDK. Esta es la base — nada más funciona sin ella.
**Guía:** [Instalar y configurar el SDK de Adapty](sdk-installation-unity)
Envía esto a tu LLM:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/es/sdk-installation-unity.md
```
:::tip[Punto de control]
- **Esperado:** El proyecto compila y se ejecuta. La consola de Unity muestra el log de activación de Adapty.
- **Problema frecuente:** "Public API key is missing" → comprueba que hayas reemplazado el marcador de posición con tu clave real de App settings.
:::
### Muestra paywalls y gestiona las compras \{#show-paywalls-and-handle-purchases\}
Obtén un paywall por ID de placement, muéstralo y gestiona los eventos de compra. Las guías que necesitas dependen de cómo gestionas las compras.
Prueba cada compra en el sandbox a medida que avances — no esperes al final. Consulta [Probar compras en sandbox](test-purchases-in-sandbox) para las instrucciones de configuración.
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-paywall-locale-in-adapty-paywall-builder). Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma, la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](localizations-and-locale-codes) para más información sobre códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché de actualización regular descrita arriba y los [paywalls de respaldo](fallback-paywalls). También usamos CDN para obtener paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para que siempre obtengas la versión más reciente de tus paywalls, garantizando fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede agotar el tiempo ligeramente después de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) con una lista de IDs de productos, el identificador del paywall, Remote Config y varias otras propiedades. | ## Obtener la configuración de vista del paywall diseñado con Paywall Builder \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important Asegúrate de activar el toggle **Show on device** en el Paywall Builder. Si esta opción no está activada, la configuración de vista no estará disponible para recuperar. ::: Después de obtener el paywall, comprueba si incluye una `ViewConfiguration`, lo que indica que fue creado con Paywall Builder. Esto te orientará sobre cómo mostrar el paywall. Si la `ViewConfiguration` está presente, trátalo como un paywall de Paywall Builder; si no, [trátalo como un paywall de Remote Config](present-remote-config-paywalls-unity). En el SDK de Unity, llama directamente al método `CreatePaywallView` sin necesidad de obtener primero la configuración de vista manualmente. :::warning El resultado del método `CreatePaywallView` solo puede usarse una vez. Si necesitas usarlo de nuevo, vuelve a llamar al método `CreatePaywallView`. Llamarlo dos veces sin recrearlo puede resultar en el error `AdaptyUIError.viewAlreadyPresented`. ::: ```csharp showLineNumbers var parameters = new AdaptyUICreatePaywallViewParameters() .SetPreloadProducts(preloadProducts) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // handle the result }); ``` Parámetros: | Parámetro | Presencia | Descripción | | :------------------ | :------------- | :----------------------------------------------------------- | | **paywall** | requerido | Un objeto `AdaptyPaywall` para obtener un controlador para el paywall deseado. | | **loadTimeout** | por defecto: 5 seg | Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el respaldo local. Ten en cuenta que en casos excepcionales este método puede agotar el tiempo ligeramente después de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internamente. | | **PreloadProducts** | opcional | Proporciona un array de `AdaptyPaywallProducts` para optimizar el tiempo de visualización de los productos en pantalla. Si se pasa `nil`, AdaptyUI obtendrá automáticamente los productos necesarios. | | **CustomTags** | opcional | Define un diccionario de etiquetas personalizadas y sus valores resueltos. Las etiquetas personalizadas actúan como marcadores de posición en el contenido del paywall, reemplazados dinámicamente por cadenas específicas para contenido personalizado. Consulta el tema [Etiquetas personalizadas en el Paywall Builder](custom-tags-in-paywall-builder) para más detalles. | | **CustomTimers** | opcional | Define un diccionario de temporizadores personalizados y sus fechas de finalización. Los temporizadores personalizados te permiten mostrar cuentas regresivas en tu paywall. | :::note Si usas varios idiomas, aprende cómo añadir una [localización del Paywall Builder](add-paywall-locale-in-adapty-paywall-builder) y cómo usar los códigos de idioma correctamente [aquí](localizations-and-locale-codes). ::: Una vez que tengas la vista, [presenta el paywall](unity-present-paywalls). ## Personalizar recursos \{#customize-assets\} Para personalizar imágenes y vídeos en tu paywall, implementa los recursos personalizados. Las imágenes y vídeos hero tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de recursos personalizado, apuntas a estos elementos por sus IDs y personalizas su comportamiento. Para otras imágenes y vídeos, necesitas [establecer un ID personalizado](custom-media) en el dashboard de Adapty. Por ejemplo, puedes: - Mostrar una imagen o vídeo diferente a algunos usuarios. - Mostrar una imagen de vista previa local mientras se carga la imagen principal remota. - Mostrar una imagen de vista previa antes de reproducir un vídeo. :::important Para usar esta función, actualiza el SDK de Adapty para Unity a la versión 3.8.0 o superior. ::: A continuación se muestra un ejemplo de cómo proporcionar recursos personalizados mediante un diccionario simple: ```csharp showLineNumbers var customAssets = new Dictionaryopcional
por defecto: `en`
|El identificador de la localización del paywall. Se espera que este parámetro sea un código de idioma compuesto por uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta es para el idioma, la segunda para la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se desinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché de actualización regular descrita arriba y los paywalls de respaldo. También usamos CDN para obtener paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para que siempre obtengas la versión más reciente de tus paywalls, garantizando fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: unity-present-paywalls --- --- title: "Mostrar paywalls" description: "Aprende cómo mostrar paywalls en tu app de Unity con el SDK de Adapty." --- Si has personalizado un paywall con el Paywall Builder, no necesitas preocuparte por renderizarlo en el código de tu app para mostrárselo al usuario. Ese paywall contiene tanto lo que debe mostrarse como la forma en que debe hacerse. :::warning Esta guía cubre el **nuevo Paywall Builder**, que requiere el SDK de Adapty 3.3.0 o posterior. Para mostrar paywalls con Remote Config, consulta [Renderizar paywalls diseñados con remote config](present-remote-config-paywalls). ::: Para mostrar un paywall, usa el método `view.Present()` sobre el `view` creado por el método [`CreatePaywallView`](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder). Cada `view` solo puede usarse una vez. Si necesitas mostrar el paywall de nuevo, llama a `CreatePaywallView` otra vez para crear una nueva instancia de `view`. :::warning Reutilizar el mismo `view` sin recrearlo puede provocar el error `AdaptyUIError.viewAlreadyPresented`. ::: ```csharp showLineNumbers title="Unity" view.Present((error) => { // handle the error }); ``` :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: ## Mostrar diálogo \{#show-dialog\} Usa este método en lugar de los diálogos de alerta nativos cuando hay un paywall visible en Android. En Android, las alertas normales aparecen detrás del paywall y el usuario no puede verlas. Este método garantiza que el diálogo se muestre correctamente por encima del paywall en todas las plataformas. ```csharp showLineNumbers title="Unity" var dialog = new AdaptyUIDialogConfiguration() .SetTitle("Close paywall?") .SetContent("You will lose access to exclusive offers.") .SetDefaultActionTitle("Stay") .SetSecondaryActionTitle("Close"); AdaptyUI.ShowDialog(view, dialog, (action, error) => { if (error == null) { if (action == AdaptyUIDialogActionType.Secondary) { // User confirmed - close the paywall view.Dismiss(); } // If primary - do nothing, user stays } }); ``` ## Configurar el estilo de presentación en iOS \{#configure-ios-presentation-style\} Configura cómo se presenta el paywall en iOS pasando el parámetro `iosPresentationStyle` al método `Present()`. El parámetro acepta los valores `AdaptyUIIOSPresentationStyle.FullScreen` (predeterminado) o `AdaptyUIIOSPresentationStyle.PageSheet`. ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` --- # File: unity-handle-paywall-actions --- --- title: "Responder a acciones de botones en el SDK de Unity" description: "Gestiona las acciones de botones de paywall en Unity usando Adapty para una mejor monetización de la app." --- Si estás creando paywalls con el Paywall Builder de Adapty, es fundamental configurar los botones correctamente: 1. Añade un [botón en el Paywall Builder](paywall-buttons) y asígnale una acción existente o crea un ID de acción personalizado. 2. Escribe código en tu app para gestionar cada acción que hayas asignado. Esta guía muestra cómo gestionar acciones personalizadas y predefinidas en tu código. :::warning **Solo las compras y restauraciones se gestionan automáticamente.** El resto de acciones de botones, como cerrar paywalls o abrir enlaces, requieren implementar respuestas específicas en el código de la app. ::: ## Cerrar paywalls \{#close-paywalls\} Para añadir un botón que cierre tu paywall: 1. En el Paywall Builder, añade un botón y asígnale la acción **Close**. 2. En el código de tu app, implementa un handler para la acción `close` que descarte el paywall. ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: view.Dismiss(null); break; default: // handle other events break; } } ``` ## Abrir URLs desde paywalls \{#open-urls-from-paywalls\} :::tip Si quieres añadir un grupo de enlaces (p. ej., términos de uso y restauración de compras), añade un elemento **Link** en el Paywall Builder y gestíonalo igual que los botones con la acción **Open URL**. ::: Para añadir un botón que abra un enlace desde tu paywall (p. ej., **Terms of use** o **Privacy policy**): 1. En el Paywall Builder, añade un botón, asígnale la acción **Open URL** e introduce la URL que quieres abrir. 2. En el código de tu app, implementa un handler para la acción `openUrl` que abra la URL recibida en un navegador. ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.OpenUrl: var urlString = action.Value; if(!string.IsNullOrWhiteSpace(urlString)) { Application.OpenURL(urlString); } break; default: // handle other events break; } } ``` ## Iniciar sesión en la app \{#log-into-the-app\} Para añadir un botón que permita a los usuarios iniciar sesión en tu app: 1. En el Paywall Builder, añade un botón y asígnale la acción **Custom** con el ID `login`. 2. En el código de tu app, implementa un handler para la acción personalizada `login` que identifique a tu usuario. ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "login") { // Navigate to login scene SceneManager.LoadScene("LoginScene"); } break; default: // handle other events break; } } ``` ## Gestionar acciones personalizadas \{#handle-custom-actions\} Para añadir un botón que gestione cualquier otra acción: 1. En el Paywall Builder, añade un botón, asígnale la acción **Custom** y asígnale un ID. 2. En el código de tu app, implementa un handler para el ID de acción que hayas creado. Por ejemplo, si tienes otro conjunto de ofertas de suscripción o compras únicas, puedes añadir un botón que muestre otro paywall: ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "openNewPaywall") { // Display another paywall ShowAlternativePaywall(); } break; default: // handle other events break; } } private void ShowAlternativePaywall() { // Implement your logic to show alternative paywall } ``` --- # File: unity-handling-events --- --- title: "Gestionar eventos del paywall" description: "Aprende a gestionar eventos del paywall en tu aplicación Unity con el SDK de Adapty." --- :::important Esta guía cubre la gestión de eventos para compras, restauraciones, selección de productos y renderizado del paywall. También debes implementar el manejo de botones (cerrar paywall, abrir enlaces, etc.). Consulta nuestra [guía sobre el manejo de acciones de botones](unity-handle-paywall-actions) para más detalles. ::: Los paywalls configurados con el [Paywall Builder](adapty-paywall-builder) no necesitan código adicional para realizar y restaurar compras. Sin embargo, generan ciertos eventos a los que tu aplicación puede responder. Estos eventos incluyen pulsaciones de botones (botones de cierre, URLs, selecciones de productos, etc.), así como notificaciones sobre acciones relacionadas con compras realizadas en el paywall. A continuación aprenderás cómo responder a estos eventos. :::warning Esta guía es **exclusivamente para paywalls del nuevo Paywall Builder**, que requieren el SDK de Adapty v3.3.0 o posterior. ::: :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: ## Gestión de eventos \{#handling-events\} Para controlar o monitorear los procesos que ocurren en la pantalla del paywall dentro de tu aplicación móvil, implementa la interfaz `AdaptyPaywallsEventsListener`: ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; public class PaywallEventsHandler : MonoBehaviour, AdaptyPaywallsEventsListener { void Start() { Adapty.SetPaywallsEventsListener(this); } // Implement all required interface methods below } ``` ### Eventos generados por el usuario \{#user-generated-events\} #### Paywall mostrado \{#paywall-appeared\} Se invoca cuando la vista del paywall aparece en pantalla. :::note En iOS, también se invoca cuando el usuario pulsa el [botón del web paywall](web-paywall#step-2a-add-a-web-purchase-button) dentro de un paywall y el web paywall se abre en un navegador integrado. ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### Paywall ocultado \{#paywall-disappeared\} Se invoca cuando la vista del paywall desaparece de la pantalla. :::note En iOS, también se invoca cuando un [web paywall](web-paywall#step-2a-add-a-web-purchase-button) abierto desde un paywall en un navegador integrado desaparece de la pantalla. ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### Selección de producto \{#product-selection\} Se invoca cuando se selecciona un producto para comprar (por el usuario o por el sistema). ```csharp showLineNumbers title="Unity" public void PaywallViewDidSelectProduct( AdaptyUIPaywallView view, string productId ) { } ```
## El número de vistas del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El contador de vistas del paywall muestra el doble del número esperado.
**Causa**: Es posible que estés llamando a `LogShowPaywall` en tu código, lo que duplica el contador de vistas cuando se usa el Paywall Builder. Para los paywalls diseñados con el Paywall Builder, el seguimiento de análisis es automático, por lo que no es necesario usar este método.
**Solución**: Asegúrate de no llamar a `LogShowPaywall` en tu código si estás usando el Paywall Builder.
## Otros problemas \{#other-issues\}
**Problema**: Estás experimentando otros problemas relacionados con el Paywall Builder que no se han cubierto anteriormente.
**Solución**: Si es necesario, migra el SDK a la versión más reciente usando las [guías de migración](unity-sdk-migration-guides). Muchos problemas se resuelven en versiones más nuevas del SDK.
---
# File: unity-quickstart-manual
---
---
title: "Habilitar compras en tu paywall personalizado con Unity SDK"
description: "Integra el SDK de Adapty en tus paywalls personalizados de Unity para habilitar compras in-app."
---
Esta guía describe cómo integrar Adapty en tus paywalls personalizados. Mantén el control total sobre la implementación del paywall, mientras el SDK de Adapty obtiene los productos, gestiona las nuevas compras y restaura las anteriores.
:::important
**Esta guía está dirigida a desarrolladores que implementan paywalls personalizados.** Si quieres la forma más sencilla de habilitar compras, usa el [Adapty Paywall Builder](unity-quickstart-paywalls). Con Paywall Builder, creas paywalls en un editor visual sin código, Adapty gestiona toda la lógica de compras automáticamente y puedes probar distintos diseños sin volver a publicar tu app.
:::
## Antes de empezar \{#before-you-start\}
### Configura los productos \{#set-up-products\}
Para habilitar las compras in-app, necesitas entender tres conceptos clave:
- [**Productos**](product) – cualquier cosa que los usuarios pueden comprar (suscripciones, consumibles, acceso de por vida)
- [**Paywalls**](paywalls) – configuraciones que definen qué productos ofrecer. En Adapty, los paywalls son la única forma de obtener productos, pero este diseño te permite modificar productos, precios y ofertas sin tocar el código de tu app.
- [**Placements**](placements) – dónde y cuándo muestras los paywalls en tu app (como `main`, `onboarding`, `settings`). Configuras los paywalls para los placements en el dashboard y luego los solicitas por ID de placement en tu código. Esto facilita ejecutar pruebas A/B y mostrar distintos paywalls a diferentes usuarios.
Asegúrate de entender estos conceptos incluso si trabajas con tu paywall personalizado. Básicamente, son solo tu forma de gestionar los productos que vendes en tu app.
Para implementar tu paywall personalizado, necesitarás crear un **paywall** y añadirlo a un **placement**. Esta configuración te permite obtener tus productos. Para saber qué debes hacer en el dashboard, sigue la guía de inicio rápido [aquí](quickstart).
### Gestiona usuarios \{#manage-users\}
Puedes trabajar con o sin autenticación de backend en tu lado.
Sin embargo, el SDK de Adapty gestiona de forma diferente a los usuarios anónimos e identificados. Lee la [guía de inicio rápido de identificación](unity-quickstart-identify) para entender las particularidades y asegurarte de que trabajas correctamente con los usuarios.
## Paso 1. Obtén los productos \{#step-1-get-products\}
Para obtener los productos de tu paywall personalizado, necesitas:
1. Obtener el objeto `paywall` pasando el ID del [placement](placements) al método `getPaywall`.
2. Obtener el array de productos para este paywall usando el método `getPaywallProducts`.
```csharp showLineNumbers
using AdaptySDK;
void LoadPaywall() {
Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => {
if (error != null) {
// Handle the error
return;
}
Adapty.GetPaywallProducts(paywall, (products, productsError) => {
if (productsError != null) {
// Handle the error
return;
}
// Use products to build your custom paywall UI
});
});
}
```
## Paso 2. Acepta compras \{#step-2-accept-purchases\}
Cuando un usuario toca un producto en tu paywall personalizado, llama al método `makePurchase` con el producto seleccionado. Esto gestionará el flujo de compra y devolverá el perfil actualizado.
```csharp showLineNumbers
using AdaptySDK;
void PurchaseProduct(AdaptyPaywallProduct product) {
Adapty.MakePurchase(product, (result, error) => {
if (error != null) {
// Handle the error
return;
}
switch (result.Type) {
case AdaptyPurchaseResultType.Success:
var profile = result.Profile;
// Purchase successful, profile updated
break;
case AdaptyPurchaseResultType.UserCancelled:
// User canceled the purchase
break;
case AdaptyPurchaseResultType.Pending:
// Purchase is pending (e.g., user will pay offline with cash)
break;
}
});
}
```
## Paso 3. Restaura compras \{#step-3-restore-purchases\}
Los app stores requieren que todas las apps con suscripciones ofrezcan una forma de que los usuarios puedan restaurar sus compras.
Llama al método `restorePurchases` cuando el usuario toque el botón de restaurar. Esto sincronizará su historial de compras con Adapty y devolverá el perfil actualizado.
```csharp showLineNumbers
using AdaptySDK;
void RestorePurchases() {
Adapty.RestorePurchases((profile, error) => {
if (error != null) {
// Handle the error
return;
}
// Restore successful, profile updated
});
}
```
## Próximos pasos \{#next-steps\}
---
no_index: true
---
import Callout from '../../../components/Callout.astro';
opcional
por defecto: `en`
|El identificador de la [localización del paywall](add-remote-config-locale). Se espera que este parámetro sea un código de idioma compuesto por una o más subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de idioma](unity-localizations-and-locale-codes) para más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexiones a internet inestables, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché actualizada regularmente descrita anteriormente y los [paywalls de respaldo](unity-use-fallback-paywalls). También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no esté disponible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo límite, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que en casos excepcionales este método puede superar ligeramente el tiempo especificado en `loadTimeout`, ya que la operación puede constar de diferentes solicitudes internamente.
| ¡No escribas los IDs de producto en el código! Dado que los paywalls se configuran de forma remota, los productos disponibles, el número de productos y las ofertas especiales (como pruebas gratuitas) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, tu app debería mostrar esos 2 productos. Sin embargo, si más adelante obtienes 3 productos, tu app debería mostrar los 3 sin requerir cambios en el código. Lo único que tienes que incluir en el código es el ID del placement. Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | Un objeto [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) con: una lista de IDs de producto, el identificador del paywall, el Remote Config y varias otras propiedades. | ## Obtener productos \{#fetch-products\} Una vez que tienes el paywall, puedes consultar el array de productos correspondiente: ```csharp showLineNumbers Adapty.GetPaywallProducts(paywall, (products, error) => { if(error != null) { // handle the error return; } // products - the requested products array }); ``` Parámetros de respuesta: | Parámetro | Descripción | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | Lista de objetos [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) con: identificador del producto, nombre del producto, precio, moneda, duración de la suscripción y varias otras propiedades. | Al implementar tu propio diseño de paywall, probablemente necesitarás acceder a estas propiedades del objeto [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html). A continuación se muestran las propiedades más utilizadas, pero consulta el documento enlazado para obtener todos los detalles de las propiedades disponibles. | Propiedad | Descripción | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | Para mostrar el título del producto, usa `product.LocalizedTitle`. Ten en cuenta que la localización se basa en el país del store seleccionado por el usuario, no en el idioma del propio dispositivo. | | **Price** | Para mostrar una versión localizada del precio, usa `product.Price.LocalizedString`. Esta localización se basa en la configuración regional del dispositivo. También puedes acceder al precio como número usando `product.Price.Amount`. El valor se proporcionará en la moneda local. Para obtener el símbolo de moneda asociado, usa `product.Price.CurrencySymbol`. | | **Subscription Period** | Para mostrar el período (p. ej., semana, mes, año, etc.), usa `product.Subscription?.LocalizedPeriod`. Esta localización se basa en la configuración regional del dispositivo. Para obtener el período de suscripción mediante programación, usa `product.Subscription?.Period`. Desde ahí puedes acceder al enum `Unit` para obtener la duración (es decir, `AdaptySubscriptionPeriodUnit.Day`, `AdaptySubscriptionPeriodUnit.Week`, `AdaptySubscriptionPeriodUnit.Month`, `AdaptySubscriptionPeriodUnit.Year` o `AdaptySubscriptionPeriodUnit.Unknown`). El valor `NumberOfUnits` te dará el número de unidades del período. Por ejemplo, para una suscripción trimestral, verías `AdaptySubscriptionPeriodUnit.Month` en la propiedad Unit y `3` en la propiedad NumberOfUnits. | | **Introductory Offer** | Para mostrar un distintivo u otro indicador de que una suscripción incluye una oferta introductoria, revisa la propiedad `product.Subscription?.Offer?.Phases`. Esta es una lista que puede contener hasta dos fases de descuento: la fase de prueba gratuita y la fase de precio introductorio. Dentro de cada objeto de fase están las siguientes propiedades útiles:opcional
por defecto: `en`
|El identificador de la localización del paywall. Se espera que este parámetro sea un código de idioma compuesto por una o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre obtengan los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen conexiones a internet inestables, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, los usuarios podrían no obtener los datos más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de la calidad de su conexión. La caché se actualiza regularmente, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché actualizada regularmente descrita anteriormente y los paywalls de respaldo. También usamos CDN para obtener los paywalls más rápido y un servidor de respaldo independiente en caso de que el CDN no esté disponible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus paywalls, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: present-remote-config-paywalls-unity --- --- title: "Renderizar paywall diseñado con Remote Config en Unity SDK" description: "Descubre cómo presentar paywalls con Remote Config en Adapty Unity SDK para personalizar la experiencia de usuario." --- Si has personalizado un paywall usando Remote Config, necesitarás implementar el renderizado en el código de tu app para mostrárselo a los usuarios. Como Remote Config ofrece flexibilidad adaptada a tus necesidades, tú decides qué incluir y cómo se ve tu paywall. Proporcionamos un método para obtener la configuración remota, dándote la autonomía de mostrar tu paywall personalizado configurado a través de Remote Config. ## Obtener el Remote Config del paywall y presentarlo \{#get-paywall-remote-config-and-present-it\} Para obtener el Remote Config de un paywall, accede a la propiedad `remoteConfig` y extrae los valores que necesites. ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // handle the error return; } // Access remote config dictionary var dictionary = paywall.RemoteConfig?.Dictionary; var headerText = dictionary?["header_text"] as string; // Or access raw JSON data var jsonData = paywall.RemoteConfig?.Data; }); ``` En este punto, una vez que hayas recibido todos los valores necesarios, es momento de renderizarlos y ensamblarlos en una página visualmente atractiva. Asegúrate de que el diseño se adapte a distintos tamaños de pantalla y orientaciones de dispositivos móviles, garantizando una experiencia fluida y amigable en todos los dispositivos. :::warning Asegúrate de [registrar el evento de visualización del paywall](present-remote-config-paywalls-unity#track-paywall-view-events) tal como se describe a continuación, para que los análisis de Adapty puedan recopilar información para los embudos y las pruebas A/B. ::: Una vez que hayas terminado de mostrar el paywall, continúa configurando el flujo de compra. Cuando el usuario realice una compra, simplemente llama a `.MakePurchase()` con el producto de tu paywall. Para más detalles sobre el método `.MakePurchase()`, consulta [Realizar compras](unity-making-purchases). Te recomendamos [crear un paywall de respaldo denominado paywall de respaldo](unity-use-fallback-paywalls). Este respaldo se mostrará al usuario cuando no haya conexión a internet ni caché disponible, garantizando una experiencia fluida incluso en esas situaciones. ## Registrar eventos de visualización del paywall \{#track-paywall-view-events\} Adapty te ayuda a medir el rendimiento de tus paywalls. Aunque recopilamos datos de compras automáticamente, registrar las visualizaciones del paywall requiere tu intervención, ya que solo tú sabes cuándo un usuario ve un paywall. Para registrar un evento de visualización del paywall, simplemente llama a `.LogShowPaywall(paywall)` y se reflejará en las métricas de tu paywall en los embudos y las pruebas A/B. :::important No es necesario llamar a `.LogShowPaywall(paywall)` si estás mostrando paywalls creados en el [Paywall Builder](adapty-paywall-builder). ::: ```csharp showLineNumbers Adapty.LogShowPaywall(paywall, (error) => { // handle the error }); ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :-------- |:------------------------------------------------------------------| | **paywall** | obligatorio | Un objeto [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html). | --- # File: unity-making-purchases --- --- title: "Realizar compras in-app en Unity SDK" description: "Guía sobre cómo gestionar compras in-app y suscripciones usando Adapty." --- Mostrar paywalls en tu app es un paso fundamental para ofrecer a los usuarios acceso a contenido o servicios premium. Sin embargo, mostrarlos es suficiente para gestionar las compras solo si usas el [Paywall Builder](adapty-paywall-builder) para personalizar tus paywalls. Si no usas el Paywall Builder, debes usar un método independiente llamado `.makePurchase()` para completar una compra y desbloquear el contenido deseado. Este método es la puerta de entrada para que los usuarios interactúen con los paywalls y completen sus transacciones. Si tu paywall tiene una oferta promocional activa para el producto que el usuario intenta comprar, Adapty la aplicará automáticamente en el momento de la compra. :::warning Ten en cuenta que la oferta introductoria se aplicará automáticamente solo si usas paywalls configurados con el Paywall Builder. En otros casos, deberás [verificar la elegibilidad del usuario para una oferta introductoria en iOS](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios). Omitir este paso puede provocar que tu app sea rechazada durante la revisión. Además, podría suponer cobrar el precio completo a usuarios que tienen derecho a una oferta introductoria. ::: Asegúrate de haber completado la [configuración inicial](quickstart) sin saltarte ningún paso. Sin ella, no podemos validar las compras. ## Realizar una compra \{#make-purchase\} :::note **¿Usas el [Paywall Builder](adapty-paywall-builder)?** Las compras se procesan automáticamente; puedes saltarte este paso. **¿Buscas una guía paso a paso?** Consulta la [guía de inicio rápido](unity-implement-paywalls-manually) para instrucciones de implementación completas con todo el contexto. ::: ```csharp showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { switch (result.Type) { case AdaptyPurchaseResultType.Pending: // handle pending purchase break; case AdaptyPurchaseResultType.UserCancelled: // handle purchase cancellation break; case AdaptyPurchaseResultType.Success: var profile = result.Profile; // handle successfull purchase break; default: break; } }); } ``` Parámetros de la solicitud: | Parámetro | Presencia | Descripción | | :---------- | :------- |:------------------------------------------------------------------------------------------------------| | **Product** | obligatorio | Un objeto [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) obtenido del paywall. | Parámetros de la respuesta: | Parámetro | Descripción | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |Si la solicitud fue exitosa, la respuesta incluye este objeto. Un objeto [AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) proporciona información completa sobre los niveles de acceso, suscripciones y compras únicas del usuario dentro de la app.
Verifica el estado del nivel de acceso para confirmar si el usuario tiene el acceso requerido a la app.
| :::warning **Nota:** si todavía usas la versión de StoreKit de Apple inferior a v2.0 y la versión del SDK de Adapty inferior a v.2.9.0, debes proporcionar el [secreto compartido de App Store de Apple](app-store-connection-configuration#step-5-enter-app-store-shared-secret) en su lugar. Este método está actualmente deprecado por Apple. ::: ## Cambiar la suscripción al realizar una compra \{#change-subscription-when-making-a-purchase\} Cuando un usuario elige una nueva suscripción en lugar de renovar la actual, el funcionamiento depende del store: - En el App Store, la suscripción se actualiza automáticamente dentro del grupo de suscripciones. Si un usuario compra una suscripción de un grupo mientras ya tiene una suscripción de otro, ambas suscripciones estarán activas al mismo tiempo. - En Google Play, la suscripción no se actualiza automáticamente. Deberás gestionar el cambio en el código de tu app como se describe a continuación. Para reemplazar la suscripción por otra en Android, llama al método `.makePurchase()` con el parámetro adicional: ```csharp showLineNumbers // Create subscription update parameters var subscriptionUpdateParams = new AdaptySubscriptionUpdateParameters( "old_product_id", // Product ID of the current subscription AdaptySubscriptionUpdateReplacementMode.WithTimeProration ); Adapty.MakePurchase(product, subscriptionUpdateParams, (profile, error) => { if(error != null) { // Handle the error return; } // successful cross-grade }); ``` Parámetro adicional de la solicitud: | Parámetro | Presencia | Descripción | | :--------------------------- | :------- |:-------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | obligatorio | Un objeto [`AdaptySubscriptionUpdateParameters`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_subscription_update_parameters.html). | Puedes leer más sobre suscripciones y modos de reemplazo en la documentación para desarrolladores de Google: - [Acerca de los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Recomendaciones de Google para los modos de reemplazo](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - Modo de reemplazo [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE()). Nota: este método solo está disponible para actualizaciones de suscripción. No se admiten degradaciones. - Modo de reemplazo [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED()). Nota: el cambio real de suscripción solo ocurrirá cuando finalice el período de facturación de la suscripción actual. ## Canjear códigos de oferta en iOS \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro';Un objeto [`AdaptyProfile`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html). Este modelo contiene información sobre los niveles de acceso, suscripciones y compras únicas.
Comprueba el **estado del nivel de acceso** para determinar si el usuario tiene acceso a la app.
| :::tip ¿Quieres ver un ejemplo real de cómo se integra el SDK de Adapty en una app móvil? Echa un vistazo a nuestras [apps de ejemplo](sample-apps), que muestran la configuración completa, incluyendo la visualización de paywalls, la realización de compras y otras funcionalidades básicas. ::: --- # File: implement-observer-mode-unity --- --- title: "Implementar el modo Observer en el SDK de Unity" description: "Implementa el modo observer en Adapty para registrar eventos de suscripción de usuarios en el SDK de Unity." --- Si ya tienes tu propia infraestructura de compras y no estás listo para migrar completamente a Adapty, puedes explorar el [modo Observer](observer-vs-full-mode). En su forma básica, el modo Observer ofrece analíticas avanzadas e integración fluida con sistemas de atribución y analíticas. Si esto cubre tus necesidades, solo tienes que: 1. Activarlo al configurar el SDK de Adapty estableciendo el parámetro `observerMode` en `true`. Sigue las instrucciones de configuración para [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk). 2. [Reportar transacciones](report-transactions-observer-mode-unity) desde tu infraestructura de compras existente a Adapty. ### Configuración del modo Observer \{#observer-mode-setup\} Activa el modo Observer si gestionas las compras y el estado de suscripción por tu cuenta y utilizas Adapty para enviar eventos de suscripción y analíticas. :::important Cuando se ejecuta en modo Observer, el SDK de Adapty no cerrará ninguna transacción, así que asegúrate de gestionarlo tú mismo. ::: ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { void Start() { DontDestroyOnLoad(this.gameObject); Adapty.SetEventListener(this); var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetObserverMode(true); // Enable observer mode Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); } public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` Parámetros: | Parámetro | Descripción | |--------------|----------------------------------------------------------------------------------------------------------------| | observerMode | Un valor booleano que controla el [modo Observer](observer-vs-full-mode). El valor por defecto es `false`. | ## Usar los paywalls de Adapty en el modo Observer \{#using-adapty-paywalls-in-observer-mode\} Si también quieres usar los paywalls y las funciones de pruebas A/B de Adapty, puedes hacerlo, pero requiere algo de configuración adicional en el modo Observer. Esto es lo que necesitarás hacer además de los pasos anteriores: 1. Muestra los paywalls de la forma habitual para [paywalls con Remote Config](present-remote-config-paywalls-unity). 3. [Asocia los paywalls](report-transactions-observer-mode-unity) con las transacciones de compra. --- # File: report-transactions-observer-mode-unity --- --- title: "Reportar transacciones en Observer Mode en el SDK de Unity" description: "Reporta transacciones de compras en el Observer Mode de Adapty para obtener información sobre usuarios y seguimiento de ingresos en el SDK de Unity." ---Para iOS, StoreKit 1: un objeto [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction).
Para iOS, StoreKit 2: objeto [Transaction](https://developer.apple.com/documentation/storekit/transaction).
Para Android: Identificador de cadena (purchase.getOrderId de la compra, donde la compra es una instancia de la clase [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) de la biblioteca de facturación).
| | variationId | requerido | El identificador de cadena de la variante. Puedes obtenerlo usando la propiedad `variationId` del objeto [AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html). |phoneNumber
firstName
lastName
| String | | gender | Enum, los valores permitidos son: `female`, `male`, `other` | | birthday | Date | ### Atributos de usuario personalizados \{#custom-user-attributes\} Puedes definir tus propios atributos personalizados. Normalmente están relacionados con el uso de tu app. Por ejemplo, en apps de fitness podrían ser el número de ejercicios por semana; en apps de aprendizaje de idiomas, el nivel de conocimiento del usuario, etc. Puedes utilizarlos en segmentos para crear paywalls y ofertas segmentadas, y también en análisis para identificar qué métricas de producto influyen más en los ingresos. ```csharp showLineNumbers try { builder = builder.SetCustomStringAttribute("string_key", "string_value"); builder = builder.SetCustomDoubleAttribute("double_key", 123.0f); } catch (Exception e) { // handle the exception } ``` Para eliminar una clave existente, usa el método `.withRemoved(customAttributeForKey:)`: ```csharp showLineNumbers try { builder = builder.RemoveCustomAttribute("key_to_remove"); } catch (Exception e) { // handle the exception } ``` A veces necesitas saber qué atributos personalizados ya se han establecido. Para ello, usa el campo `customAttributes` del objeto `AdaptyProfile`. :::warning Ten en cuenta que el valor de `customAttributes` puede estar desactualizado, ya que los atributos de usuario pueden enviarse desde distintos dispositivos en cualquier momento, por lo que los atributos en el servidor pueden haber cambiado desde la última sincronización. ::: ### Límites \{#limits\} - Hasta 30 atributos personalizados por usuario - Los nombres de clave pueden tener hasta 30 caracteres. El nombre de la clave puede incluir caracteres alfanuméricos y cualquiera de los siguientes: `_` `-` `.` - El valor puede ser una cadena de texto o un número flotante con un máximo de 50 caracteres. --- # File: unity-listen-subscription-changes --- --- title: "Comprobar el estado de la suscripción en Unity SDK" description: "Rastrea y gestiona el estado de la suscripción del usuario en Adapty para mejorar la retención de clientes en tu aplicación Unity." --- Con Adapty, hacer seguimiento del estado de la suscripción es muy sencillo. No tienes que insertar manualmente los IDs de producto en tu código. En cambio, puedes confirmar fácilmente el estado de suscripción de un usuario comprobando si tiene un [nivel de acceso](access-level) activo.Un objeto [AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html). En general, solo tienes que comprobar el estado del nivel de acceso del perfil para determinar si el usuario tiene acceso premium a la app.
El método `.getProfile` proporciona el resultado más actualizado, ya que siempre intenta consultar la API. Si por algún motivo (por ejemplo, sin conexión a internet) el SDK de Adapty no puede obtener información del servidor, se devuelven los datos de la caché. También es importante tener en cuenta que el SDK de Adapty actualiza la caché de `AdaptyProfile` de forma periódica para mantener esta información lo más actualizada posible.
| El método `.getProfile()` te proporciona el perfil del usuario a partir del cual puedes obtener el estado del nivel de acceso. Puedes tener múltiples niveles de acceso por app. Por ejemplo, si tienes una app de noticias y vendes suscripciones a diferentes temáticas de forma independiente, puedes crear los niveles de acceso "sports" y "science". Sin embargo, la mayoría de las veces solo necesitarás un nivel de acceso; en ese caso, puedes usar simplemente el nivel de acceso "premium" predeterminado. Aquí tienes un ejemplo para comprobar el nivel de acceso "premium" predeterminado: ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // "premium" is an identifier of default access level var accessLevel = profile.AccessLevels["premium"]; if (accessLevel != null && accessLevel.IsActive) { // grant access to premium features } }); ``` ### Escuchar actualizaciones del estado de la suscripción \{#listening-for-subscription-status-updates\} Cada vez que la suscripción del usuario cambia, Adapty lanza un evento. Para recibir mensajes de Adapty, necesitas hacer una configuración adicional: ```csharp showLineNumbers // Extend `AdaptyEventListener ` with `OnLoadLatestProfile ` method: public class AdaptyListener : MonoBehaviour, AdaptyEventListener { public void OnLoadLatestProfile(AdaptyProfile profile) { // handle any changes to subscription state } } ``` Adapty también lanza un evento al inicio de la aplicación. En ese caso, se pasará el estado de suscripción almacenado en caché. ### Caché del estado de la suscripción \{#subscription-status-cache\} La caché implementada en el SDK de Adapty almacena el estado de suscripción del perfil. Esto significa que, incluso si el servidor no está disponible, se puede acceder a los datos en caché para obtener información sobre el estado de suscripción del perfil. No obstante, hay que tener en cuenta que no es posible solicitar datos directamente desde la caché. El SDK consulta periódicamente el servidor cada minuto para comprobar si hay actualizaciones o cambios relacionados con el perfil. Si hay modificaciones, como nuevas transacciones u otras actualizaciones, se enviarán a los datos en caché para mantenerlos sincronizados con el servidor. --- # File: unity-deal-with-att --- --- title: "Gestionar ATT en el SDK de Unity" description: "Comienza con Adapty en Unity para simplificar la configuración y gestión de suscripciones." --- Si tu aplicación utiliza el framework AppTrackingTransparency y presenta al usuario una solicitud de autorización de seguimiento de la app, debes enviar el [estado de autorización](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) a Adapty. ```csharp showLineNumbers var builder = new Adapty.ProfileParameters.Builder() .SetAppTrackingTransparencyStatus(IOSAppTrackingTransparencyStatus.Authorized); Adapty.UpdateProfile(builder.Build(), (error) => { if(error != null) { // handle the error } }); ``` :::warning Te recomendamos encarecidamente que envíes este valor lo antes posible cuando cambie; solo así los datos se enviarán a tiempo a las integraciones que hayas configurado. ::: --- # File: kids-mode-unity --- --- title: "Kids Mode en Unity SDK" description: "Activa fácilmente el Modo Niños para cumplir con las políticas de Apple y Google. No se recopilan IDFA, GAID ni datos publicitarios en Unity SDK." --- Si tu aplicación Unity está destinada a niños, debes seguir las políticas de [Apple](https://developer.apple.com/kids/) y [Google](https://support.google.com/googleplay/android-developer/answer/9893335). Si usas el SDK de Adapty, unos pocos pasos sencillos te ayudarán a configurarlo para cumplir con estas políticas y superar las revisiones de las tiendas. ## ¿Qué se necesita? \{#whats-required\} Debes configurar el SDK de Adapty para desactivar la recopilación de: - [IDFA (Identifier for Advertisers)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) (iOS) - [Android Advertising ID (AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) (Android) - [Dirección IP](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) Además, te recomendamos usar el ID de usuario del cliente con cuidado. Un ID en formato `opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto de uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
Consulta [Localizaciones y códigos de localización](flutter-localizations-and-locale-codes) para más información sobre los códigos de localización y cómo recomendamos usarlos.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, es posible que los usuarios no obtengan los datos absolutamente más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo inestable que sea su conexión. La caché se actualiza con regularidad, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché actualizada periódicamente descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| | **loadTimeout** | por defecto: 5 seg |Este valor limita el tiempo de espera para este método. Si se alcanza el tiempo de espera, se devolverán los datos en caché o el respaldo local.
Ten en cuenta que, en casos excepcionales, este método puede agotar el tiempo de espera un poco más tarde de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes solicitudes internas.
| Parámetros de respuesta: | Parámetro | Descripción | |:----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | Un objeto [`AdaptyOnboarding`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_onboarding.html) con: el identificador y la configuración del onboarding, Remote Config y otras propiedades. | Tras obtener el onboarding, llama al método `CreateOnboardingView`. :::warning El resultado del método `CreateOnboardingView` solo puede usarse una vez. Si necesitas usarlo de nuevo, llama al método `CreateOnboardingView` otra vez. Llamarlo dos veces sin volver a crearlo puede provocar el error `AdaptyUIError.viewAlreadyPresented`. ::: ```csharp showLineNumbers AdaptyUI.CreateOnboardingView(onboarding, (view, error) => { // handle the result }); ``` Parámetros: | Parámetro | Presencia | Descripción | |:---------------| :------------- |:-----------------------------------------------------------------------------| | **onboarding** | obligatorio | Un objeto `AdaptyOnboarding` para obtener una vista del onboarding deseado. | | **externalUrlsPresentation** |opcional
por defecto: `InAppBrowser`
|Controla cómo se abren los enlaces en el onboarding. Opciones disponibles:
- `AdaptyWebPresentation.InAppBrowser` - Abre los enlaces en un navegador dentro de la app (por defecto)
- `AdaptyWebPresentation.ExternalBrowser` - Abre los enlaces en el navegador externo del dispositivo
Consulta [Personalizar cómo se abren los enlaces en los onboardings](unity-present-onboardings#customize-how-links-open-in-onboardings) para ver ejemplos de uso.
| Una vez que hayas cargado correctamente el onboarding y su configuración de vista, puedes [mostrarlo en tu app móvil](unity-present-onboardings). ## Acelerar la obtención del onboarding con el onboarding de audiencia por defecto \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} Normalmente, los onboardings se obtienen casi de inmediato, por lo que no necesitas preocuparte por acelerar este proceso. Sin embargo, en los casos en que tienes numerosas audiencias y onboardings, y tus usuarios tienen una conexión a internet débil, obtener un onboarding puede tardar más de lo que te gustaría. En estas situaciones, puede que quieras mostrar un onboarding por defecto para garantizar una experiencia de usuario fluida en lugar de no mostrar ninguno. Para resolver esto, puedes usar el método `GetOnboardingForDefaultAudience`, que obtiene el onboarding del placement especificado para la audiencia **All Users**. Sin embargo, es fundamental entender que el enfoque recomendado es obtener el onboarding con el método `getOnboarding`, tal como se detalla en la sección [Obtener el onboarding](#fetch-onboarding) anterior. :::warning Considera usar `GetOnboarding` en lugar de `GetOnboardingForDefaultAudience`, ya que este último tiene limitaciones importantes: - **Problemas de compatibilidad**: Puede generar problemas al admitir varias versiones de la app, lo que requiere diseños compatibles con versiones anteriores o aceptar que las versiones más antiguas puedan mostrarse incorrectamente. - **Sin personalización**: Solo muestra contenido para la audiencia "All Users", eliminando la segmentación basada en país, atribución o atributos personalizados. Si una obtención más rápida supera estos inconvenientes para tu caso de uso, usa `GetOnboardingForDefaultAudience` como se muestra a continuación. De lo contrario, usa `GetOnboarding` como se describe [arriba](#fetch-onboarding). ::: ```csharp showLineNumbers Adapty.GetOnboardingForDefaultAudience("YOUR_PLACEMENT_ID", (onboarding, error) => { if (error != null) { // handle the error return; } // the requested onboarding }); ``` Parámetros: | Parámetro | Presencia | Descripción | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | obligatorio | El identificador del [Placement](placements) deseado. Es el valor que especificaste al crear un placement en el Adapty Dashboard. | | **locale** |opcional
por defecto: `en`
|El identificador de la localización del onboarding. Se espera que este parámetro sea un código de idioma compuesto de uno o dos subetiquetas separadas por el carácter menos (**-**). La primera subetiqueta corresponde al idioma y la segunda a la región.
Ejemplo: `en` significa inglés, `pt-br` representa el portugués de Brasil.
| | **fetchPolicy** | por defecto: `.reloadRevalidatingCacheData` |Por defecto, el SDK intentará cargar los datos desde el servidor y devolverá los datos en caché en caso de fallo. Recomendamos esta opción porque garantiza que tus usuarios siempre reciban los datos más actualizados.
Sin embargo, si crees que tus usuarios tienen una conexión a internet inestable, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En este caso, es posible que los usuarios no obtengan los datos absolutamente más recientes, pero experimentarán tiempos de carga más rápidos, independientemente de lo inestable que sea su conexión. La caché se actualiza con regularidad, por lo que es seguro usarla durante la sesión para evitar solicitudes de red.
Ten en cuenta que la caché permanece intacta al reiniciar la app y solo se borra cuando se reinstala la app o mediante limpieza manual.
El SDK de Adapty almacena los onboardings localmente en dos capas: la caché actualizada periódicamente descrita anteriormente y los onboardings de respaldo. También usamos CDN para obtener los onboardings más rápido y un servidor de respaldo independiente en caso de que el CDN no sea accesible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings, asegurando la fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: unity-present-onboardings --- --- title: "Presentar onboardings en Unity SDK" description: "Aprende a presentar onboardings de manera efectiva para impulsar más conversiones." --- Si has personalizado un onboarding usando el builder, no necesitas preocuparte por renderizarlo en el código de tu app Unity para mostrárselo al usuario. Dicho onboarding contiene tanto lo que debe mostrarse dentro del onboarding como la forma en que debe mostrarse. Antes de empezar, asegúrate de que: 1. Tienes instalado el [SDK de Adapty para Unity](sdk-installation-unity) 3.14.0 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). Para mostrar un onboarding, usa el método `view.Present()` sobre el `view` creado por el método `CreateOnboardingView`. Cada `view` solo puede usarse una vez. Si necesitas mostrar el paywall de nuevo, llama a `CreateOnboardingView` otra vez para crear una nueva instancia de `view`. :::warning Reutilizar el mismo `view` sin recrearlo puede producir un error `AdaptyUIError.viewAlreadyPresented`. ::: ```csharp showLineNumbers title="Unity" view.Present((presentError) => { if (presentError != null) { // handle the error } }; ``` ## Configurar el estilo de presentación en iOS \{#configure-ios-presentation-style\} Configura cómo se presenta el onboarding en iOS pasando el parámetro `iosPresentationStyle` al método `Present()`. El parámetro acepta los valores `AdaptyUIIOSPresentationStyle.FullScreen` (predeterminado) o `AdaptyUIIOSPresentationStyle.PageSheet`. ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` ## Personalizar cómo se abren los enlaces en los onboardings \{#customize-how-links-open-in-onboardings\} :::important La personalización de cómo se abren los enlaces en los onboardings está disponible a partir del SDK de Adapty v. 3.15. ::: Por defecto, los enlaces en los onboardings se abren en un navegador integrado en la app, lo que ofrece una experiencia fluida al mostrar las páginas web dentro de tu aplicación sin cambiar de app. Para abrir los enlaces en un navegador externo en su lugar, pasa `AdaptyWebPresentation.ExternalBrowser` al método `CreateOnboardingView`: ```csharp showLineNumbers title="Unity" AdaptyUI.CreateOnboardingView( onboarding, AdaptyWebPresentation.ExternalBrowser, // default — InAppBrowser (view, error) => { if (error != null) { // handle the error return; } // present the onboarding view view.Present((presentError) => { if (presentError != null) { // handle the error } }); } ); ``` Opciones disponibles: - `AdaptyWebPresentation.InAppBrowser` - Abre los enlaces en un navegador integrado en la app (predeterminado) - `AdaptyWebPresentation.ExternalBrowser` - Abre los enlaces en el navegador externo del dispositivo --- # File: unity-handling-onboarding-events --- --- title: "Gestionar eventos de onboarding en Unity SDK" description: "Gestiona eventos relacionados con el onboarding en Unity usando Adapty." --- Antes de empezar, asegúrate de que: 1. Tienes instalado el [SDK de Adapty para Unity](sdk-installation-unity) 3.14.0 o posterior. 2. Has [creado un onboarding](create-onboarding). 3. Has añadido el onboarding a un [placement](placements). Los onboardings configurados con el builder generan eventos a los que tu app puede responder. A continuación aprenderás cómo responder a esos eventos. Para controlar o monitorizar los procesos que ocurren en la pantalla de onboarding dentro de tu app de Unity, implementa la interfaz `AdaptyOnboardingsEventsListener`. ## Acciones personalizadas \{#custom-actions\} En el builder puedes añadir una acción **custom** a un botón y asignarle un ID.
Luego puedes usar ese ID en tu código y gestionarlo como una acción personalizada. Por ejemplo, si un usuario pulsa un botón personalizado como **Login** o **Allow notifications**, se activará el método `OnboardingViewOnCustomAction` con el parámetro `actionId` igual al **Action ID** definido en el builder. Puedes crear tus propios IDs, como "allowNotifications".
Para gestionar los eventos del onboarding, implementa la interfaz `AdaptyOnboardingsEventsListener`:
```csharp showLineNumbers title="Unity"
public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener
{
void Start()
{
Adapty.SetOnboardingsEventsListener(this);
}
public void OnboardingViewOnCustomAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
string actionId
)
{
if (actionId == "allowNotifications") {
// request notification permissions
}
}
public void OnboardingViewDidFailWithError(
AdaptyUIOnboardingView view,
AdaptyError error
)
{
// handle errors
}
// Implement other required interface methods (see examples below)
}
```
:::important
Ten en cuenta que debes gestionar qué ocurre cuando el usuario cierra el onboarding. Por ejemplo, necesitas dejar de mostrar el onboarding en sí.
:::
Implementa el método `OnboardingViewOnCloseAction` en tu clase:
```csharp showLineNumbers title="Unity"
public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener
{
public void OnboardingViewOnCloseAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
string actionId
)
{
view.Dismiss((error) => {
if (error != null) {
// handle the error
}
});
}
// ... other interface methods
}
```
2. Haz clic en el nombre del grupo de suscripción. Verás tus productos listados en la sección **Subscriptions**.
3. Asegúrate de que el producto que estás probando aparece como **Ready to Submit**.
4. Compara el ID del producto de la tabla con el que aparece en la pestaña [**Products**](https://app.adapty.io/products) del Adapty Dashboard. Si los IDs no coinciden, copia el ID del producto de la tabla y [crea un producto](create-product) con ese ID en el Adapty Dashboard.
## Paso 3. Comprueba la disponibilidad del producto \{#step-4-check-product-availability\}
1. Vuelve a **App Store Connect** y abre la misma sección **Subscriptions**.
2. Haz clic en el nombre del grupo de suscripción para ver tus productos.
3. Selecciona el producto que estás probando.
4. Desplázate hasta la sección **Availability** y comprueba que todos los países y regiones requeridos están en la lista.
## Paso 4. Comprueba los precios del producto \{#step-5-check-product-prices\}
1. De nuevo, ve a la sección **Monetization** → **Subscriptions** en **App Store Connect**.
2. Haz clic en el nombre del grupo de suscripción.
3. Selecciona el producto que estás probando.
4. Desplázate hacia abajo hasta **Subscription Pricing** y despliega la sección **Current Pricing for New Subscribers**.
5. Asegúrate de que todos los precios requeridos están en la lista.
## Paso 5. Comprueba que el estado de pago de la app, la cuenta bancaria y los formularios fiscales están activos \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. En la página de inicio de [**App Store Connect**](https://appstoreconnect.apple.com/), haz clic en **Business**.
2. Selecciona el nombre de tu empresa.
3. Desplázate hacia abajo y comprueba que tu **Paid Apps Agreement**, **Bank Account** y **Tax forms** aparecen todos como **Active**.
Siguiendo estos pasos deberías poder resolver la advertencia `InvalidProductIdentifiers` y publicar tus productos en el store.
## Paso 6. Vuelve a crear el producto si está bloqueado \{#step-6-recreate-the-product-if-its-stuck\}
Puede que los pasos 1 a 5 pasen todos correctamente — estado `Approved`, Bundle ID correcto, API key válida — y aun así el SDK siga devolviendo `1000 noProductIDsFound`. En ese caso, es posible que el producto esté bloqueado en el registro de Apple. El registro de productos de Apple puede entrar en un estado en el que un producto existe en la interfaz de App Store Connect pero no está expuesto en la ruta de búsqueda de StoreKit.
Elimina el producto en App Store Connect y vuelve a crearlo con el mismo ID de producto. Espera hasta 24 horas después de volver a crearlo para que los cambios se propaguen.
---
# File: cantMakePayments-unity
---
---
title: "Solución para el error Code-1003 cantMakePayment en el SDK de Unity"
description: "Resuelve el error de pagos al gestionar suscripciones en Adapty."
---
El error 1003, `cantMakePayments`, indica que no es posible realizar compras in-app en este dispositivo.
Si encuentras el error `cantMakePayments`, normalmente se debe a una de estas razones:
- Restricciones del dispositivo: El error no está relacionado con Adapty. Consulta las soluciones más abajo.
- Configuración del modo Observer: El método `makePurchase` y el modo Observer no pueden usarse al mismo tiempo. Consulta la sección más abajo.
## Problema: Restricciones del dispositivo \{#issue-device-restrictions\}
| Problema | Solución |
|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
| Restricciones de Screen Time | Desactiva las restricciones de compras in-app en [Screen Time](https://support.apple.com/en-us/102470) |
| Cuenta suspendida | Contacta con el soporte de Apple para resolver problemas con la cuenta |
| Restricciones regionales | Usa una cuenta de App Store de una región compatible |
## Problema: Usar el modo Observer y makePurchase a la vez \{#issue-using-both-observer-mode-and-makepurchase\}
Si usas `makePurchases` para gestionar las compras, no necesitas el modo Observer. El [modo Observer](observer-vs-full-mode) solo es necesario si implementas la lógica de compra tú mismo.
Por lo tanto, si usas `makePurchase`, puedes eliminar sin problema la activación del modo Observer del código de inicialización del SDK.
---
# File: migration-to-unity-sdk-314
---
---
title: "Migrar el SDK de Adapty para Unity a la v. 3.14"
description: "Migra al SDK de Adapty para Unity v3.14 para mejorar el rendimiento y acceder a nuevas funciones de monetización."
---
El SDK de Adapty 3.14.0 es una versión mayor que incorpora mejoras que pueden requerir algunos pasos de migración:
1. Listener de eventos independiente para eventos de paywall.
2. Renombrar `AdaptyUI.CreateView` a `AdaptyUI.CreatePaywallView` y métodos relacionados.
3. Actualizar el método `MakePurchase` para usar `AdaptyPurchaseParameters` en lugar de parámetros individuales.
4. Reemplazar `SetFallbackPaywalls` por el método `SetFallback`.
5. Actualizar el acceso a propiedades del paywall para usar `AdaptyPlacement`.
6. Actualizar el acceso a la configuración remota usando el objeto `AdaptyRemoteConfig`.
7. Reemplazar `VendorProductIds` por `ProductIdentifiers` en el modelo `AdaptyPaywall`.
8. Actualizar la política de obtención en `GetPaywall` para usar `AdaptyFetchPolicy`.
## Listener de eventos independiente para eventos de paywall \{#separate-event-listener-for-paywall-events\}
Si muestras paywalls diseñados con el [Paywall Builder](adapty-paywall-builder), los eventos de la vista de paywall ahora usan la interfaz dedicada `AdaptyPaywallsEventsListener` y el método `SetPaywallsEventsListener`. La interfaz principal `AdaptyEventListener` sigue siendo la encargada de las actualizaciones de perfil y los detalles de instalación.
```diff showLineNumbers
using UnityEngine;
using AdaptySDK;
public class AdaptyListener : MonoBehaviour,
- AdaptyEventListener {
+ AdaptyEventListener,
+ AdaptyPaywallsEventsListener {
void Start() {
Adapty.SetEventListener(this);
+ Adapty.SetPaywallsEventsListener(this);
}
// AdaptyEventListener methods
public void OnLoadLatestProfile(AdaptyProfile profile) { }
public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { }
public void OnInstallationDetailsFail(AdaptyError error) { }
+ // AdaptyPaywallsEventsListener methods
+ // Implement paywall event handlers here
}
```
[Más información sobre cómo gestionar eventos de paywall](unity-handling-events).
## Renombrar los métodos de creación y presentación de vistas \{#rename-view-creation-and-presentation-methods\}
Los métodos de creación y presentación de vistas han sido renombrados:
```diff showLineNumbers
using AdaptySDK;
- AdaptyUI.CreateView(paywall, parameters, (view, error) => {
+ AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => {
if (error != null) {
// handle the error
return;
}
- AdaptyUI.PresentView(view, (error) => {
+ AdaptyUI.PresentPaywallView(view, (error) => {
// handle the error
});
});
}
```
Del mismo modo, el método de cierre ha sido renombrado:
```diff showLineNumbers
- AdaptyUI.DismissView(view, (error) => {
+ AdaptyUI.DismissPaywallView(view, (error) => {
// handle the error
});
```
## Actualizar el método MakePurchase \{#update-makepurchase-method\}
El método `MakePurchase` ahora usa `AdaptyPurchaseParameters` en lugar de los argumentos individuales `subscriptionUpdateParams` e `isOfferPersonalized`. Esto mejora la seguridad de tipos y permite ampliar los parámetros de compra en el futuro.
```diff showLineNumbers
using AdaptySDK;
void MakePurchase(
AdaptyPaywallProduct product,
AdaptySubscriptionUpdateParameters subscriptionUpdate,
bool? isOfferPersonalized
) {
- Adapty.MakePurchase(product, subscriptionUpdate, isOfferPersonalized, (result, error) => {
+ var parameters = new AdaptyPurchaseParametersBuilder()
+ .SetSubscriptionUpdateParams(subscriptionUpdate)
+ .SetIsOfferPersonalized(isOfferPersonalized)
+ .Build();
+
+ Adapty.MakePurchase(product, parameters, (result, error) => {
switch (result.Type) {
case AdaptyPurchaseResultType.Pending:
// handle pending purchase
break;
case AdaptyPurchaseResultType.UserCancelled:
// handle purchase cancellation
break;
case AdaptyPurchaseResultType.Success:
var profile = result.Profile;
// handle successful purchase
break;
default:
break;
}
});
}
```
Si no necesitas parámetros adicionales, puedes usar simplemente:
```csharp showLineNumbers
using AdaptySDK;
void MakePurchase(AdaptyPaywallProduct product) {
Adapty.MakePurchase(product, (result, error) => {
// handle purchase result
});
}
```
## Actualizar el método de respaldo \{#update-fallback-method\}
:::important
Al actualizar al SDK de Unity 3.14, deberás descargar los nuevos archivos de respaldo desde el Adapty Dashboard y reemplazar los existentes en tu proyecto.
:::
El método para configurar los paywall de respaldo ha sido actualizado. El método `SetFallbackPaywalls` ha sido renombrado a `SetFallback`:
```diff showLineNumbers
using AdaptySDK;
void SetFallBackPaywalls() {
#if UNITY_IOS
var assetId = "adapty_fallback_ios.json";
#elif UNITY_ANDROID
var assetId = "adapty_fallback_android.json";
#else
var assetId = "";
#endif
- Adapty.SetFallbackPaywalls(assetId, (error) => {
+ Adapty.SetFallback(assetId, (error) => {
// handle the error
});
}
```
Consulta el ejemplo de código final en la página [Usar paywalls de respaldo en Unity](unity-use-fallback-paywalls).
## Actualizar el acceso a propiedades del paywall \{#update-paywall-property-access\}
Las siguientes propiedades se han movido de `AdaptyPaywall` a `AdaptyPlacement`:
```diff showLineNumbers
using AdaptySDK;
void ProcessPaywall(AdaptyPaywall paywall) {
- var abTestName = paywall.ABTestName;
- var audienceName = paywall.AudienceName;
- var revision = paywall.Revision;
- var placementId = paywall.PlacementId;
+ var abTestName = paywall.Placement.ABTestName;
+ var audienceName = paywall.Placement.AudienceName;
+ var revision = paywall.Placement.Revision;
+ var placementId = paywall.Placement.Id;
}
```
## Actualizar el acceso a la configuración remota \{#update-remote-config-access\}
Las propiedades de Remote Config se han reestructurado en un objeto `AdaptyRemoteConfig` para una mejor organización:
```diff showLineNumbers
using AdaptySDK;
void ProcessRemoteConfig(AdaptyPaywall paywall) {
- var remoteConfigString = paywall.RemoteConfigString;
- var locale = paywall.Locale;
- var remoteConfigDict = paywall.RemoteConfig;
+ var remoteConfigString = paywall.RemoteConfig.Data;
+ var locale = paywall.RemoteConfig.Locale;
+ var remoteConfigDict = paywall.RemoteConfig.Dictionary;
}
```
## Actualizar el uso del modelo AdaptyPaywall \{#update-adaptyPaywall-model-usage\}
La propiedad `VendorProductIds` ha quedado obsoleta en favor de `ProductIdentifiers`. La nueva propiedad devuelve objetos `AdaptyProductIdentifier` en lugar de cadenas simples, lo que proporciona información de producto más estructurada.
```diff showLineNumbers
using AdaptySDK;
void ProcessPaywallProducts(AdaptyPaywall paywall) {
- var productIds = paywall.VendorProductIds;
- foreach (var vendorId in productIds) {
- // use vendorId
- }
+ var productIdentifiers = paywall.ProductIdentifiers;
+ foreach (var productId in productIdentifiers) {
+ var vendorId = productId.VendorProductId;
+ // use vendorId
+ }
}
```
El objeto `AdaptyProductIdentifier` da acceso al ID del producto del proveedor a través de la propiedad `VendorProductId`, manteniendo la misma funcionalidad y ofreciendo una mejor estructura para futuras mejoras.
## Actualizar la política de obtención en GetPaywall \{#update-getpaywall-fetch-policy\}
El tipo del parámetro `fetchPolicy` en el método `GetPaywall` ha cambiado de `AdaptyPaywallFetchPolicy` a `AdaptyPlacementFetchPolicy`. Este cambio unifica el uso de la política de obtención en todo el SDK.
```diff showLineNumbers
using AdaptySDK;
void GetPaywall(string placementId) {
- Adapty.GetPaywall(placementId, AdaptyPaywallFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => {
+ Adapty.GetPaywall(placementId, AdaptyPlacementFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => {
// handle the result
});
}
```
---
# File: migration-to-unity-sdk-34
---
---
title: "Migrar Adapty Unity SDK a v. 3.4"
description: "Migra al Adapty Unity SDK v3.4 para mejorar el rendimiento y acceder a nuevas funciones de monetización."
---
Adapty SDK 3.4.0 es una versión mayor que incluye mejoras que requieren pasos de migración por tu parte.
## Actualizar los archivos de paywall de respaldo \{#update-fallback-paywall-files\}
Actualiza los archivos de paywall de respaldo para garantizar la compatibilidad con la nueva versión del SDK:
1. [Descarga los archivos de paywall de respaldo actualizados](fallback-paywalls) desde el Adapty Dashboard.
2. [Reemplaza los paywalls de respaldo existentes en tu aplicación móvil](unity-use-fallback-paywalls) con los nuevos archivos.
## Actualizar la implementación del modo Observer \{#update-implementation-of-observer-mode\}
Si usas el modo Observer, asegúrate de actualizar su implementación.
Anteriormente, se usaban distintos métodos para reportar transacciones a Adapty. En la nueva versión, el método `reportTransaction` debe usarse de forma consistente tanto en Android como en iOS. Este método reporta explícitamente cada transacción a Adapty, garantizando que sea reconocida. Si se usó un paywall, pasa el ID de variación para vincular la transacción a él.
:::warning
**¡No omitas el reporte de transacciones!**
Si no llamas a `reportTransaction`, Adapty no reconocerá la transacción, no aparecerá en los análisis y no se enviará a las integraciones.
:::
```diff showLineNumbers
- #if UNITY_ANDROID && !UNITY_EDITOR
- Adapty.RestorePurchases((profile, error) => {
- // handle the error
- });
- #endif
Adapty.ReportTransaction(
"YOUR_TRANSACTION_ID",
"PAYWALL_VARIATION_ID", // optional
(error) => {
// handle the error
});
```
---
# File: migration-to-unity330
---
---
title: "Migrar Adapty Unity SDK a la versión 3.3"
description: "Migra al Adapty Unity SDK v3.3 para obtener mejor rendimiento y nuevas funciones de monetización."
---
Adapty SDK 3.3.0 es una versión mayor que incorpora mejoras que pueden requerir algunos pasos de migración por tu parte.
1. Actualiza a Adapty SDK v3.3.x.
2. Se han renombrado varias clases, propiedades y métodos en los módulos Adapty y AdaptyUI del SDK de Adapty.
3. A partir de ahora, el método `SetLogLevel` acepta un callback como argumento.
4. A partir de ahora, el método `PresentCodeRedemptionSheet` acepta un callback como argumento.
5. Cambia la forma en que se crea la vista del paywall.
6. Elimina el método `GetProductsIntroductoryOfferEligibility`.
7. Guarda los paywalls de respaldo en archivos separados (uno por plataforma) en `Assets/StreamingAssets/` y pasa los nombres de archivo al método `SetFallbackPaywalls`.
8. Actualiza la lógica de compra.
9. Actualiza el manejo de eventos del Paywall Builder.
10. Actualiza el manejo de errores del paywall del Paywall Builder.
11. Actualiza las configuraciones de integración para Adjust, Amplitude, AppMetrica, Appsflyer, Branch, Firebase and Google Analytics, Mixpanel, OneSignal, Pushwoosh.
13. Actualiza la implementación del modo Observer.
14. Actualiza la inicialización del plugin de Unity con una llamada explícita a `Activate`.
## Actualizar el Adapty Unity SDK a la versión 3.3.x \{#upgrade-adapty-unity-sdk-to-33x\}
Hasta esta versión, Adapty SDK era el SDK principal e imprescindible para el funcionamiento correcto de Adapty en tu app, mientras que AdaptyUI SDK era un SDK opcional que solo se necesitaba si usabas el Adapty Paywall Builder.
A partir de la versión 3.3.0, AdaptyUI SDK queda obsoleto y AdaptyUI se fusiona con el Adapty SDK como módulo. Debido a estos cambios, debes eliminar AdaptyUISDK y reinstalar AdaptySDK.
1. Elimina las dependencias de los paquetes **AdaptySDK** y **AdaptyUISDK** de tu proyecto.
2. Borra las carpetas **AdaptySDK** y **AdaptyUISDK**.
3. Importa de nuevo el paquete AdaptySDK tal como se describe en la página [Instalación y configuración del SDK de Adapty para Unity](sdk-installation-unity).
## Renombramientos \{#renamings\}
1. Renombramientos en el módulo Adapty:
| Versión anterior | Nueva versión |
| ------------------------- | ------------------------ |
| Adapty.sdkVersion | Adapty.SDKVersion |
| Adapty.LogLevel | AdaptyLogLevel |
| Adapty.Paywall | AdaptyPaywall |
| Adapty.PaywallFetchPolicy | AdaptyPaywallFetchPolicy |
| PaywallProduct | AdaptyPaywallProduct |
| Adapty.Profile | AdaptyProfile |
| Adapty.ProfileParameters | AdaptyProfileParameters |
| ProfileGender | AdaptyProfileGender |
| Error | AdaptyError |
2. Renombramientos en el módulo AdaptyUI:
| Versión anterior | Nueva versión |
| ------------------ | ------------------ |
| CreatePaywallView | CreateView |
| PresentPaywallView | PresentView |
| DismissPaywallView | DismissView |
| AdaptyUI.View | AdaptyUIView |
| AdaptyUI.Action | AdaptyUIUserAction |
## Cambiar el método SetLogLevel \{#change-the-setloglevel-method\}
A partir de ahora, el método `SetLogLevel` acepta un callback como argumento.
```diff showLineNumbers
- Adapty.SetLogLevel(Adapty.LogLevel.Verbose);
+ Adapty.SetLogLevel(Adapty.LogLevel.Verbose, null); // or you can pass the callback to handle the possible error
```
## Cambiar el método PresentCodeRedemptionSheet \{#change-the-presentcoderedemptionsheet-method\}
A partir de ahora, el método `PresentCodeRedemptionSheet` acepta un callback como argumento.
```diff showLineNumbers
- Adapty.PresentCodeRedemptionSheet();
+ Adapty.PresentCodeRedemptionSheet(null); // or you can pass the callback to handle the possible error
```
## Cambiar la forma en que se crea la vista del paywall \{#change-how-the-paywall-view-is-created\}
Para ver el ejemplo de código completo, consulta [Obtener la configuración de vista del paywall diseñado con el Paywall Builder](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder).
```diff showLineNumbers
+ var parameters = new AdaptyUICreateViewParameters()
+ .SetPreloadProducts(true);
- AdaptyUI.CreatePaywallView(
+ AdaptyUI.CreateView(
paywall,
- preloadProducts: true,
+ parameters,
(view, error) => {
// use the view
});
```
## Eliminar el método GetProductsIntroductoryOfferEligibility \{#remove-the-getproductsintroductoryoffereligibility-method\}
Antes de Adapty iOS SDK 3.3.0, el objeto producto siempre incluía las ofertas, independientemente de si el usuario era elegible. Había que comprobar la elegibilidad manualmente antes de usar la oferta.
Ahora, el objeto producto solo incluye una oferta si el usuario es elegible. Esto significa que ya no es necesario comprobar la elegibilidad: si hay una oferta disponible, el usuario es elegible.
## Actualizar el método para proporcionar paywalls de respaldo \{#update-method-for-providing-fallback-paywalls\}
Hasta esta versión, los paywalls de respaldo se pasaban como JSON serializado. A partir de la versión 3.3.0, el mecanismo ha cambiado:
1. Guarda los paywalls de respaldo en archivos dentro de `/Assets/StreamingAssets/`, un archivo para Android y otro para iOS.
2. Pasa los nombres de archivo al método `SetFallbackPaywalls`.
Tu código cambiará de la siguiente manera:
```diff showLineNumbers
using AdaptySDK;
void SetFallBackPaywalls() {
+ #if UNITY_IOS
+ var assetId = "adapty_fallback_ios.json";
+ #elif UNITY_ANDROID
+ var assetId = "adapty_fallback_android.json";
+ #else
+ var assetId = "";
+ #endif
- Adapty.SetFallbackPaywalls("FALLBACK_PAYWALLS_JSON_STRING", (error) => {
+ Adapty.SetFallbackPaywalls(assetId, (error) => {
// handle the error
});
}
```
Consulta el ejemplo de código completo en la página [Usar paywalls de respaldo en Unity](unity-use-fallback-paywalls).
## Actualizar la lógica de compra \{#update-making-purchase\}
Anteriormente, las compras canceladas y pendientes se consideraban errores y devolvían los códigos `PaymentCancelled` y `PendingPurchase`, respectivamente.
Ahora se usa una nueva clase `AdaptyPurchaseResultType` para procesar las compras canceladas, exitosas y pendientes. Actualiza el código de compra de la siguiente manera:
```diff showLineNumbers
using AdaptySDK;
void MakePurchase(AdaptyPaywallProduct product) {
- Adapty.MakePurchase(product, (profile, error) => {
- // handle successfull purchase
+ Adapty.MakePurchase(product, (result, error) => {
+ switch (result.Type) {
+ case AdaptyPurchaseResultType.Pending:
+ // handle pending purchase
+ break;
+ case AdaptyPurchaseResultType.UserCancelled:
+ // handle purchase cancellation
+ break;
+ case AdaptyPurchaseResultType.Success:
+ var profile = result.Profile;
+ // handle successful purchase
+ break;
+ default:
+ break;
}
});
}
```
Consulta el ejemplo de código completo en la página [Realizar compras en la app móvil](unity-making-purchases).
## Actualizar el manejo de eventos del Paywall Builder \{#update-handling-of-paywall-builder-events\}
Las compras canceladas y pendientes ya no se consideran errores; todos estos casos se procesan con el método `PaywallViewDidFinishPurchase`.
1. Elimina el procesamiento del evento de compra cancelada.
2. Actualiza el manejo del evento de compra exitosa de la siguiente manera:
```diff showLineNumbers
- public void OnFinishPurchase(
- AdaptyUI.View view,
- Adapty.PaywallProduct product,
- Adapty.Profile profile
- ) { }
+ public void PaywallViewDidFinishPurchase(
+ AdaptyUIView view,
+ AdaptyPaywallProduct product,
+ AdaptyPurchaseResult purchasedResult
+ ) { }
```
3. Actualiza el manejo de acciones:
```diff showLineNumbers
- public void OnPerformAction(
- AdaptyUI.View view,
- AdaptyUI.Action action
- ) {
+ public void PaywallViewDidPerformAction(
+ AdaptyUIView view,
+ AdaptyUIUserAction action
+ ) {
switch (action.Type) {
- case AdaptyUI.ActionType.Close:
+ case AdaptyUIUserActionType.Close:
view.Dismiss(null);
break;
- case AdaptyUI.ActionType.OpenUrl:
+ case AdaptyUIUserActionType.OpenUrl:
var urlString = action.Value;
if (urlString != null {
Application.OpenURL(urlString);
}
default:
// handle other events
break;
}
}
```
4. Actualiza el manejo del inicio de compra:
```diff showLineNumbers
- public void OnSelectProduct(
- AdaptyUI.View view,
- Adapty.PaywallProduct product
- ) { }
+ public void PaywallViewDidSelectProduct(
+ AdaptyUIView view,
+ string productId
+ ) { }
```
5. Actualiza el manejo de compra fallida:
```diff showLineNumbers
- public void OnFailPurchase(
- AdaptyUI.View view,
- Adapty.PaywallProduct product,
- Adapty.Error error
- ) { }
+ public void PaywallViewDidFailPurchase(
+ AdaptyUIView view,
+ AdaptyPaywallProduct product,
+ AdaptyError error
+ ) { }
```
6. Actualiza el manejo del evento de restauración exitosa:
```diff showLineNumbers
- public void OnFailRestore(
- AdaptyUI.View view,
- Adapty.Error error
- ) { }
+ public void PaywallViewDidFailRestore(
+ AdaptyUIView view,
+ AdaptyError error
+ ) { }
```
Consulta el ejemplo de código completo en la página [Manejar eventos del paywall](unity-handling-events).
## Actualizar el manejo de errores del paywall del Paywall Builder \{#update-handling-of-paywall-builder-paywall-errors\}
El manejo de errores también ha cambiado; actualiza tu código según las indicaciones a continuación.
1. Actualiza el manejo de errores de carga de productos:
```diff showLineNumbers
- public void OnFailLoadingProducts(
- AdaptyUI.View view,
- Adapty.Error error
- ) { }
+ public void PaywallViewDidFailLoadingProducts(
+ AdaptyUIView view,
+ AdaptyError error
+ ) { }
```
2. Actualiza el manejo de errores de renderizado:
```diff showLineNumbers
- public void OnFailRendering(
- AdaptyUI.View view,
- Adapty.Error error
- ) { }
+ public void PaywallViewDidFailRendering(
+ AdaptyUIView view,
+ AdaptyError error
+ ) { }
```
## Actualizar la configuración del SDK de integraciones de terceros \{#update-third-party-integration-sdk-configuration\}
A partir de Adapty Unity SDK 3.3.0, hemos actualizado la API pública del método `updateAttribution`. Anteriormente, aceptaba un diccionario `[AnyHashable: Any]`, lo que permitía pasar objetos de atribución directamente desde varios servicios. Ahora requiere un `[String: any Sendable]`, por lo que tendrás que convertir los objetos de atribución antes de pasarlos.
Para garantizar que las integraciones funcionen correctamente con Adapty Unity SDK 3.3.0 y versiones posteriores, actualiza las configuraciones de tu SDK para las siguientes integraciones tal como se describe en las secciones a continuación.
### Adjust
Actualiza el código de tu app móvil como se muestra a continuación. Para ver el ejemplo de código completo, consulta la [Configuración del SDK para la integración con Adjust](adjust#connect-your-app-to-adjust).
```diff showLineNumbers
- using static AdaptySDK.Adapty;
using AdaptySDK;
Adjust.GetAdid((adid) => {
- Adjust.GetAttribution((attribution) => {
- Dictionary