# REACT-NATIVE - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: es Generated on: 2026-07-24T13:01:55.751Z Total files: 45 --- # File: sdk-installation-react-native-expo --- --- title: "Install & configure Adapty React Native SDK in an Expo project" description: "Step-by-step guide on installing Adapty React Native SDK in an Expo project for subscription-based apps." --- :::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 de React Native](sdk-installation-react-native-pure) en su lugar. ::: 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 utilizas 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 necesitas 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 de Expo? Echa un vistazo a nuestras apps de muestra: - [Ejemplo de Expo dev build](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) para funcionalidad completa, incluyendo compras reales y Paywall Builder - [Ejemplo de Expo Go y Web](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) para pruebas en modo mock ::: Para una guía completa de 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-sdk-integration-skill-react-native
---
---
title: "Integra Adapty en tu app de React Native con la skill de integración del SDK"
description: "Usa la skill adapty-sdk-integration para integrar el SDK de Adapty en tu app de React Native de principio a fin con tu herramienta de codificación con IA."
---
La [skill adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza la integración de Adapty de extremo a extremo: configuración del dashboard, instalación del SDK, paywall y verificación por etapas. Detecta tu plataforma automáticamente y obtiene la documentación de Adapty relevante en cada etapa.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
Para instalarla, elige el formulario para tu herramienta. La lista completa está en el [README de la skill](https://github.com/adaptyteam/adapty-sdk-integration-skill).
**Claude Code**
```
claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill
claude plugin install adapty-sdk-integration@adapty
```
**GitHub Copilot CLI**
```
gh skill install adaptyteam/adapty-sdk-integration-skill
```
**Gemini CLI**
```
gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill
```
**OpenAI Codex u otra herramienta** — usa la [CLI de skills](https://skills.sh) (ten en cuenta que las skills instaladas de esta forma no se actualizan automáticamente):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
También puedes clonar el repositorio y copiar `skills/adapty-sdk-integration/` en el directorio de skills de tu herramienta.
Tras la instalación, ejecuta la skill en tu proyecto:
```
/adapty-sdk-integration
```
La skill hace algunas preguntas de configuración y luego te guía por la configuración del dashboard, la instalación del SDK, el paywall y la verificación.
:::important
La skill está en beta. Si se queda bloqueada o se comporta de forma inesperada, sigue la [guía de integración paso a paso](adapty-cursor-react-native) — te lleva a través de cada etapa con la documentación correcta.
:::
La [skill adapty-sdk-integration](https://github.com/adaptyteam/adapty-sdk-integration-skill) automatiza la integración de Adapty de extremo a extremo: configuración del dashboard, instalación del SDK, paywall y verificación por etapas. Detecta tu plataforma automáticamente y obtiene la documentación de Adapty relevante en cada etapa.
**Herramientas compatibles**: Claude Code, GitHub Copilot CLI, OpenAI Codex, Gemini CLI.
Para instalarla, elige el formulario para tu herramienta. La lista completa está en el [README de la skill](https://github.com/adaptyteam/adapty-sdk-integration-skill).
**Claude Code**
```
claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill
claude plugin install adapty-sdk-integration@adapty
```
**GitHub Copilot CLI**
```
gh skill install adaptyteam/adapty-sdk-integration-skill
```
**Gemini CLI**
```
gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill
```
**OpenAI Codex u otra herramienta** — usa la [CLI de skills](https://skills.sh) (ten en cuenta que las skills instaladas de esta forma no se actualizan automáticamente):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
También puedes clonar el repositorio y copiar `skills/adapty-sdk-integration/` en el directorio de skills de tu herramienta.
Tras la instalación, ejecuta la skill en tu proyecto:
```
/adapty-sdk-integration
```
La skill hace algunas preguntas de configuración y luego te guía por la configuración del dashboard, la instalación del SDK, el paywall y la verificación.
---
# File: adapty-cursor-react-native
---
---
title: "Integra Adapty en tu app React Native con ayuda de IA"
description: "Una guía paso a paso para integrar Adapty en tu app React Native usando Cursor, Context7, ChatGPT, Claude u otras herramientas de IA."
---
Esta guía te lleva paso a paso por la integración de Adapty en tu app de React Native con una herramienta de codificación con IA: le proporcionas la documentación correcta de Adapty en el orden correcto.
For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command.
## Antes de empezar: configuración del dashboard \{#before-you-start-dashboard-setup\}
Adapty necesita algo de configuración en el dashboard antes de que escribas código con el SDK. Puedes hacerlo con una skill interactiva de LLM o manualmente desde el Dashboard.
### Enfoque con skill (recomendado) \{#skill-approach-recommended\}
El skill de 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 necesitas [conectar tus stores](integrate-payments) en el Dashboard.
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
Una vez añadido el skill, ejecuta `/adapty-cli` en tu agente. Te guiará paso a paso — incluyendo cuándo abrir el Dashboard para conectar tus stores.
### Enfoque desde el dashboard
Si prefieres configurar todo de forma manual, esto es lo que necesitas antes de escribir código. Tu LLM no puede buscar los valores del dashboard por ti — tendrás que proporcionarlos.
1. **Conecta tus app stores**: En el Adapty Dashboard, ve a **App settings → General**. Conecta tanto App Store como Google Play si tu app tiene como destino ambas plataformas. Esto es necesario para que las compras funcionen.
[Conecta los app 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, 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 referencias 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 luego 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 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` 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 paywall correctamente.
:::
### 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 requieren cambios en el código.
[Pruebas A/B](ab-tests)
- **Paywalls y placements adicionales**: Añade más llamadas `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\}
### Usar Context7 (recomendado)
[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 automáticamente la documentación correcta 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 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 funciona correctamente.
:::
### Usa los documentos en texto plano
Puedes acceder a cualquier documento 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-react-native.md](https://adapty.io/docs/es/adapty-cursor-react-native.md).
Cada etapa del [recorrido de implementación](#implementation-walkthrough) a continuación incluye un bloque "Send this to your LLM" con enlaces `.md` para pegar.
Para acceder a más documentación de una vez, consulta los [archivos de índice y subconjuntos por plataforma](#plain-text-doc-index-files) a continuación.
## Guía de implementación paso a paso \{#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, qué deberías ver al terminar y los problemas más habituales.
### Planifica tu integración \{#plan-your-integration\}
Antes de escribir código, pídele a tu LLM que analice tu proyecto y cree un plan de implementación. Si tu herramienta de IA tiene 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 generar cualquier código.
Dile a tu LLM qué enfoque usas para las compras, ya que esto determina qué guías 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**](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 análisis e integraciones.
¿No sabes cuál elegir? Consulta la [tabla comparativa en la guía de inicio rápido](react-native-quickstart-paywalls).
### Instalar y configurar el SDK \{#install-and-configure-the-sdk\}
Añade la dependencia del SDK de Adapty con npm (o yarn) y actívalo con tu clave SDK pública. Esta es la base: sin ella, nada más funciona.
Tenemos guías de instalación independientes 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)
```
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[Checkpoint]
- **Esperado:** La app se compila y ejecuta tanto en iOS como en Android. Los logs de Metro bundler muestran el log de activación de Adapty.
- **Error frecuente:** "Public API key is missing" → comprueba que hayas reemplazado el marcador de posición con tu clave real desde **App settings**.
:::
### Mostrar paywalls y gestionar compras \{#show-paywalls-and-handle-purchases\}
Obtén un paywall por su ID de placement, muéstralo y gestiona los eventos de compra. Las guías que necesitas dependen de cómo gestiones 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 ver las instrucciones de configuració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 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é cuando existan. 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 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 una limpieza manual.
El SDK de Adapty almacena los paywalls localmente en dos capas: la caché de actualización periódica 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 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 limitada.
| | **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 superar ligeramente el tiempo indicado en `loadTimeout`, ya que la operación puede implicar distintas solicitudes internamente.
Para Android: puedes crear un `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` proviene de `import com.adapty.utils.seconds`), o con `TimeInterval.seconds(5)`. Para no establecer ningún límite, usa `TimeInterval.INFINITE`.
| Parámetros de respuesta: | Parámetro | Descripción | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Flow | Un objeto `AdaptyFlow` con los identificadores del flow (`id`, `variationId`), el nombre, el placement, sus variantes de paywall (`paywalls`) y los Remote Configs (`remoteConfigs`). | ## Obtener la configuración de la vista \{#fetch-the-view-configuration\} :::important Asegúrate de activar el botón **Show on device** en el builder. Si esta opción no está activada, la configuración de la vista no estará disponible para recuperar. ::: Si el placement fue diseñado en el **Flow Builder** o en el **Paywall Builder**, Adapty renderiza la interfaz por ti. Crea la vista con `createFlowView` y, a continuación, [presenta el flow o el paywall](react-native-present-paywalls). Si el placement es un paywall personalizado sin interfaz del Builder, [trátalo como un paywall de Remote Config](present-remote-config-paywalls-react-native). En el SDK de React Native, llama a `createFlowView` directamente — no necesitas obtener primero la configuración de la vista. :::warning El resultado del método `createFlowView` solo puede usarse una vez. Si necesitas usarlo de nuevo, llama de nuevo al método `createFlowView`. Llamarlo dos veces sin recrearlo puede provocar el error `AdaptyUIError.viewAlreadyPresented`. ::: ```typescript showLineNumbers try { const view = await createFlowView(flow); } catch (error) { // handle the error } ``` Parámetros: | Parámetro | Presencia | Descripción | | :------------------- | :-------- | :----------------------------------------------------------- | | **flow** | obligatorio | Un objeto `AdaptyFlow` para obtener un controlador del flow/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, reemplazados dinámicamente por cadenas específicas para personalizar el contenido dentro del flow/paywall. Consulta el tema Custom tags in paywall builder para más detalles. | | **prefetchProducts** | opcional | Actívalo para optimizar el momento en que se muestran los productos en pantalla. Cuando es `true`, AdaptyUI recuperará automáticamente los productos necesarios. Valor predeterminado: `false`. | | **android.enableSafeArea** | opcional | Solo para Android (se ignora en iOS). Pásalo como objeto anidado: `android: { enableSafeArea: true }`. Cuando es `true`, la vista del flow aplica márgenes de área segura. Por defecto es `true` para la presentación modal (`createFlowView` + `present()`) y `false` para el componente `AdaptyFlowView` embebido. El valor predeterminado es adecuado para la mayoría de los casos. | :::note Si utilizas varios idiomas, aprende cómo añadir una [localización de flow](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, [muestra el flow/paywall](react-native-present-paywalls). ## Obtén un flow o paywall para la audiencia predeterminada y cárgalo más rápido \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} Por lo general, los flows y paywalls se cargan casi al instante, así que no tendrás que preocuparte por optimizar este proceso. Sin embargo, si tienes muchas audiencias y placements, y tus usuarios tienen una conexión a internet lenta, la carga de un flow o paywall puede tardar más de lo deseado. En esos casos, puede que quieras mostrar un flow o paywall predeterminado para garantizar una experiencia fluida, en lugar de no mostrar nada. Para solucionar esto, puedes usar el método `getFlowForDefaultAudience`, que obtiene el flow o paywall del placement especificado para la audiencia **All Users**. Sin embargo, es importante entender que el enfoque recomendado es obtener el flow o paywall con el método `getFlow`, tal como se explica en la sección [Obtener flow/paywall](#fetch-flowpaywall) anterior. :::warning Por qué recomendamos usar `getFlow` El método `getFlowForDefaultAudience` tiene algunos inconvenientes importantes: - **Posibles problemas de compatibilidad con versiones anteriores**: Si necesitas mostrar diferentes paywalls para distintas versiones de la app (la actual y futuras), podrías encontrarte con dificultades. 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 tener problemas con paywalls que no se renderizan correctamente. - **Pérdida de targeting**: 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ís, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a aceptar estas desventajas para beneficiarte de una obtención más rápida del flow o paywall, usa el método `getFlowForDefaultAudience` de la siguiente manera. De lo contrario, quédate con `getFlow` descrito [arriba](#fetch-flowpaywall). ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const flow = await adapty.getFlowForDefaultAudience(id); // the requested flow/paywall } catch (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. | | **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 a internet inestables, considera usar `.returnCacheDataElseLoad` para devolver los datos en caché si existen. En ese 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 lo intermitente que sea 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 una limpieza manual.
| ## Personalizar assets \{#customize-assets\} Para personalizar imágenes y vídeos en tu flow/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 personalizados, seleccionas 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 Adapty Dashboard. 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. ::: A continuación se muestra un ejemplo de cómo puedes proporcionar recursos personalizados mediante un diccionario simple: ```javascript const customAssets: Recordopcional
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 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 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, 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é 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 localmente en dos capas: la caché de actualización periódica 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 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 limitada.
| | **loadTimeoutMs** | 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 fallback local.
Ten en cuenta que en casos poco frecuentes este método puede superar ligeramente el tiempo de espera especificado en `loadTimeout`, ya que la operación puede estar compuesta de distintas solicitudes internamente.
Para Android: puedes crear un `TimeInterval` con funciones de extensión (como `5.seconds`, donde `.seconds` proviene de `import com.adapty.utils.seconds`), o con `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 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 interruptor **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 indicará cómo mostrar el paywall. Si el `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-react-native). En el SDK de React Native, 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 volver a utilizarlo, llama de nuevo al método `createPaywallView`. 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** | requerido | Un objeto `AdaptyPaywall` para obtener un controlador para el 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, reemplazándose dinámicamente con cadenas específicas para personalizar el contenido. Consulta el tema Custom tags in paywall builder para más detalles. | | **prefetchProducts** | opcional | Actívalo para optimizar el momento en que se muestran los productos en pantalla. Cuando es `true`, AdaptyUI obtiene automáticamente los productos necesarios. Valor predeterminado: `false`. | :::note Si utilizas 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í](react-native-localizations-and-locale-codes). ::: Una vez que tengas la vista, [muestra el paywall](react-native-present-paywalls). ## Obtén un paywall para la audiencia predeterminada y acelera la carga \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} Por lo general, los paywalls se cargan casi al instante, así que no tendrás que preocuparte por optimizar este proceso. Sin embargo, si tienes muchas audiencias y paywalls, y tus usuarios tienen una conexión a internet débil, la carga puede tardar más de lo deseable. En esas situaciones, puede que quieras mostrar un paywall predeterminado para garantizar una buena experiencia de usuario 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`, tal como se detalla en la sección [Obtener información del paywall](#fetch-paywall-designed-with-paywall-builder) más arriba. :::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), es posible que te encuentres con dificultades. 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 tener 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 (incluida la basada en países, atribución de marketing o tus propios atributos personalizados). Si estás dispuesto a aceptar estas desventajas para beneficiarte de una obtención más rápida del paywall, usa el método `getPaywallForDefaultAudience` de la siguiente manera. De lo contrario, sigue usando `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 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](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 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, puede 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 peticiones de red.
Ten en cuenta que la caché permanece intacta al reiniciar la aplicación 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 recursos personalizados. Las imágenes y vídeos hero tienen IDs predefinidos: `hero_image` y `hero_video`. En un bundle de recursos personalizado, seleccionas 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 Adapty Dashboard. 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. ::: Este es un ejemplo de cómo puedes proporcionar recursos personalizados mediante un diccionario simple: ```javascript const customAssets: Record
## El número de visualizaciones del paywall es demasiado alto \{#the-paywall-view-number-is-too-big\}
**Problema**: El contador de visualizaciones del paywall muestra el doble del número esperado.
**Motivo**: Es posible que estés llamando a `logShowFlow` (React Native SDK v4+) / `logShowPaywall` en tu código, lo que duplica el contador de visualizaciones si usas el Paywall Builder o el Flow Builder. Para flows y paywalls creados con estas herramientas, 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 `logShowFlow` (React Native SDK v4+) / `logShowPaywall` en tu código si usas el Paywall Builder o el Flow 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**: Si es necesario, migra el SDK a la versión más reciente siguiendo las [guías de migración](react-native-sdk-migration-guides). Muchos problemas se resuelven en versiones más nuevas del SDK.
---
# File: react-native-quickstart-manual
---
---
title: "Habilitar compras en tu paywall personalizado con React Native SDK"
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 buscas la forma más sencilla de habilitar compras, usa el [Adapty Flow Builder](react-native-quickstart-paywalls). Con Flow Builder, creas flows en un editor visual sin código, Adapty gestiona toda la lógica de compra 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 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 (por ejemplo, `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 distintos usuarios.
Asegúrate de entender estos conceptos incluso si trabajas con tu propio paywall personalizado. Básicamente, son tu forma de gestionar los productos que vendes en tu app.
Para implementar tu paywall personalizado, tendrás que 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. Obtener productos \{#step-1-get-products\}
Para obtener los productos de tu paywall personalizado, necesitas:
1. Obtener el objeto `flow` pasando el ID del [placement](placements) al método `getFlow`.
2. Obtener el array de productos de este flow usando el método `getPaywallProducts`.
```typescript showLineNumbers
async function loadPaywall() {
try {
const flow: AdaptyFlow = await adapty.getFlow('YOUR_PLACEMENT_ID');
const products: AdaptyPaywallProduct[] = await adapty.getPaywallProducts(flow);
// Use products to build your custom paywall UI
} catch (error) {
// Handle the error
}
}
```
## Paso 2. Aceptar compras \{#step-2-accept-purchases\}
Cuando un usuario pulsa sobre un producto en tu paywall personalizado, llama al método `makePurchase` con el producto seleccionado. Esto gestionará el flow 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. Restaurar compras \{#step-3-restore-purchases\}
Los stores requieren que todas las aplicaciones 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\}
:::tip
¿Tienes preguntas o estás teniendo algún problema? Consulta nuestro [foro de soporte](https://adapty.featurebase.app/) donde encontrarás respuestas a preguntas frecuentes o podrás plantear las tuyas. ¡Nuestro equipo y la comunidad están aquí para ayudarte!
:::
Tu paywall está listo para mostrarse en la app. Prueba tus compras en el [sandbox de App Store](test-purchases-in-sandbox) o en [Google Play Store](testing-on-android) para asegurarte de que puedes completar una compra de prueba desde el paywall. Para ver cómo funciona esto en una implementación lista para producción, consulta [CustomPurchaseScreen.tsx](https://github.com/adaptyteam/AdaptySDK-React-Native/blob/master/examples/ExpoGoWebMock/src/CustomPurchaseScreen.tsx) en nuestra app de ejemplo, donde se muestra el manejo de compras con gestión adecuada de errores, estados de carga y estado de la interfaz.
A continuación, [comprueba si los usuarios han completado su compra](react-native-check-subscription-status) para determinar si mostrar el paywall o conceder acceso a las funciones de pago.
---
# File: fetch-paywalls-and-products-react-native
---
---
title: "Obtener paywalls y productos para paywalls de Remote Config en el SDK de React Native"
description: "Obtén paywalls y productos en el SDK de React Native de Adapty para mejorar la monetización de los usuarios."
---
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 recibir 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 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 una limpieza manual.
El SDK de Adapty almacena los flows y 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 cargar flows y 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 asegurarse de que siempre obtengas la versión más reciente de tus flows, garantizando 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 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 agotar el tiempo de espera ligeramente después de lo especificado en `loadTimeout`, ya que la operación puede consistir en diferentes peticiones internamente.
| :::note En v4, `getFlow` ya no acepta un parámetro `locale`. En el caso de los paywalls personalizados, todos los idiomas disponibles se devuelven en el Remote Config del flow (`flow.remoteConfigs`); elige el que corresponda al idioma del dispositivo o la configuración de la app del usuario. ::: ¡No escribas los IDs de productos en el código! Dado que los flows se configuran de forma remota, los productos disponibles, su cantidad y las ofertas especiales (como las pruebas gratuitas) pueden cambiar con el tiempo. Asegúrate de que tu código gestione estos escenarios. Por ejemplo, si inicialmente obtienes 2 productos, la app debería mostrar esos 2 productos. Sin embargo, si más adelante obtienes 3 productos, la app debería mostrar los 3 sin necesidad de modificar 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 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | Un objeto `AdaptyFlow` que contiene el placement, los identificadores (`id`, `variationId`), el nombre, sus variaciones de paywall (`paywalls`) y un array `remoteConfigs` (una entrada por cada locale configurado). Para obtener los productos del flow, llama a `getPaywallProducts(flow)`. | ## Obtener productos \{#fetch-products\} Una vez que tienes el flow, puedes consultar el array de productos que le corresponde: ```typescript showLineNumbers try { // ...flow const products = await adapty.getPaywallProducts(flow); // the requested products list } catch (error) { // handle the 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 ilustran las propiedades más utilizadas, pero consulta el documento enlazado para obtener todos los detalles sobre 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 el precio en formato localizado, usa `product.price?.localizedString`. Esta localización se basa en la configuración de idioma 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`. | | **Subscription Period** | 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 conocer la unidad de tiempo ('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ás `'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.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 encontrarás las siguientes propiedades útiles: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, independientemente de lo intermitente que sea 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 reinstala la app o mediante limpieza manual.
|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](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 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 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 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 la app se reinstala o mediante una limpieza manual.
El SDK de Adapty almacena los paywalls en dos capas: la caché de actualización regular 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 limitada.
| | **loadTimeoutMs** | 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 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 de diferentes peticiones internamente.
| ¡No escribas 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 escribir directamente 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 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: ```typescript showLineNumbers try { // ...paywall const products = await adapty.getPaywallProducts(paywall); // the requested products list } catch (error) { // handle the 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 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 todos los detalles sobre 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 del store seleccionado por el usuario, no en el idioma del dispositivo. | | **Precio** | Para mostrar el precio localizado, usa `product.price?.localizedString`. La 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 devolverá en la moneda local. Para obtener el símbolo de la moneda, 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`. La localización se basa en la configuración regional del dispositivo. Para obtener el período de suscripción mediante código, usa `product.subscription?.subscriptionPeriod`. Desde ahí puedes acceder a la propiedad `unit` para conocer la unidad de tiempo (es decir, `'day'`, `'week'`, `'month'`, `'year'` o `'unknown'`). El valor `numberOfUnits` te dará el número de unidades del período. Por ejemplo, en una suscripción trimestral verás `'month'` en la propiedad `unit` y `3` en la propiedad `numberOfUnits`. | | **Oferta introductoria** | Para mostrar una etiqueta u otro indicador de que una suscripción incluye 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 encontrarás las siguientes propiedades útiles:opcional
predeterminado: `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](react-native-localizations-and-locale-codes) para obtener más información sobre los códigos de idioma y cómo recomendamos usarlos.
| | **fetchPolicy** | predeterminado: `.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 consideras que tus usuarios tienen una conexión a internet inestable, puedes usar `.returnCacheDataElseLoad` para devolver los datos en caché cuando estén disponibles. 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 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 reinstala la app o mediante una limpieza manual.
|Si la solicitud se ha realizado correctamente, 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 determinar 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 del SDK de Adapty inferior a v2.9.0, debes proporcionar el [secreto compartido de Apple App Store](app-store-connection-configuration#step-5-enter-app-store-shared-secret) en su lugar. Este método está actualmente en desuso por Apple. ::: ## Cambiar de 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 funcionamiento depende del store: - En el App Store, la suscripción se actualiza automáticamente dentro del grupo de suscripciones. Si un usuario adquiere una suscripción de un grupo mientras ya tiene activa otra de un grupo diferente, ambas suscripciones estarán activas al mismo tiempo. - En Google Play, la suscripción no se actualiza automáticamente. Debes gestionar el cambio en el código de tu app 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 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 de solicitud adicional: | Parámetro | Presencia | Descripción | | :--------- | :-------- | :----------------------------------------------------------- | | **params** | requerido | un objeto del 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. ```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 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 cambios a un plan 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 se producirá 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\}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 Kids en React Native SDK" description: "Activa fácilmente el Modo Kids para cumplir con las políticas de Apple y Google. Sin IDFA, GAID ni datos publicitarios en React Native SDK." --- Si tu aplicación React Native 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. :::important En iOS, el modo Kids se activa mediante el trait de Swift Package `KidsMode`, que elimina en compilación todo el código relacionado con IDFA, AdSupport y AppTrackingTransparency. Requiere el SDK v4 (que instala el SDK nativo de iOS a través de Swift Package Manager) y **Xcode 26** o posterior. Consulta [Actualizaciones en tu iOS Podfile](#updates-in-your-ios-podfile) a continuación. ::: ## ¿Qué se necesita? \{#whats-required\} Tienes que configurar el SDK 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 customer user ID con cuidado. 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 de 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 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 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, 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 irregular 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é se mantiene 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 cargar los 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 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 de 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 agotarse ligeramente después del tiempo especificado en `loadTimeout`, 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://react-native.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 forma instantánea, así 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 deseado. En esos casos, puede que quieras mostrar un onboarding predeterminado para garantizar una experiencia de usuario fluida en lugar de no mostrar ningún onboarding. Para solucionar 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 generar problemas al dar soporte a varias versiones de la app, lo que obliga a diseñar con compatibilidad hacia atrás o asumir que las versiones 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 obtención más rápida compensa estos inconvenientes en 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); // el onboarding solicitado } catch (error) { // manejar el 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 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, puede que los usuarios no obtengan los datos absolutamente 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 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 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 esté disponible. Este sistema está diseñado para garantizar que siempre obtengas la versión más reciente de tus onboardings y al mismo tiempo asegurar la fiabilidad incluso cuando la conexión a internet es escasa.
| --- # File: react-native-present-onboardings --- --- title: "Presentar onboardings en el SDK de React Native" description: "Descubre cómo presentar onboardings en React Native para aumentar conversiones e ingresos." --- :::warning **Los onboardings están obsoletos en el SDK v4 y se eliminarán en una versión futura.** Ya no reciben correcciones ni mejoras. Usa [flows](react-native-get-pb-paywalls) en su lugar: a diferencia de los onboardings, que se ejecutan dentro de un WebView, los flows se renderizan de forma nativa en el dispositivo, lo que ofrece animaciones más fluidas, una apariencia nativa coherente, tiempos de carga más rápidos y sin dependencia del entorno WebView. Consulta [Obtener flows y paywalls](react-native-get-pb-paywalls) y [Mostrar flows y paywalls](react-native-present-paywalls) para empezar. ::: Si has personalizado un onboarding usando el builder, no necesitas preocuparte por renderizarlo en el código de tu aplicación móvil para mostrárselo al usuario. Ese onboarding incluye tanto lo que debe mostrarse como la forma en que debe mostrarse. Antes de empezar, asegúrate de que: 1. Tienes instalado el [SDK de Adapty para React Native](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**: El componente embebido 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 configuración adicional para `AdaptyOnboardingView` para evitar un artefacto visual de renderizado. Consulta [La interfaz del sistema se superpone al contenido del onboarding en Android](#system-ui-overlaps-onboarding-content-on-android). :::
Luego, puedes usar este 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".
:::important
Ten en cuenta que debes gestionar qué ocurre cuando el usuario cierra el onboarding. Por ejemplo, debes 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-to-react-native-sdk-v4
---
---
title: "Migrar el SDK de React Native de Adapty a la versión 4.0"
description: "Migra al SDK de React Native de Adapty v4.0 (beta) reemplazando las APIs de paywall por APIs de flow, compatibles tanto con Flow Builder como con Paywall Builder."
---
El SDK de React Native de Adapty 4.0 (beta) introduce los flows y cambia el nombre de las APIs de paywall en consecuencia. Las nuevas APIs funcionan tanto con el nuevo Flow Builder como con el Paywall Builder existente — no se requieren cambios de configuración en el Adapty Dashboard.
## Referencia rápida \{#quick-reference\}
| v3 | v4 |
|---|---|
| `adapty.getPaywall(placementId, locale?, params?)` | `adapty.getFlow(placementId, params?)` |
| `adapty.getPaywallForDefaultAudience(placementId, locale?, params?)` | `adapty.getFlowForDefaultAudience(placementId, params?)` |
| `adapty.getPaywallProducts(paywall)` | `adapty.getPaywallProducts(flow)` |
| `adapty.logShowPaywall(paywall)` | `adapty.logShowFlow(flow)` |
| `AdaptyPaywall` (tipo) | `AdaptyFlow` |
| `createPaywallView(paywall)` | `createFlowView(flow)` |
| `AdaptyPaywallView` (componente) | `AdaptyFlowView` |
| `EventHandlers` (tipo) | `FlowEventHandlers` |
| `onPaywallShown` | `onAppeared` |
| `onPaywallClosed` | `onDisappeared` |
| `onRenderingFailed` | `onError` |
`AdaptyPaywallProduct` mantiene su nombre — los productos siguen perteneciendo a un flow, y `getPaywallProducts` ahora acepta un `AdaptyFlow`. Los métodos `getFlow` y `getFlowForDefaultAudience` ya no reciben un parámetro `locale`. Los métodos de vista `present`, `dismiss`, `setEventHandlers` y `showDialog`, y los manejadores de eventos `onCloseButtonPress`, `onUrlPress`, `onCustomAction`, `onProductSelected`, `onPurchaseStarted`, `onPurchaseCompleted`, `onPurchaseFailed`, `onRestoreStarted`, `onRestoreCompleted`, `onRestoreFailed`, `onLoadingProductsFailed`, `onWebPaymentNavigationFinished` y `onAndroidSystemBack` conservan los mismos nombres que en v3. Algunos comportamientos predeterminados han cambiado — consulta [Cambios en el comportamiento predeterminado](#default-behavior-changes).
## Versión mínima de iOS \{#minimum-ios-version\}
Adapty React Native SDK 4.0 eleva el deployment target mínimo de iOS 13.0 a **iOS 15.0**. Establece tu deployment target de iOS en 15.0 o superior antes de actualizar.
## Instalación \{#installation\}
### Actualizar el paquete \{#update-the-package\}
v4.0 es una versión previa al lanzamiento, así que fija la versión exacta: npm no selecciona versiones pre-release mediante rangos con caret/tilde:
```bash showLineNumbers
npm install react-native-adapty@4.0.0
# or
yarn add react-native-adapty@4.0.0
```
### iOS: los SDKs nativos ahora se obtienen a través de Swift Package Manager \{#ios-native-sdks-now-come-through-swift-package-manager\}
[El repositorio de specs de CocoaPods pasará a ser de solo lectura en diciembre de 2026](https://blog.cocoapods.org/CocoaPods-Specs-Repo/), por lo que a partir de la v4 los SDKs nativos `Adapty`, `AdaptyUI` y `AdaptyPlugin` **ya no se descargan como sub-dependencias de CocoaPods** — el podspec los obtiene a través de **Swift Package Manager** (mediante el helper `spm_dependency`). Esto requiere dos cosas:
- **React Native 0.75 o posterior** — necesario para el helper `spm_dependency` del podspec. Con una versión anterior, `pod install` falla con un error explícito; actualiza React Native primero, o quédate con `react-native-adapty` 3.x.
- **Frameworks dinámicos** — las dependencias SPM requieren enlace dinámico. La forma de habilitarlo difiere entre Expo y React Native sin configuración adicional.
#### Expo
Añade el plugin de configuración [`expo-build-properties`](https://docs.expo.dev/versions/latest/sdk/build-properties/) y establece los frameworks de iOS como dinámicos en `app.json` (o `app.config.js`):
```json showLineNumbers title="app.json"
{
"expo": {
"plugins": [
[
"expo-build-properties",
{
"ios": {
"useFrameworks": "dynamic"
}
}
]
]
}
}
```
Luego instala el plugin y regenera el proyecto nativo:
```bash showLineNumbers
npx expo install expo-build-properties
npx expo prebuild --clean
```
#### Bare React Native
Añade los frameworks dinámicos a tu target de iOS y reinstala los pods:
```ruby showLineNumbers title="ios/Podfile"
use_frameworks! :linkage => :dynamic
```
```bash showLineNumbers
cd ios && pod install --repo-update
```
Si anteriormente incluiste `Adapty`, `AdaptyUI` o `AdaptyPlugin` como sub-dependencias de CocoaPods, elimina primero cualquier línea `pod 'Adapty'`, `pod 'AdaptyUI'` o `pod 'AdaptyPlugin'` de tu `Podfile`.
:::warning
Cambiar del enlace estático predeterminado a frameworks dinámicos puede entrar en conflicto con bibliotecas que aún no admiten encabezados modulares y es incompatible con Flipper. Si encuentras problemas de compilación, consulta este [artículo sobre cómo integrar Swift Package Manager con bibliotecas de React Native](https://www.callstack.com/blog/integrating-swift-package-manager-with-react-native-libraries).
:::
Consulta [Instalar el SDK de Adapty](sdk-installation-reactnative) para ver la configuración completa.
## Obtención de flows \{#fetching-flows\}
### getPaywall → getFlow
El tipo devuelto cambia de `AdaptyPaywall` a `AdaptyFlow`, y se elimina el parámetro `locale` — cuando renderizas un flow, el idioma se resuelve automáticamente; para paywalls personalizados, todos los idiomas están disponibles en `flow.remoteConfigs`:
```diff showLineNumbers
- const paywall = await adapty.getPaywall('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
```
`getPaywallForDefaultAudience` se renombra de la misma forma:
```diff showLineNumbers
- const paywall = await adapty.getPaywallForDefaultAudience('YOUR_PLACEMENT_ID', 'en');
+ const flow = await adapty.getFlowForDefaultAudience('YOUR_PLACEMENT_ID');
```
### getPaywallProducts(paywall) → getPaywallProducts(flow)
`getPaywallProducts` mantiene su nombre pero ahora recibe un `AdaptyFlow`:
```diff showLineNumbers
- const products = await adapty.getPaywallProducts(paywall);
+ const products = await adapty.getPaywallProducts(flow);
```
## Modelo de datos \{#data-model\}
`getFlow` devuelve un `AdaptyFlow` en lugar de un `AdaptyPaywall`, y la forma del objeto ha cambiado:
| Campo de v3 `AdaptyPaywall` | Campo de v4 `AdaptyFlow` | Acción |
|---|---|---|
| `remoteConfig?` (único) | `remoteConfigs?: AdaptyRemoteConfig[]` (array) | Un flow lleva un Remote Config por idioma configurado. Lee el que corresponde al usuario: `flow.remoteConfigs?.find((c) => c.lang === 'en')`. |
| `products` | `flow.paywalls[i].productIdentifiers` | Los identificadores de producto ahora están en cada variación del flow, no en el flow en sí. |
| `webPurchaseUrl?` | `flow.paywalls[i].webPurchaseUrl` | Se ha movido del flow a cada variación de paywall. |
| `version?: number` | `flowVersionId?: string` | Renombrado, y el tipo ha cambiado de `number` a `string`. |
| `hasViewConfiguration` | eliminado | Elimina cualquier comprobación de `hasViewConfiguration` de tu código. |
| `requestLocale` | eliminado | La configuración regional ya no forma parte del modelo. |
| _(nuevo)_ | `paywalls: AdaptyFlowPaywall[]` | Cada entrada es una variación de paywall dentro del flow. |
| _(nuevo)_ | `responseCreatedAt: number` | Marca de tiempo de la respuesta del servidor, en milisegundos. |
Product identifiers moved from the flow to each variation:
```diff showLineNumbers
- const ids = paywall.products;
+ const ids = flow.paywalls[0].productIdentifiers;
```
## Métodos de paywall web \{#web-paywall-methods\}
`openWebPaywall` y `createWebPaywallUrl` mantienen sus nombres, pero el primer argumento es ahora un `AdaptyFlowPaywall` (una variante de flow) en lugar de un `AdaptyPaywall`. Puedes seguir pasando un `AdaptyPaywallProduct`.
```diff showLineNumbers
const flow = await adapty.getFlow('YOUR_PLACEMENT_ID');
- await adapty.openWebPaywall(paywall);
+ await adapty.openWebPaywall(flow.paywalls[0]);
```
## Seguimiento de visualizaciones de flows \{#tracking-flow-views\}
### logShowPaywall → logShowFlow
`logShowPaywall` ha pasado a llamarse `logShowFlow` y ahora recibe un `AdaptyFlow`. El evento se sigue registrando contra la misma variación, por lo que las métricas de embudo y las pruebas A/B existentes siguen funcionando sin cambios en el dashboard.
```diff showLineNumbers
- await adapty.logShowPaywall(paywall);
+ await adapty.logShowFlow(flow);
```
Al igual que en v3, no es necesario llamar a este método cuando se muestran flows o paywalls renderizados por el [Flow Builder](adapty-flow-builder) o el [Paywall Builder](adapty-paywall-builder) — Adapty registra esas vistas automáticamente.
## Mostrar flows \{#displaying-flows\}
### createPaywallView → createFlowView
Renombra la función de fábrica y pasa el `AdaptyFlow`. Los métodos del controlador devuelto (`present`, `dismiss`, `setEventHandlers`, `showDialog`) no cambian:
```diff showLineNumbers
- import { createPaywallView } from 'react-native-adapty';
+ import { createFlowView } from 'react-native-adapty';
- const view = await createPaywallView(paywall);
+ const view = await createFlowView(flow);
await view.present();
```
### AdaptyPaywallView → AdaptyFlowView
Si renderizas con el componente React, renómbralo y pasa el prop `flow`:
```diff showLineNumbers
- import { AdaptyPaywallView } from 'react-native-adapty';
+ import { AdaptyFlowView } from 'react-native-adapty';
- ```diff showLineNumbers - subscriptionDetails?: AdaptySubscriptionDetails; + subscription?: AdaptySubscriptionDetails; ``` 2. [AdaptySubscriptionDetails](https://react-native.adapty.io/interfaces/adaptysubscriptiondetails): - `promotionalOffer` ha sido eliminado. Ahora la oferta promocional se entrega dentro de la propiedad `offer` solo si está disponible. En ese caso, `offer?.identifier?.type` será `'promotional'`. - `introductoryOfferEligibility` ha sido eliminado (las ofertas solo se devuelven si el usuario es elegible). - `offerId` ha sido eliminado. El ID de la oferta ahora se almacena en `AdaptySubscriptionOffer.identifier`. - `offerTags` se ha movido 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 ha eliminado del modelo `AdaptyDiscountPhase`. El identificador de 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. ## Actualizar la realización de compras \{#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 gestionarse 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 }) ``` ## Modificar eventos de compra del Paywall Builder \{#modify-paywall-builder-purchase-events\} Anteriormente: - Las compras canceladas activaban el callback `onPurchaseCancelled`. - Las compras pendientes devolvían el código de error `25: 'pendingPurchase'`. Ahora: - Ambos casos se gestionan 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 Actualiza el código de tu app para 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 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 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 Actualiza el código de tu aplicación 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 Actualiza el código de tu aplicación 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 aplicación móvil como se indica 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 Actualiza el código de tu aplicación 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).