Suscripciones de RevenueCat: 16 casos límite y noches en vela
Puntos clave: Implementar suscripciones in-app con RevenueCat parece sencillo: tres niveles, un SDK. En realidad, son 16 casos límite de cambios de plan, obligaciones legales francesas sobre la visualización de precios con IVA incluido, y un singleton PurchaseService que debe gestionar la restauración de compras en tiempo real. Aquí está todo lo que la documentación no dice.
Cuando decidí monetizar TAMSIV, la elección de RevenueCat fue obvia. Ellos gestionan la complejidad de las tiendas por ti — los recibos de Google Play, la validación del servidor, el seguimiento de las suscripciones. Bueno, en teoría.
En la práctica, pasé tres semanas en la implementación. No por RevenueCat en sí (el SDK está bien hecho), sino por todos los casos límite que nadie menciona en los tutoriales. Aquí está la experiencia completa.
¿Cómo estructurar los niveles de suscripción de una aplicación de IA?
TAMSIV ofrece tres planes:
- Free — Acceso a funciones básicas con límites diarios. Suficiente para descubrir la aplicación, no para un uso intensivo.
- Pro — Todo desbloqueado: generación de imágenes de IA, STT en la nube de Deepgram (mejor que el nativo en entornos ruidosos), notas ilimitadas, todas las voces TTS.
- Team — La capa colaborativa completa: grupos jerárquicos de hasta 6 niveles, asignaciones, listas de verificación de grupo, permisos avanzados.
La elección de tres niveles no es arbitraria. Los estudios muestran que tres opciones maximizan la conversión — el efecto de anclaje empuja a los usuarios hacia el plan intermedio. El Free atrae, el Pro convierte, el Team monetiza a los equipos.
El archivo planLimits.ts
En el código, un archivo config/planLimits.ts centraliza todas las feature gates. Cada funcionalidad verifica el plan activo antes de ejecutarse:
// Ejemplo simplificado
const PLAN_LIMITS = {
free: { dailyVoiceTasks: 5, aiImages: 0, cloudSTT: false },
pro: { dailyVoiceTasks: -1, aiImages: 20, cloudSTT: true },
team: { dailyVoiceTasks: -1, aiImages: 50, cloudSTT: true },
};
Este archivo único es la fuente de la verdad. No hay condiciones if (plan === 'pro') dispersas en el código — todo pasa por los límites configurados. Cuando modifico un plan, toco un solo archivo.
¿Cuáles son los 16 casos límite de cambios de plan?
Aquí es donde se vuelve una pesadilla. Un usuario puede:
- Actualizar: Free → Pro, Free → Team, Pro → Team
- Degradar: Team → Pro, Team → Free, Pro → Free
- Cambiar de período: Mensual → Anual, Anual → Mensual
- Combinar ambos: Actualización + cambio de período
- Cancelar: Con acceso hasta el final del período
- Reactivar: Antes o después de la expiración
- Restaurar: En un nuevo teléfono
Conté 16 casos distintos. Para cada uno, hay que gestionar:
- El momento de activación: Una actualización entra en vigor inmediatamente. Una degradación se pospone hasta el final del período actual.
- El prorrateo: Google Play calcula automáticamente el prorrateo para las actualizaciones. Pero tú debes mostrarlo correctamente en la interfaz de usuario.
- La actualización de las feature gates en tiempo real: Cuando un usuario actualiza, las nuevas funcionalidades deben desbloquearse instantáneamente, sin reiniciar la aplicación.
- La visualización correcta: El plan correcto, la fecha de expiración correcta, el precio correcto, el estado correcto.
Tres días de pruebas para cubrirlo todo. Es tedioso, metódico y absolutamente indispensable. Si falta un solo caso, recibirás un correo electrónico de un usuario furioso que pagó por un Pro y sigue en Free.
¿Cómo gestionar las obligaciones legales francesas para las suscripciones?
Si vendes en Francia, la DGCCRF impone reglas estrictas:
- Precio con IVA obligatorio: En Francia, siempre se muestran los precios con IVA (Toutes Taxes Comprises) para los consumidores. Las tiendas proporcionan los precios localizados, pero tú debes verificar que la visualización respeta la legislación.
- Mención "Precio con IVA": El texto debe ser explícito.
- Enlace a las CGV: Las Condiciones Generales de Venta deben ser accesibles desde la pantalla de pago.
- Información sobre el derecho de desistimiento: Para las compras digitales, el derecho de desistimiento se aplica bajo ciertas condiciones. Debes informar al usuario.
- Duración del compromiso: El usuario debe saber claramente si está suscribiendo una suscripción mensual o anual, y cómo cancelarla.
No respetar estas reglas es arriesgarse a un rechazo de la aplicación por parte de Google o una multa de la DGCCRF. Las CGV y menciones legales de TAMSIV son accesibles desde el sitio web y desde la aplicación.
¿Cómo arquitecturar el PurchaseService en React Native?
Todo pasa por un singleton PurchaseService. Este es el patrón que utilizo para todos los servicios en TAMSIV — ConversationService, CalendarService, GamificationService, todos siguen el mismo modelo (lo menciono en el artículo sobre refactoring clean architecture).
El PurchaseService hace 4 cosas:
- Inicializa RevenueCat al iniciar la aplicación con la clave API del proyecto.
- Escucha los cambios de estado: actualización, degradación, expiración, restauración. Cada cambio desencadena una actualización de las feature gates.
- Expone el plan activo a través de un hook:
usePurchase()devuelve el plan actual, la fecha de expiración y las funcionalidades disponibles. - Sincroniza con Supabase: El plan activo también se almacena en la base de datos para que el backend pueda verificar los permisos (por ejemplo, limitar el número de solicitudes de voz para el plan Free).
La restauración de compras
Este es el caso más complicado. Un usuario cambia de teléfono, reinstala la aplicación y espera encontrar su suscripción Pro. RevenueCat gestiona esto a través de restorePurchases(), pero el momento es crítico: la restauración puede tardar unos segundos, durante los cuales el usuario está en modo Free. Si no gestionas este estado intermedio, el usuario ve una pantalla "Actualizar a Pro" cuando ya es Pro.
La solución: un estado de "cargando" explícito al inicio, que bloquea la visualización de las feature gates hasta que RevenueCat haya confirmado el plan activo.
¿Qué métricas seguir para las suscripciones?
RevenueCat proporciona un excelente panel de control. Las métricas que sigo diariamente:
- MRR (Monthly Recurring Revenue): Los ingresos recurrentes mensuales. La métrica reina.
- Conversión Free → Pro: ¿Qué porcentaje de usuarios gratuitos actualizan?
- Churn rate: ¿Cuántos suscriptores cancelan cada mes?
- Trial conversion: Si ofreces una prueba gratuita, ¿qué porcentaje convierte?
- Revenue per user: Los ingresos promedio por usuario activo.
Estas métricas alimentan el panel de administración que construí para monitorear la salud del proyecto en tiempo real.
¿Qué errores evitar con RevenueCat?
Aquí están las trampas en las que caí:
- No probar en sandbox: Google Play tiene un modo sandbox para las compras. Úsalo sistemáticamente. Un error de pago en producción es un reembolso + un usuario perdido.
- Olvidar la migración de usuarios existentes: Si añades suscripciones a una aplicación existente, los usuarios actuales deben ser migrados al plan Free correctamente. Sin degradaciones silenciosas.
- No gestionar el modo avión: RevenueCat almacena en caché el plan activo localmente. Pero si el usuario está sin conexión durante una actualización, las feature gates pueden desincronizarse. Prevé un mecanismo de reconciliación al volver a estar en línea.
- Ignorar los webhooks: RevenueCat envía webhooks para cada evento (compra, cancelación, renovación). El backend debe procesarlos para mantener Supabase sincronizado.
¿Cómo interactúa el sistema de referidos con las suscripciones?
TAMSIV tiene un sistema de referidos que ofrece un mes gratis de Pro o Team cuando un usuario invita a un amigo. Esto añade una capa de complejidad: el código promocional de RevenueCat debe aplicarse correctamente, el mes gratis debe comenzar en el momento adecuado, y el regreso al plan original debe ser transparente.
La interacción referidos + suscripción generó 3 de los 16 casos límite mencionados anteriormente. Es una excelente palanca de crecimiento, pero requiere una implementación cuidadosa.
Preguntas Frecuentes
¿Por qué RevenueCat en lugar de la API nativa de Google Play Billing?
La API nativa de Google Play Billing es compleja, está mal documentada y cambia regularmente. RevenueCat abstrae esta complejidad con un SDK limpio, un panel de análisis y soporte multiplataforma (Android + iOS). El costo (gratis hasta $2.5k MRR, luego 1% de los ingresos) es insignificante en comparación con el tiempo de desarrollo ahorrado.
¿Debería ofrecer una prueba gratuita?
Depende de tu modelo. Para TAMSIV, el plan Free ya es una prueba permanente de las funcionalidades básicas. Una prueba gratuita del Pro durante 7 días está en fase de prueba — los primeros datos muestran una tasa de conversión más alta, pero también un churn mayor después de la prueba.
¿Cómo mostrar los precios en varias monedas?
Google Play proporciona los precios localizados a través de la API. RevenueCat los expone en offerings.current.availablePackages. No tienes que gestionar la conversión de divisas tú mismo — la tienda siempre muestra el precio local. En Francia, es en euros con IVA incluido.
¿Qué sucede si Google Play está caído?
RevenueCat almacena en caché el plan activo en el dispositivo. Si Google Play no está disponible temporalmente, el usuario mantiene su acceso. El riesgo es mínimo porque Google Play tiene un tiempo de actividad del 99.99%. Pero el PurchaseService prevé un fallback al caché local en caso de un tiempo de espera de la API.
¿Cómo gestionar el IVA para las ventas internacionales?
La tienda es la que gestiona el IVA, no tú. Google Play recauda y remite el IVA según el país del comprador. Tú recibes el importe neto. Pero aún así debes mostrar los precios con IVA incluido en la aplicación y respetar las reglas de visualización del país del usuario.