Architecture

Por qué los reembolsos van solo a GA4

Un reembolso es una conversión que corrió hacia atrás. GA4 tiene un evento nativo exactamente para eso: descuenta los ingresos del compra original. Ninguna plataforma publicitaria tiene un evento de reembolso real, así que enviar un "Refund" personalizado no aporta nada y arriesga contaminar justo los recuentos sobre los que corre tu puja. Beaconry enruta los reembolsos solo a GA4. Aquí tienes el razonamiento, el detalle a nivel de cable y por qué esto se adelanta al ticket de soporte "mi reembolso desapareció de Meta".

Tiempo de lectura: ~7 minPublicado: 2026-06-08

El principio en una frase

Un evento de conversión va a un canal solo si ese canal tiene un concepto real de él. Para los reembolsos, exactamente un destino califica: GA4. Cada plataforma publicitaria, o bien no tiene ningún evento de reembolso, o bien tiene una casilla que haría daño si dispararas hacia ella. Así que la regla no es "envía el reembolso a todas partes donde se acepte técnicamente", sino "envíalo solo donde signifique algo". Ese único principio decide todo el comportamiento, y vale la pena entender por qué, porque la alternativa tentadora (rociar un evento de reembolso personalizado a cada canal que no lo rechace) es justo el tipo de decisión bienintencionada que corrompe silenciosamente un informe de campaña.

Qué hace GA4 realmente con un reembolso

GA4 trata refund como un evento de e-commerce de primera clase, con el mismo estatus que purchase, add_to_cart o view_item. No es un evento personalizado que tengas que definir. Cuando GA4 recibe un refund con un transaction_id que coincide con un purchase anterior, descuenta los ingresos reembolsados de esa compra en los informes de monetización. Las cifras "Total revenue" y "Purchase revenue" del cliente bajan en el importe reembolsado, automáticamente, sin aritmética de informes personalizados.

Ese descuento es toda la razón por la que vale la pena enviar reembolsos. Sin él, un reembolso es solo un número en una tabla que alguien tiene que recordar restar a mano. Con él, los números de ingresos de GA4 se mantienen veraces por sí solos. Esta es una capacidad que las plataformas publicitarias simplemente no exponen, y es lo que convierte a GA4 en el único canal donde un reembolso se gana su lugar en el cable.

Qué hacen las plataformas publicitarias con un reembolso: nada útil

Recorre los canales a los que Beaconry reenvía y hazte la única pregunta que importa, "¿tiene esta plataforma un evento de reembolso nativo que descuente de la compra?":

  • Meta CAPI: no. Refund no es un tipo de evento soportado por la Conversions API. Meta sí tiene una Cancellation-and-Refund API, pero esa es la API de gestión de pedidos de la Commerce Platform para administrar pedidos de tienda, una superficie completamente distinta, no la Conversions API sobre la que optimizan el píxel y CAPI. Un evento Refund personalizado enviado a CAPI es inerte: nunca aparece en la vista estándar del Events Manager y los algoritmos de puja no actúan sobre él.
  • TikTok Events API: ningún evento estándar de reembolso o devolución. Según la propia documentación de TikTok, el manejo de reembolsos es "not applicable" para el conjunto de eventos de optimización de campañas. Un evento personalizado sería, en el mejor de los casos, un contador pasivo.
  • Snapchat CAPI: ningún evento de reembolso nativo. Peor aún, sin un mapeo estándar cae en la misma casilla CUSTOM_EVENT_1 que Beaconry reserva para los leads de formulario. Disparar un reembolso ahí chocaría con tus eventos de lead y haría imposible separar ambos en el Snap Events Manager.
  • Pinterest Conversions API: ningún evento de reembolso nativo. Podrías enviar un refund personalizado y Pinterest incluso lo mostraría en el manager, pero no aporta valor de Smart Bidding y no hace ningún descuento de ingresos. Es un contador con una etiqueta amistosa.
  • Reddit Conversions API: la misma historia que Pinterest. Un reembolso personalizado aparecería pero no optimizaría nada ni descontaría nada.
  • Microsoft Ads: la OfflineConversions API no tiene de entrada ningún concepto de conversión de reembolso al que mapear, así que no hay nada que enviar.

Fíjate en el patrón. En Meta y TikTok un reembolso personalizado se traga en silencio. En Snapchat es activamente dañino (colisión de casilla). En Pinterest y Reddit es visible pero inútil. Ninguno de ellos hace lo que hace GA4. Así que la respuesta honesta en todas partes excepto en GA4 es: omítelo.

La trampa: "pero Pinterest y Reddit lo mostrarían"

