← Toda la documentación

Medir ingresos

Adjunta ingresos a cualquier evento con $revenue y $currency, y dónde aparecen esos números.

Los ingresos no son un tipo de evento aparte. Los adjuntas a cualquier evento que ya envíes, con dos propiedades reservadas.

lp.track('ticket_purchased', { $revenue: 49.99, $currency: 'USD', ticket_type: 'vip' });

Esa es toda la API.

Las dos propiedades reservadas

PropiedadTipoQué pasa
$revenuenúmeroSe promueve a una columna revenue_micros como round(valor × 1_000_000)
$currencystring, máximo 8 caracteresSe pasa a mayúsculas en una columna currency

Ambas se quitan de properties antes de guardar el evento. En el ejemplo de arriba, el evento almacenado conserva ticket_type: 'vip' y nada más: $revenue y $currency pasan a ser sus propias columnas.

Infinity y NaN se ignoran.

Por qué micros

Los ingresos se guardan como micros enteros: 49.99 queda como 49990000. Las sumas sobre enteros son exactas y deterministas. Las sumas sobre floats se desvían, y dos personas corriendo la misma consulta sobre los mismos datos pueden obtener totales distintos. Guardar micros hace imposible esa clase de error.

No tienes que hacer nada al respecto. Envía un número normal; la conversión ocurre al ingresar.

Cualquier otra propiedad con $ se rechaza

$revenue y $currency son las únicas claves de propiedad que pueden empezar con $. Cualquier otra clave de propiedad con $ rechaza el evento completo.

// Rechazado — se descarta el evento entero
lp.track('purchase', { $revenue: 20, $user_id: 'user_8f21c' });

Es a propósito: la identidad nunca se puede definir desde las propiedades. Usa identify() en el navegador, o el campo user_id en los eventos desde el servidor.

Los límites habituales de propiedades siguen aplicando al resto del evento: 64 propiedades, claves de 64 caracteres, strings de 1024 caracteres, 8192 bytes serializados. La tabla completa está en la Referencia del SDK.

Envíalos desde tu backend

El error más común al medir ingresos es disparar el evento desde el navegador en una página de “gracias por tu compra”.

Esa página se puede recargar, y ahí se cuenta doble. Se puede guardar en favoritos y volver a visitar, y se cuenta doble otra vez. A veces incluso se puede llegar sin haber pagado. Y un pago que falla después del redirect, o una tarjeta que se rechaza de forma asíncrona, igual quedó contado.

Envía los ingresos desde tu backend, después de que el pago realmente se concrete: desde tu handler del webhook de Stripe, o donde sea que tu orden quede en firme.

await fetch('https://collector.launchpulse.dev/v1/events', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.LAUNCHPULSE_SECRET}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    event: 'subscription_paid',
    user_id: order.userId,
    properties: {
      $revenue: order.amount / 100,
      $currency: order.currency,
      plan: order.plan,
    },
  }),
});

La configuración completa, con el endpoint y sus límites, está en Eventos desde el servidor.

Usa el mismo user_id que tu código de navegador le pasa a identify(). Eso es lo que conecta el pago con la sesión, la fuente y la campaña que lo produjeron.

Moneda

$currency es un string de máximo 8 caracteres, que se pasa a mayúsculas al ingresar. Envía un código ISO: USD, EUR, MXN.

LaunchPulse no convierte entre monedas. Si cobras en varias, los totales suman los números crudos sin importar la moneda, así que conviene normalizar a una sola antes de enviar, o leer los ingresos por moneda.

Dónde aparecen los ingresos

  • El bloque de Ingresos en el panel Pulse — se muestra solo cuando no hay un evento de primer valor configurado. Una vez que defines uno, ese bloque muestra activación. Mira Conversiones y activación.
  • La métrica de Ingresos en insights — para desglosar ingresos por fuente, campaña o cualquier propiedad.
  • Las tarjetas del portafolio — ingresos por proyecto, en toda tu cuenta.

Si los ingresos aparecen en 0

Vale la pena saber esto antes de que te confunda.

El almacén de analítica descarta las columnas que están completamente vacías para un proyecto. Si nunca enviaste $revenue en un proyecto, la columna no existe y los ingresos se leen como 0 en todos lados. Eso no es un error ni una consulta rota: sencillamente no hay nada ahí.

Cuando cae tu primer evento con $revenue, la columna aparece y los números empiezan a poblarse. Así que si los ingresos parecen clavados en cero:

  1. Revisa el registro de eventos y abre un evento de compra. ¿Tiene un valor de ingreso?
  2. Si la propiedad sigue dentro de properties como $revenue literal, el evento se guardó pero algo no está calzando: confirma que enviaste un número, no un string. "49.99" no es 49.99.
  3. Recuerda que un 2xx de la API de ingesta no prueba que tu clave sea válida. Las claves desconocidas, revocadas y pausadas reciben todas un 2xx uniforme. El registro de eventos es la única confirmación real.

Un ejemplo completo

Un newsletter de pago, midiendo tanto el registro gratis como la conversión a pago:

// Navegador — alguien se suscribe a la lista gratuita
lp.track('newsletter_signup', { source_page: '/pricing' });
// Backend — webhook de Stripe, después de invoice.paid
await sendToLaunchPulse({
  event: 'subscription_paid',
  user_id: customer.internalId,
  properties: {
    $revenue: invoice.amount_paid / 100,
    $currency: invoice.currency,
    plan: 'annual',
    is_renewal: invoice.billing_reason === 'subscription_cycle',
  },
});

Ahora la métrica de Ingresos en insights puede desglosar por plan, o por is_renewal para separar ingresos nuevos de renovaciones, o por first_source para ver qué canal de adquisición produce clientes que pagan y no solo tráfico.

SiguienteEventos desde el servidor

Hablemos

¿Dudas sobre LaunchPulse o quieres que te lo mostremos? Escríbenos y te responde una persona real.

O escríbenos a hello@launchpulse.dev