Saltar al contenido principal

Analítica de creador — Referencia técnica

← Volver a Analítica de creador

El panel es en su mayoría una composición de analíticas que ya existían en el backend (resumen de ganancias, ganancias por fuente, ganancias de posts exclusivos, conteo de suscriptores), más varias queries de backend genuinamente nuevas agregadas a lo largo de distintas pasadas: una serie temporal diaria de ganancias (Fase D.4 / roadmap 4.12), retención/abandono de suscriptores mensual, y un estado de ganancias anual por año calendario. La página que reemplaza era un stub honesto que declaraba que la analítica de creador "no tenía soporte de backend"; eso ya estaba desactualizado.

Dónde vive esto

Backend

Frontend

  • apps/frontend-nextjs/src/page-components/settings/InsightsAndToolsPage.tsx (ruta /settings/insights-tools) — el panel. Era un stub honesto; ahora compone las tarjetas de abajo, consulta myPostPurchaseEarnings, subscriberCount y subscriberRetention(months: 6), y tiene una exportación "Exportar CSV" del lado del cliente (handleExportCsv) que arma un CSV a partir de los números del resumen de ganancias y de la tabla de retención de 6 meses ya presentes en memoria — sin una query de exportación dedicada.
  • apps/frontend-nextjs/src/page-components/settings/CreatorSalesPage.tsx (ruta /settings/sales, "Ventas y ganancias") — pestañas de ventas/compras sobre myPostPurchaseSales / myPurchasedPosts, más una lista "Mejores compradores" calculada del lado del cliente (byBuyer) que agrupa la página de ventas actual por buyer.id con conteos de venta por comprador y totales de sellerEarningsCoins.
  • apps/frontend-nextjs/src/components/payouts/EarningsTrendChart.tsx — la gráfica de barras de tendencia diaria (recharts), consultando myEarningsTimeSeries con un selector de rango 7d/30d/90d.
  • apps/frontend-nextjs/src/components/payouts/EarningsSummaryCard.tsx, EarningsBySourceChart.tsx y EarningsStatementCard.tsx — preexistentes, reutilizados sin cambios (EarningsStatementCard consulta myEarningsStatement para un estado de cuenta descargable por año y por lo demás está documentada bajo Retiros). Las dos primeras también solían aparecer en /settings/get-coins (la página de compra de monedas) — se quitaron de ahí: duplicaban este dashboard y, peor aún, comprar tus propias monedas subía visiblemente "ganado de por vida" en esa tarjeta (ver la nota sobre la corrección de lifetimeEarned en Retiros).

Checklist de implementación técnica

  • myEarningsTimeSeries(days) — query/resolver/manager/access-service, serie diaria rellenada con ceros; EarningsTrendChart.tsx
  • Ventas de posts exclusivos — expone myPostPurchaseEarnings (el backend ya existía; sin consumidor de frontend antes)
  • Conteo de suscriptores activos — expone subscriberCount(creatorId)
  • Tarjetas de resumen y por-fuente reutilizadas
  • Serie temporal de retención de suscriptores — query/resolver/manager subscriberRetention(months), gráfica de barras de 6 meses más abandono en InsightsAndToolsPage.tsx
  • Vista de ventas por comprador — myPostPurchaseSales expuesto mediante una lista "Mejores compradores" agrupada del lado del cliente en CreatorSalesPage.tsx (/settings/sales)
  • Exportación CSV — solo del lado del cliente (handleExportCsv en InsightsAndToolsPage.tsx); sin query de exportación dedicada
  • Estado de ganancias anual — myEarningsStatement(year) vía EarningsStatementCard.tsx, también renderizado en esta página (documentación principal bajo Retiros)

API de GraphQL

# Daily earnings trend, zero-filled, last N days (default 30, max 365)
query MyEarningsTimeSeries($days: Int) {
myEarningsTimeSeries(days: $days) {
date # YYYY-MM-DD
earnings # coins earned that day
}
}

# Monthly subscriber retention/churn, oldest -> newest (default 6 months, max 24)
query SubscriberRetention($months: Int) {
subscriberRetention(months: $months) {
month # YYYY-MM
newSubscribers
churned
activeAtEnd
churnRate # percent
retentionRate # percent
}
}

# Reused on the dashboard
query DashboardExtras($creatorId: ID!) {
myEarningsSummary { availableForCashout unmaturedRecentEarnings }
myEarningsBySource(days: 30) { tips contentSales profileSubscriptions groupSubscriptions marketplace other }
myPostPurchaseEarnings { totalSales totalRevenue totalEarnings platformFees }
myPostPurchaseSales(limit: 20, offset: 0) { id coinPrice sellerEarningsCoins status createdAt buyer { id username } }
subscriberCount(creatorId: $creatorId)
myEarningsStatement(year: 2026) { totalEarnings tips contentSales profileSubscriptions groupSubscriptions marketplace other totalCashedOut }
}

Notas

  • La definición de ganancias es compartida. Tanto myEarningsBySource como myEarningsTimeSeries cuentan los mismos tipos de transacción como "ganancias", así que el total de la tendencia y el total por fuente coinciden para una ventana dada. Las compras de monedas y los bonos otorgados por admin se excluyen de la tendencia (si no, aparecerían como picos espurios).
  • El relleno con ceros ocurre en el manager, no en SQL — el access-service devuelve solo los días con ganancias, y getEarningsTimeSeries en el manager lo expande en un arreglo continuo día por día. Esto mantiene la query barata mientras le da a la gráfica un eje limpio.
  • Los buckets de retención se calculan en código de aplicación, no en SQL — getSubscriberRetention obtiene una sola vez todo el historial de UserSubscription del creador (getAllByCreatorForAnalytics) y lo agrupa en meses calendario en JS. "Activos al final" de un mes cuenta las suscripciones creadas antes del fin del bucket y no canceladas antes de ese punto; la tasa de abandono es el número de bajas en el mes sobre los activos al inicio.
  • Las exportaciones de CSV/estado de cuenta son del lado del cliente. Tanto el botón "Exportar CSV" en Insights & Tools como la descarga del estado de cuenta en EarningsStatementCard construyen su archivo (CSV / texto plano) a partir de datos de query ya obtenidos en el navegador — no hay un endpoint de exportación del lado del servidor ni almacenamiento de archivos involucrado.