Esta es la decisión que parece razonable y no lo es. Pinterest y Reddit SÍ renderizan un evento refund personalizado en sus paneles, así que un instinto obvio es "bueno, envíalo a los canales que lo muestren, omite los que lo tragan". Esa regla es arbitraria, y las reglas arbitrarias se pudren.

Es arbitraria porque el factor decisivo es "¿es este evento visible en la interfaz del proveedor?", no "¿significa algo este evento?". La visibilidad es un accidente del panel de cada plataforma, no una señal de valor. Un evento de reembolso en Pinterest no descuenta ingresos, no ajusta la puja y no corrige la atribución. Solo incrementa un número que nadie aguas abajo está conectado para interpretar. Enviarlo a Pinterest-porque-visible pero no a Meta-porque-invisible dividiría una decisión lógica en dos reglas contradictorias, y la siguiente persona en tocar el dispatcher tendría que averiguar al revés por qué.

La regla con principios es más limpia y se generaliza: un evento de conversión se despacha a un canal solo si el canal tiene un concepto real de él. Para los reembolsos eso se resuelve solo en GA4, y sigue siendo cierto para cualquier canal futuro que Beaconry añada sin que nadie tenga que volver a litigarlo.

Cómo se impone la omisión en el código

El dispatcher tiene una lista de omisión por canal, BCNR_Forwarder::SKIP_BY_CHANNEL. El nombre refund aparece en la lista de omisión para meta, tiktok, snapchat, pinterest y reddit. Microsoft Ads nunca tuvo de entrada un mapeo de reembolso. GA4 no tiene entrada de omisión para refund, así que recibe el evento con normalidad. El fragmento relevante del bucle de despacho se ve así:

// In BCNR_Forwarder::dispatch(), after the pre-dispatch filter:

if ( self::has_ga4() ) {
    self::dispatch_ga4( $event );          // refund lands here, nets vs purchase
    self::after_dispatch( 'ga4', $event );
}

if ( self::has_meta() && self::should_dispatch_to_channel( 'meta', $event ) ) {
    // should_dispatch_to_channel('meta', ...) returns false for 'refund'
    // because 'refund' is in SKIP_BY_CHANNEL['meta'] - so this is skipped
    self::dispatch_meta( $event );
    self::after_dispatch( 'meta', $event );
}
// ... same skip outcome for tiktok / snapchat / pinterest / reddit

El check should_dispatch_to_channel() de cada canal lee su propia entrada SKIP_BY_CHANNEL y devuelve false cuando el nombre del evento está en la lista. Así que un reembolso llega a dispatch_ga4() y se detiene ahí. La omisión es datos, no lógica de ramificación dispersa por cinco métodos de despacho, y por eso un sexto canal publicitario hereda el comportamiento correcto en el momento en que añades 'refund' a su conjunto de omisión.

Vale la pena señalar una sutileza: un reembolso NO se clasifica como evento "analytics-only" como lo son form_start y form_abandon. Esos pasan por una compuerta central separada (ANALYTICS_ONLY_EVENTS) que se detiene en seco antes de cualquier canal publicitario. Un reembolso es un evento de comercio genuino, simplemente da la casualidad de que solo un canal lo soporta. Los dos mecanismos parecen similares desde fuera (ambos terminan solo en GA4) pero existen por razones distintas: analytics-only es "señal de comportamiento, nunca una conversión", refund es "conversión real, solo un canal la implementa". Confundirlos en el código sería un error en el momento en que alguna plataforma publicitaria futura lance un evento de reembolso real.

El payload del reembolso en sí

Cuando WooCommerce dispara su hook de pedido reembolsado, el handle_refund() de Beaconry construye el evento. Tres detalles son determinantes:

El valor es negativo. El valor del reembolso se envía como -1 * delta, un número negativo. El manejo nativo de GA4 hace el descuento por su cuenta, pero el signo negativo también significa que si un cliente SÍ construye un informe personalizado que suma valores de eventos a lo largo de la pipeline, el reembolso resta en lugar de sumar. Es el signo correcto para el único canal que lo entiende y aritmética inofensiva para cualquier consumidor aguas abajo:

BCNR_Forwarder::dispatch( [
    'name'      => 'refund',
    'event_id'  => 'bcnr_refund_' . $order_id . '_' . (int) ( $total_refunded * 100 ),
    'timestamp' => time(),
    'page_url'  => self::current_url(),
    'params'    => [
        'transaction_id' => (string) $order_id,
        'currency'       => $order->get_currency(),
        'value'          => -1 * $delta,   // negative: nets against the purchase
    ],
    'user_data' => self::user_data_from_order( $order ),
] );

