← Guías

Cómo cobrar suscripciones en tu app

RevenueCat en iOS y Android. Los 5 pasos, y las dos cosas que te rechazan la publicación.

CAT8 min

Esto es lo que corre hoy en NutrIA, con más de 100.000 descargas y más de 5.000 suscriptores. Stack: Expo 54, React Native 0.81, react-native-purchases 8.9.

Qué hace RevenueCat. Integras una sola vez y él habla con la App Store y con Google Play por ti. Una integración en vez de una por tienda.

La alternativa es conectarte directo a StoreKit y a Google Play Billing, y escribir tú la validación de recibos, los reintentos, las renovaciones, el sandbox y la sincronización entre las dos. Hasta cierto volumen RevenueCat es gratis.

1. Crear el producto en las tiendas

Antes de tocar código, el producto tiene que existir donde se cobra.

En App Store Connect creas un grupo de suscripción y adentro los planes. Con uno mensual y uno anual arrancas.

En Google Play Console es lo mismo, en Productos, Suscripciones.

Usa el mismo ID en las dos tiendas:

pro_mensual
pro_anual
App Store Connect/Suscripciones
ProductoTipoPrecio
nutria_pro_mensualAuto-renovable$4.990
nutria_pro_anualAuto-renovable$39.990
Los dos planes creados.

El precio anual no es el mensual por doce. Ponle 30% o 40% de descuento. Lo que compras con eso es que la persona no tenga doce oportunidades al año de cancelar.

2. Conectar RevenueCat

RevenueCat es el que habla con las tiendas por ti.

Entras a revenuecat.com, creas la cuenta, y de ahí él mismo te va guiando por un onboarding paso a paso: crear el proyecto, conectar la App Store, conectar la Play Store. No tienes que adivinar el orden ni buscar dónde va cada cosa, te lo va pidiendo.

Lo único que conviene tener listo antes:

  • iOS: una App Store Connect API Key. Se genera en Users and Access, Integrations.
  • Android: una cuenta de servicio de Google Cloud con acceso a Play.

Listo eso, RevenueCat lee tus compras de las dos tiendas en un solo lugar.

Al final del onboarding te va a pedir que instales el SDK en tu proyecto:

npx expo install react-native-purchases

Puedes instalarlo ahí mismo. La configuración en código la vemos en el paso 4.

Si quieres usar los paywalls prearmados de RevenueCat necesitas también react-native-purchases-ui. En NutrIA no lo usamos, el paywall es nuestro.

3. El entitlement

Es el único concepto de toda la guía y es donde se equivoca casi todo el mundo.

El entitlement es el pase. Los productos son las distintas formas de comprarlo.

Como el pase del gimnasio. Da lo mismo si lo pagaste mensual, anual o te lo regalaron. El pase es el mismo y es lo único que revisa el portero.

ENTITLEMENT
🎟️Proel pase

Tu app pregunta ¿tiene el pase?

PRODUCTOS
mensual$4.990 / mes
anual$39.990 / año
promolanzamiento
el que agregues mañanasin tocar código

Las formas de comprarlo

Un entitlement, muchos productos. Por eso puedes cambiar precios sin tocar la app.

Creas un entitlement, le pones Pro, y adentro le cuelgas el mensual y el anual.

RevenueCat/Entitlements
proEntitlement
nutria_pro_mensualadjunto
nutria_pro_anualadjunto
Un entitlement con los dos productos adjuntos.

Tu app pregunta ¿tiene el pase?, nunca ¿cuál compró?.

Yo lo hice al revés. Al principio conecté la app directo a los IDs de los productos. Cuando quise cambiar precios y agregar un plan, tuve que rehacer el paywall y publicar una versión solo por eso. Con entitlements agregas el plan en el dashboard y la app ni se entera.

4. Conectar el SDK

Si no lo instalaste durante el onboarding:

npx expo install react-native-purchases

Se configura una sola vez, al arrancar la app. En NutrIA vive en app/_layout.tsx:

import Purchases from 'react-native-purchases';
import { Platform } from 'react-native';

