Dispara conversiones en cualquier botón con una sola clase CSS
La mayoría de las conversiones en un sitio no son envíos de formulario ni pedidos de WooCommerce. Son clics: un botón Comprar que abre un checkout externo, un CTA de Contacto que hace scroll hasta un número de teléfono, un enlace de la página de precios que pasa el relevo a Polar o Stripe. Beaconry cubre esos casos con cinco slots CSS genéricos. Añade una clase al elemento y el clic dispara una conversión server-side por la misma pipeline que todo lo demás. Nada de JavaScript que escribir, ningún snippet de proveedor que pegar.
La brecha entre los hooks de formulario y los de commerce
Beaconry tiene cobertura server-side profunda allí donde puede engancharse directamente a la plataforma. Los plugins de formulario disparan un lead cuando un envío aterriza en PHP. WooCommerce, EDD y SureCart disparan un funnel de diez eventos desde hooks reales de pedido. Esos caminos son precisos porque los datos están justo ahí, en el servidor: los campos del formulario, el total del pedido, las líneas de producto.
Pero mucha intención de alto valor nunca llega a un hook de servidor en tu sitio. Un botón que abre buy.polar.sh en una pestaña nueva navega fuera antes de que se ejecute ningún PHP. Un enlace "Reservar una llamada" que apunta a Calendly abandona tu dominio por completo. Un ancla "Descargar la prueba" dispara una respuesta de archivo, no un envío de formulario. No hay envío, no hay pedido, no hay hook al que escuchar. La única señal es el clic en sí, en el navegador, en el momento en que ocurre.
El click-tracking llena exactamente esa brecha. Es una captura del lado del navegador para elementos que no tienen equivalente server-side, cableada para que el evento resultante siga viajando por el mismo path REST same-origin y el mismo fan-out server-side que un lead de formulario real. Etiquetas el elemento y Beaconry hace el resto.
Los cinco slots, y qué dispara cada uno realmente
Hay cinco clases CSS. Cada una mapea a un nombre de evento canónico de GA4, y el forwarder mapea luego ese nombre de GA4 al vocabulario de eventos propio de cada canal. El sentido de usar eventos publicitarios estándar (en lugar de un evento genérico "click") es que Meta, TikTok, Pinterest y el resto conservan su señal de optimización: un begin_checkout le dice a Meta que optimice para intención de checkout, un evento custom genérico no le dice nada.
Aquí está el mapeo verificado, directo de setupClickTracking() en el motor empaquetado y de EVENT_MAP_GA4_TO_META en el forwarder. (Una cosa a vigilar: el slot de checkout dispara GA4 begin_checkout, no initiate_checkout. begin_checkout es la grafía canónica de GA4; el forwarder es lo que lo traduce al InitiateCheckout de Meta. Confundir los dos envía un evento que GA4 descarta en silencio.)
| Clase CSS | Evento GA4 | Evento Meta CAPI | Uso típico |
|---|---|---|---|
.beaconry-checkout | begin_checkout | InitiateCheckout | Relevo de Comprar / Suscribirse / Añadir al carrito a un checkout externo |
.beaconry-lead | generate_lead | Lead | Solicitud de presupuesto, "Hablar con ventas", descarga con gate |
.beaconry-signup | sign_up | CompleteRegistration | Inicio de prueba gratis, creación de cuenta, alta en lista de espera |
.beaconry-contact | contact | contact (evento custom) | CTA de teléfono / email / WhatsApp / "Reservar una llamada" |
.beaconry-cta | select_content | ViewContent | Botón genérico de alta intención que igual quieres medir |
Dos de estos se resuelven de una forma que vale la pena conocer. .beaconry-contact no tiene evento estándar de Meta, así que el forwarder pasa el nombre de GA4 sin cambios y Meta registra un evento custom llamado literalmente contact. .beaconry-cta mapea al ViewContent de Meta, que es un evento estándar real, así que lleva peso de optimización en lugar de caer en un cubo de evento custom. Ambos son deliberados: un evento custom sigue siendo rastreable, un evento estándar es preferible cuando encaja uno. El mismo nombre de GA4 se reparte a TikTok, LinkedIn, Pinterest, Snapchat, Reddit, X, Google Ads y Microsoft Ads a través de sus propios mapas, así que configuras el slot una vez y cada canal configurado recibe su equivalente nativo.
Cómo funciona la captura por dentro
Toda la función es un único listener de clic delegado en document, montado dentro del motor empaquetado nl-data.js. No hay binding por botón, así que sigue funcionando para elementos añadidos después de la carga de la página (una tabla de precios renderizada por un bloque, un modal inyectado más tarde). El listener sube desde el objetivo del clic con closest() para encontrar un ancestro etiquetado, lee la clase que coincidió, construye el payload y lo envía.
La entrega usa navigator.sendBeacon(). Ese detalle importa más de lo que parece. Un fetch() normal disparado en un clic que también navega el navegador fuera (un enlace Comprar externo) se cancela a mitad de vuelo cuando la página se descarga, y el evento se pierde. sendBeacon() está hecho justo para esto: el navegador garantiza que la petición se encola y se envía incluso mientras la página se desmonta. Así que un botón Comprar puede a la vez navegar al checkout externo y disparar su conversión de forma fiable.
A partir de ahí el evento es de lo más corriente. Hace POST a /wp-json/beaconry/v1/event en tu propio dominio (same-origin, así que los adblockers no pueden descartarlo sin romper WordPress), el endpoint REST valida el consentimiento y normaliza el nombre, y BCNR_Forwarder::dispatch() lo reparte del lado del servidor. No se ejecuta ningún código de navegador específico de canal. Esa es toda la razón por la que una clase CSS genérica puede alimentar diez plataformas publicitarias a la vez: el slot solo tiene que producir un nombre canónico de GA4, y la maquinaria server-side existente se ocupa de cada traducción de proveedor.
Una salvaguarda incorporada en el motor: cuando el click-tracking está activo, los auto-eventos para enlaces salientes y enlaces de contacto saltan cualquier elemento que ya lleve una clase .beaconry-*, así que un botón Comprar etiquetado no dispara además un auto-evento genérico click o contact. Obtienes una conversión limpia, no una señal duplicada. (Cuando el click-tracking está apagado, esas clases se tratan como puramente decorativas y los auto-eventos disparan con normalidad, así que dejar una clase suelta en una plantilla de tema nunca se traga una señal en silencio.)
Overrides por botón con data-atributos
La clase elige el tipo de evento. Los data-atributos rellenan los valores para ese botón concreto. Todo es opcional: una clase pelada dispara una conversión de valor cero con el propio texto del botón como etiqueta, lo cual está bien para un CTA de Contacto. Un botón Comprar suele querer un precio y una identidad de producto para que el valor aterrice en los informes y el match de catálogo funcione para los Dynamic Product Ads.
| Atributo | Va a | Notas |
|---|---|---|
data-bcnr-value | value del evento + items[0].price | Numérico. Recurre al default por slot fijado en la pestaña Tracking, luego 0. |
data-bcnr-currency | currency del evento | ISO de tres letras, pasado a mayúsculas automáticamente. Por defecto tu moneda configurada, luego EUR. |
data-bcnr-content-id | content_ids[] + items[0].item_id | Tu SKU o slug de tier. Aportarlo construye un array items[] de un solo ítem para que GA4 acepte el evento en los informes de ingresos. |
data-bcnr-content-name | content_name + items[0].item_name | Nombre de producto legible. |
data-bcnr-label | label del evento | Sobrescribe el texto del botón capturado automáticamente. Útil cuando el texto visible es un icono o es demasiado genérico. |
Un botón Comprar real que pasa el relevo a un checkout externo de Polar:
<a class="beaconry-checkout"
href="https://buy.polar.sh/polar_cl_WVaBy3MStSJXOSCilMYu4RhA5DBFcGicJbgHo1IkT3A"
data-bcnr-value="149"
data-bcnr-currency="USD"
data-bcnr-content-id="studio-tier"
data-bcnr-content-name="Beaconry Studio">
Buy Studio
</a>Al hacer clic dispara GA4 begin_checkout con valor 149 USD y un array items[] de un ítem, que el forwarder convierte en Meta InitiateCheckout, TikTok InitiateCheckout, Pinterest checkout y demás, cada uno con el content id adjunto para el match de catálogo. El visitante aterriza en el checkout de Polar; la conversión se encoló con sendBeacon() antes de que la navegación se completara.
Un CTA de Contacto que no necesita más que la clase:
<a class="beaconry-contact" href="tel:+1-555-0142">
Call us
</a>Esto dispara GA4 contact con valor 0 y la etiqueta "Call us", registrado en Meta como un evento custom contact y enrutado al equivalente tipo lead de cada uno de los demás canales. Sin valor, sin content id, porque una llamada telefónica no tiene ninguno. Si más adelante decides que los leads de teléfono valen un valor estimado fijo, añade data-bcnr-value="50" y nada más cambia.
Cuándo usar click-tracking, y cuándo no
El click-tracking es la herramienta correcta cuando la conversión no tiene huella server-side en tu sitio. Úsalo para relevos a checkouts externos (Polar, Stripe Payment Links, Gumroad), para enlaces de reserva y agenda fuera del sitio, para CTAs de tel / mailto / WhatsApp y para enlaces de afiliado o partner que igual quieres atribuir. En todos esos, el clic es el único momento en que puedes observar la intención.
Es la herramienta equivocada cuando ya existe un hook server-side preciso, y recurrir a él ahí te cuesta precisión de forma activa:
- Los envíos de formulario reales pertenecen a las integraciones de formulario, no al click-tracking. Los hooks de formulario disparan en el envío real (tras la validación, tras guardar el lead) y pueden adjuntar PII hasheada (email, teléfono) para el match-rate. Un clic en el botón de envío dispara demasiado pronto: no puede ver si la validación pasó, y no tiene datos de campos. Etiqueta el formulario en la pestaña Forms en su lugar.
- Las compras de WooCommerce, EDD y SureCart pertenecen al funnel de commerce. Esas disparan desde hooks de pedido con el total real, las líneas de producto reales y un event id estable por pedido, así que un refresco de la página de gracias nunca cuenta doble. Un clic en "Realizar pedido" no tiene nada de eso y dispararía mal, hubiese pasado o no el pago de verdad.
- Un checkout multi-paso dentro del sitio es trabajo del funnel de commerce, medido como
begin_checkoutsin unpurchaseposterior. No lo tapes con un clic.beaconry-checkouten el botón "Continuar".
La regla práctica: si la conversión produce un hook de servidor, usa la integración que escucha en él, porque ve más (totales, ítems, PII) y dispara en el momento correcto. Si la conversión es una navegación o una acción solo de navegador sin hook, eso es precisamente para lo que sirve el click-tracking.
Activarlo
El click-tracking está apagado por defecto. Actívalo en Admin de WordPress, Beaconry, Tracking, Click-Tracking, donde también puedes fijar los valores por defecto por slot que un botón usa cuando no tiene su propio data-bcnr-value. A partir de ahí, cualquier elemento del sitio que lleve una de las cinco clases está en vivo.
Para sitios de staging que comparten una base de datos de producción hay un kill switch duro: define( 'BCNR_CLICK_TRACKING_ENABLED', false ); en wp-config.php anula el toggle de la base de datos, así que una copia de staging nunca dispara conversiones de clic aunque haya heredado el ajuste "on" de la base de datos clonada. (La misma constante puesta a true fuerza la activación, pero el toggle de la base de datos es el camino normal.)
Si además corres Modo Híbrido para un canal (el pixel del navegador junto al dispatch server-side), el click-tracking refleja automáticamente el evento a ese pixel con el mismo event id, de modo que el proveedor deduplica las copias de navegador y servidor en una sola. Es el mismo mecanismo de dedup que usan los caminos de commerce y formulario, tratado en el artículo de modo híbrido enlazado abajo.
Para llevarte
El click-tracking es la vía de escape para conversiones que nunca tocan un hook de servidor. Cinco clases CSS (checkout, lead, signup, contact, cta) mapean cada una a un evento publicitario estándar, así que una sola clase en un botón Comprar o un CTA de Contacto se reparte a cada canal configurado en el vocabulario propio de ese canal. Los data-atributos añaden valor e identidad de producto por botón. sendBeacon() hace que sobreviva a la navegación fuera. Y el path REST same-origin más el forwarder server-side compartido hacen que todo el asunto sea resistente a adblockers y agnóstico de proveedor sin una línea de código de integración. Recurre a él cuando no haya hook al que escuchar, y deja los caminos precisos (formularios, commerce) a las integraciones que son sus dueñas.