Los reembolsos parciales se manejan por delta. El handler lee get_total_refunded() (el importe reembolsado acumulado del pedido) y lo compara con el último total que Beaconry ya reportó, almacenado en el meta del pedido. Envía solo la diferencia, el delta. Reembolsa hoy 30 de un pedido de 100 y el valor del evento es -30. Reembolsa otros 20 la próxima semana y el siguiente valor del evento es -20, no -50. GA4 descuenta cada corrección por turno contra el mismo transaction_id, de modo que la cifra de ingresos en curso sigue la realidad en cada paso en lugar de restar dos veces.

El event_id es idempotente. El event_id hornea el total reembolsado en céntimos dentro de la cadena: bcnr_refund_<order_id>_<cents>. WooCommerce puede disparar el mismo hook de reembolso más de una vez para una sola acción de reembolso, y la comparación del total almacenado ya cortocircuita un nuevo disparo (si total_refunded <= prev_total, retorno anticipado). El event_id estampado en céntimos es la segunda línea de defensa: el mismo importe de reembolso produce el mismo id, así que incluso un duplicado que se haya colado por la guarda se deduplica en lugar de contarse dos veces. EDD y SureCart usan la misma forma a través de sus propios hooks de reembolso (surecart/models/refund/created para SureCart, la ruta de reembolso de EDD para EDD), de modo que el enrutamiento solo a GA4 y el comportamiento de descuento son idénticos en las tres plataformas de comercio.

Qué se adelanta esto: "mi reembolso desapareció de Meta"

Aquí está el ticket de soporte que este diseño evita. Un cliente emite un reembolso en WooCommerce, abre GA4 y ve los ingresos bajar correctamente. Luego abre el Meta Events Manager, busca un reembolso coincidente y no encuentra nada. El instinto es "el plugin se está comiendo mis reembolsos". No lo hace. Meta no tiene dónde poner un reembolso. No hay ningún evento de reembolso de Meta en el que pueda aterrizar, así que la ausencia es comportamiento correcto, no un bug.

Lo honesto que se puede hacer, y lo que hace Beaconry, es no enviar de entrada un evento fantasma a Meta. Un evento Refund personalizado en CAPI "aparecería" solo en el sentido de inflar un contador de eventos personalizados sobre el que nadie actúa, mientras hace cero descuento y cero optimización. Eso de hecho empeoraría la confusión, porque ahora SÍ HAY un número de reembolso de Meta, solo que no hace nada y no se concilia contra tu recuento de compras. Omitirlo por completo es a la vez el comportamiento más honesto y el que mantiene limpia la vista del Events Manager.

Así que la respuesta al ticket es corta: los reembolsos viven en GA4, donde la plataforma los descuenta de la compra por ti. Los canales publicitarios siguen optimizando sobre las conversiones que realmente soportan, con recuentos que no están contaminados por eventos de reembolso inertes. Si quieres la imagen completa de ingresos corregida por reembolsos, está en la monetización de GA4, ya descontada, sin resta manual.

Cómo corrigen las plataformas publicitarias los reembolsos sin un evento

Es justo preguntar: si Meta y TikTok nunca ven el reembolso, ¿sus números de ROAS quedan permanentemente mal? No, y por eso solo-GA4 es comportamiento conforme a la documentación y no una laguna. Las plataformas publicitarias manejan la corrección de valor a través de sus propios mecanismos de decaimiento de atribución y ajuste de conversiones, no a través de un evento de reembolso en tiempo real. No hay ningún Purchase de valor negativo que se supone debas enviarles; su modelo es envejecer y ajustar las conversiones atribuidas de su lado. Intentar atornillar un evento de reembolso a un sistema que no se construyó para consumir uno no mejora su precisión, solo añade ruido. La división del trabajo es limpia: GA4 posee la verdad de ingresos descontada y corregida por reembolsos; los canales publicitarios poseen la optimización sobre las conversiones positivas que soportan y corrigen el valor a su manera.

Conclusión

Los reembolsos van solo a GA4 porque GA4 es el único canal con un evento de reembolso nativo que descuenta los ingresos de la compra. Cada plataforma publicitaria o bien no tiene evento de reembolso (Meta, TikTok, Microsoft), o tiene uno que solo contaminaría o colisionaría (la colisión de casilla de lead de Snapchat), o tiene un contador cosmético que no optimiza nada (Pinterest, Reddit). El principio, "envía una conversión a un canal solo si ese canal tiene un concepto real de él", es lo que mantiene honesto el enrutamiento y lo que hace que un canal futuro encaje sin tener que repensarlo. La recompensa práctica es doble: los ingresos de GA4 se mantienen veraces sin resta manual, y tus recuentos de conversiones por canal publicitario se mantienen limpios, sin eventos de reembolso fantasma inflando los números de los que depende tu puja. La pregunta "¿a dónde fue mi reembolso de Meta?" se responde sola en cuanto sabes que Meta nunca tuvo un lugar donde ponerlo.