if (Platform.OS === 'ios') {
  Purchases.configure({ apiKey: 'appl_TU_KEY' });
} else if (Platform.OS === 'android') {
  Purchases.configure({ apiKey: 'goog_TU_KEY' });
}

Purchases.setLogLevel(Purchases.LOG_LEVEL.DEBUG);

Las keys son distintas por plataforma y empiezan con appl_ y goog_. Son públicas por diseño, van dentro del binario, así que no son un secreto que tengas que esconder.

Después de eso conviene envolver todo en un hook y no volver a tocar el SDK directamente:

const { offerings, purchasePackage, isPro } = useRevenueCat(user?.id);

Si estás vibecodeando, pásale esto a tu agente en vez de escribirlo:

Instala y configura react-native-purchases en este proyecto Expo.

- Configura Purchases una sola vez en el layout raíz, con la key
  de iOS o la de Android según Platform.OS
- Crea un hook useRevenueCat(userId) que exponga:
  offerings, purchasePackage(pkg), restore(), isPro, cargando
- isPro se calcula leyendo el entitlement "Pro"
- Escucha cambios con addCustomerInfoUpdateListener
- Nunca chequees por product id. Siempre por el entitlement "Pro".

El último punto es el que importa. Si no se lo dices explícito, el agente te va a chequear por producto, que es justo el error del paso 3.

Lo que queda funcionando, en esencia:

// Traer los planes para el paywall
const offerings = await Purchases.getOfferings();
const paquetes = offerings.current?.availablePackages ?? [];

// Cobrar
const { customerInfo } = await Purchases.purchasePackage(paquete);

// Preguntar si tiene el pase. Siempre por entitlement.
const isPro = !!customerInfo?.entitlements?.active?.Pro;

Ojo con el nombre del entitlement. Es sensible a mayúsculas. Si en RevenueCat lo creaste como Pro, en el código tiene que ser Pro.

5. Y ahora ves todo

Desde acá tienes el dashboard: suscriptores activos, cuánto facturas, churn, LTV, de dónde vienen, qué plan convierte mejor.

RevenueCat/Overview
Suscriptores activos5.041
MRR$11.2K
Churn mensual4.8%
LTV$58
Esto es lo que reviso todas las semanas.

Las tres que yo miro:

  • Churn mensual. Cuánta gente se va. Si sube dos meses seguidos es problema de producto, no de precio.
  • Trial a pago. Si tienes prueba gratis, este número te dice si la prueba es muy corta o muy larga.
  • Mensual contra anual. Si casi todos eligen mensual, tu descuento anual es muy chico.

Las dos cosas que te rechazan la app

Esto es lo que más rechazos causa y casi nunca está en los tutoriales.

Botón de restaurar compras. Apple lo exige. Si alguien cambia de teléfono o reinstala, tiene que poder recuperar su suscripción sin volver a pagar. Es una línea:

await Purchases.restorePurchases();

Ponlo visible en el paywall y en ajustes. Si no está, te rechazan.

Las condiciones a la vista. En la misma pantalla donde cobras tienen que estar: qué incluye, cuánto cuesta, cada cuánto se renueva, y los links a términos y política de privacidad. No en otra pantalla, ahí mismo.

Probar sin volverte loco

Las compras no se prueban con tu cuenta normal.

En iOS creas un Sandbox Tester en App Store Connect y lo pones en Ajustes, App Store, Cuenta de Sandbox. En sandbox el tiempo va acelerado: una suscripción mensual se renueva cada 5 minutos, así que ves un ciclo completo de renovación y cancelación en media hora.

En Android subes la app a testing interno y agregas tu correo como tester con licencia.

Mientras desarrollas, deja setLogLevel(DEBUG) prendido. Los errores de configuración de RevenueCat son mudos si no lo tienes.

Los errores que cometí

Chequear por producto en vez de entitlement. Me costó rehacer el paywall y una publicación entera.

No poner el botón de restaurar en la primera versión. Rechazo, y una semana esperando la siguiente revisión.

Poner el precio bajo por miedo. No era estrategia. Era que no creía que la app valiera más. Cuando lo subí no se fue casi nadie.

No mirar el churn los primeros meses. Estaba obsesionado con las descargas. Las descargas no pagan el servidor.