Nodos de Canvas
Los flujos de Canvas se crean con distintos tipos de nodos que definen cómo avanzan las personas por la automatización. Esta guía explica todos los nodos disponibles y su comportamiento.
Nodos de desencadenante
Los nodos de desencadenante definen cómo entran las personas en un Canvas.
Desencadenantes disponibles
| Tipo de desencadenante | Descripción |
|---|---|
| Evento | La persona entra al realizar un evento específico. |
| Cambio de entidad | La persona entra cuando cambia un registro de entidad relacionado. |
| API | La persona entra mediante una llamada a la API. |
| Programación | Las personas entran según una programación recurrente. |
| Mensaje de WhatsApp | La persona entra cuando envía un mensaje de WhatsApp. |
| SMS entrante | Un contacto conocido entra cuando escribe por SMS; filtra por cuenta de SMS, tipo de mensaje y condiciones de Texto / Tipo de mensaje. |
La entrada en segmento no es un desencadenante. Para entradas causadas por algo que hizo la persona, usa un desencadenante de evento con un filtro; para entradas causadas por el paso del tiempo, usa un recorrido recurrente sobre el segmento.
Comprobación de repetición - lo mismo dos veces
Un desencadenante de evento puede exigir que el evento que llega sea una repetición: al menos N ocurrencias de este evento por la misma persona, en los últimos D días, con los mismos valores de las propiedades que elijas - contando el evento que acaba de llegar. La persona entra exactamente en la N-ésima ocurrencia coincidente; las ocurrencias con otros valores nunca la inscriben.
El ejemplo para el que se construyó: alguien que miró el mismo hotel para las mismas fechas dos veces.
| Ajuste | Valor |
|---|---|
| Evento | hotel_viewed |
| Repetición | al menos 2 veces en los últimos 2 días |
| con el mismo | hotel, check_in |
Una segunda mirada a Casa Azul para el 3-5 de octubre inicia el recorrido. Una primera mirada a Casa Azul, o una mirada a cualquier otro hotel, no - el recuento está fijado al hotel y al check_in del propio evento que llega.
Pon esta comprobación en el desencadenante, no en un paso de Condición. Un recorrido que entrase en cada hotel_viewed y preguntase "¿dos veces?" dentro inscribiría a la persona en la primera mirada; con la reentrada bloqueada, la segunda mirada nunca podría iniciarlo. El desencadenante hace la pregunta antes de que se gaste la entrada.
Cómo se evalúa: cuando llega el evento, el desencadenante cuenta los eventos hotel_viewed almacenados de esa persona en la ventana cuyos hotel y check_in son iguales a los del evento que llega, excluye de ese recuento el id del propio evento que llega y suma uno por el evento en sí - así la respuesta es la misma haya llegado o no el evento al almacén de analítica. Por debajo, la comprobación es el filtro de evento sameProperties descrito en nodos de bifurcación, con cada propiedad comparada con el valor del evento desencadenante.
Nodos de mensaje
Los nodos de mensaje envían comunicaciones a las personas a través de distintos canales.
Canales compatibles
- Email: envía emails personalizados.
- SMS: envía mensajes de texto (en una cuenta de Delivyr, elige una plantilla aprobada y rellena sus variables - consulta Cuentas de Delivyr).
- Notificaciones Push: envía notificaciones Push móviles.
- WhatsApp: envía plantillas o respuestas de WhatsApp.
- Webhook: llama a una API externa con un cuerpo creado mediante plantilla Liquid.
In-app es un canal que eliges dentro del nodo de Mensaje, junto a email, SMS, push, WhatsApp y Viber. Se comporta distinto: el mensaje queda en cola y se muestra cuando la persona vuelve a abrir tu aplicación, en lugar de enviársele, así que no tiene acuse propio de "enviado" ni "entregado" - consulta Nodos de mensaje in-app.
Eliges el canal desde el propio nodo de mensaje. Webhook aparece en el mismo selector de canales que Email y SMS, con su propio generador de solicitud - método, encabezados, cuerpo, autenticación, reintentos y una espera opcional de asignación de respuesta. Usa Enviar prueba para realizar una llamada de ejemplo; después haz clic en cualquier campo de la respuesta para asignarlo a una variable de recorrido, o pega una respuesta de ejemplo para crear la asignación sin una llamada en vivo. Cuando está activa la asignación de respuesta, también puedes habilitar una salida en caso de error: un segundo puerto que sigue el recorrido si la llamada falla o se agota el tiempo. Déjalo sin conectar para continuar por la salida normal - fallo abierto.
Enviar prueba genera la solicitud para el contacto de prueba que elijas. Un contacto real (Random user o Select existing user) se carga desde tu espacio de trabajo y se procesa exactamente como en un envío real - {{ user.id }} es el ID interno del contacto y todos los demás campos y atributos salen de su perfil. Un Custom user es inventado, así que sus campos vacíos usan valores de ejemplo. Tras la prueba, alterna el resultado entre Respuesta recibida y Solicitud enviada para ver el método, la URL, los encabezados y el cuerpo exactos que se enviaron; las credenciales (encabezados Authorization, de clave API y de firma) aparecen ocultas.
El canal Webhook llama a un servicio externo en vez de a la bandeja de entrada de una persona, por lo que el consentimiento de suscripción no se gestiona para webhooks: no hay opt-in de webhook y la preferencia de suscripción de la audiencia no los restringe. Todo lo demás se aplica de forma predeterminada:
- Las horas de silencio y los límites de frecuencia restringen los webhooks de forma predeterminada, igual que los mensajes. Un webhook que representa un contacto con cliente - por ejemplo, activa un mensaje en otro sistema - no debe ejecutarse en la ventana de silencio de una persona. Si tu webhook es una llamada puramente entre sistemas - sincronizar un CRM o iniciar una tarea de backend, marca Llamada de sistema: omitir horas de silencio y límites de frecuencia en el nodo para excluir ambos.
- Las listas de supresión siempre se aplican: un contacto suprimido nunca activa el webhook. La casilla Llamada de sistema no cambia esto.
- Facturación: los contactos sobre los que se activa un webhook cuentan como perfiles activos facturables, igual que los destinatarios de mensajes. Consulta Cómo se calcula el uso.
Comportamiento de avance tras un mensaje
Las personas avanzan al siguiente paso inmediatamente después de que el mensaje se pone en cola para enviarse. El Canvas no espera a que el mensaje llegue a la bandeja de entrada.
Este es el enfoque habitual de la industria. Permite:
- Escalabilidad: procesa millones de personas sin bloquearse.
- Rendimiento: la ejecución de Canvas no se ralentiza por los tiempos de entrega.
- Fiabilidad: trabajadores dedicados se ocupan de la entrega con reintentos.
Qué significa «mensaje enviado»:
- El mensaje se personaliza con datos de la persona.
- Se añade a la cola de envío.
- La persona avanza al siguiente paso de Canvas.
- Un trabajador dedicado procesa la cola y entrega los mensajes.
Garantías de entrega de mensajes:
- Los mensajes se reintentan hasta 3 veces con espera exponencial.
- Los mensajes fallidos se registran para investigarlos.
- El seguimiento de entrega - aperturas, clics y rebotes - se gestiona por separado.
Consentimiento de suscripción
Los nodos de mensaje aplican el consentimiento de suscripción en el momento del envío, por canal. Se aplican las mismas reglas que en campañas, así que un recorrido y una campaña tratan del mismo modo al mismo contacto. La preferencia de suscripción de la audiencia de Canvas determina lo estricta que es la regla:
- Suscrito - predeterminada: envía solo a contactos que han dado consentimiento en ese canal -
subscribeduopted_in. Se omiten los contactos dados de baja explícitamente y los que no tienen ningún registro de suscripción. - Confirmado: solo suscriptores confirmados con doble opt-in.
- Todos: envía independientemente del estado de suscripción; es la anulación explícita de «enviar incluso a no suscritos» o transaccional.
Aspectos específicos por canal:
- Email también omite direcciones con rebote duro.
- Push es más permisivo: como el permiso Push se concede en el dispositivo y no mediante un registro de opt-in, se envía salvo que el contacto se haya dado de baja explícitamente. Un contacto sin registro sigue recibiendo Push.
Un envío omitido no retira al contacto del recorrido: solo se omite el mensaje y el contacto avanza al siguiente paso - webhook, Actualizar usuario, ramificación, etc. siguen ejecutándose para todos. El consentimiento se vuelve a comprobar en cada envío, por lo que un cambio de suscripción realizado antes en el recorrido - por ejemplo, en un paso Actualizar usuario - o desde el centro de preferencias se respeta en el siguiente mensaje. Nada queda congelado en la entrada.
También se aplican las listas de supresión en todos los canales. Se omite un contacto que pertenezca al segmento de una lista de supresión activa - y permanece en el recorrido, salvo que las etiquetas de excepción de esa lista excluyan este Canvas. Los recorridos usan la pertenencia materializada del contacto al segmento, que se actualiza según una programación; por eso la supresión se refleja con una breve demora. Las campañas la evalúan en vivo al enviar.
Grupos de suscripción por número (SMS/WhatsApp)
Para SMS y WhatsApp, los recorridos aplican la misma regla de grupo de suscripción por número o WABA que las campañas. Una lista de suscripción vinculada a un remitente específico se convierte en el grupo de ese remitente: los grupos de SMS son por número de envío y los de WhatsApp por WABA. Un contacto que se dio de baja del grupo del número emisor - o WABA - se omite en ese mensaje, pero, como ocurre con todas las omisiones, avanza al paso siguiente: solo se descarta el mensaje.
El grupo cuya baja se comprueba depende del remitente que elijas en el nodo de mensaje: el número de SMS para un mensaje SMS y el WABA para WhatsApp. Si no eliges ninguno, se usa el remitente predeterminado del espacio de trabajo - para SMS - o el WABA predeterminado - para WhatsApp - y se comprueba el grupo de ese valor predeterminado.
Horas de silencio
Los nodos de mensaje respetan la configuración de horas de silencio del espacio de trabajo, evaluada en la zona horaria del contacto al enviar. Cuando un contacto llega a un nodo de mensaje durante una ventana de silencio - o un festivo configurado, el comportamiento sigue la regla de cada canal de la organización:
- Omitir: el mensaje no se envía y el contacto avanza al siguiente paso.
- Retrasar: el nodo de mensaje se aplaza hasta que termine la ventana, y después se ejecuta y envía.
Esto replica el comportamiento de campañas - por ejemplo, email puede retrasarse por la noche mientras que SMS se omite, de modo que las horas de silencio se aplican de manera coherente tanto si el contacto llega mediante una campaña como por un recorrido.
Enviar un mensaje de prueba
Cada nodo de mensaje incluye un botón Enviar mensaje de prueba en su modal de configuración. Úsalo para verificar la personalización y la conectividad con el proveedor antes de publicar.
Cobertura por canal:
- Email: abre un modal de envío de prueba con el mismo selector de usuario - aleatorio / existente / personalizado - y una anulación del email destinatario.
- SMS: abre un modal de envío de prueba con el mismo selector y una anulación de número de teléfono.
- WhatsApp: igual que SMS, pero la plantilla elegida debe estar en estado
approved.
El selector resuelve las variables Liquid con los atributos de la persona elegida y luego envía directamente mediante el proveedor del espacio de trabajo, sin pasar por la cola de Canvas, la segmentación de audiencia ni las reglas de horas de silencio. La supresión sigue aplicándose: se rechaza un envío de prueba a una dirección o número suprimidos, igual que un envío real. Los envíos de prueba no cuentan en las estadísticas de ejecución, no activan webhooks y siempre son gratuitos.
Los envíos de prueba se renderizan mediante la misma canalización que los envíos reales: los tokens de personalización, atributos personalizados y bloques de contenido se resuelven de forma idéntica. Lo que recibas en una prueba será exactamente lo que reciba la audiencia.
Plantillas en un paso de mensaje
- "From template" de email y "From template" de in-app vinculan el paso a una plantilla guardada. Cambiar plantilla elige otra y el paso la sigue desde entonces: no se copia nada al paso, así que no se pierde nada.
- Los pasos de Push y Webhook copian una plantilla con Start from template. Elegir otra plantilla sobre contenido que editaste pide confirmación antes de reemplazarlo; el contenido que sigue exactamente como lo dejó la última plantilla se reemplaza sin preguntar.
- Guardar como plantilla (email con Drag & drop o Custom HTML, push, in-app con Drag & drop o HTML) guarda el contenido actual del paso como una plantilla nueva, con el nombre predeterminado "nombre del recorrido - canal" y etiquetas opcionales. El paso conserva su propio contenido y no queda vinculado a la plantilla nueva. Requiere permiso para editar plantillas.
Retenido por Joryio
En Opciones avanzadas de entrega cada paso de mensaje elige qué ocurre cuando la persona acaba de recibir otro mensaje: Enviar siempre (el valor por defecto, para pasos transaccionales), Puede esperar y luego enviar, o Puede esperar, omitir si caduca, con el tiempo máximo de retención. En un paso que puede esperar, Joryio retiene un rato un mensaje de poco valor cuando la persona recibió otro en el último día, luego lo envía, o lo descarta cuando se agota el margen de espera en un paso de omisión. Se ejecuta después de las reglas de consentimiento, horas de silencio, suscripción y frecuencia, nunca en su lugar. Cuando dos mensajes de una persona están pendientes en la misma ventana, el de mayor valor va primero y el otro espera, nombrando el mensaje que se adelantó. Un mensaje retenido se muestra como Retenido por Joryio - motivo en la cronología del destinatario y como retenido en la analítica del recorrido, para que una tasa de conversión nunca se diluya en silencio. Un grupo de comparación envía siempre; su resultado está en Ajustes, Modelos ML bajo Mensajes retenidos.
Nodos de mensaje in-app
Los mensajes in-app funcionan de forma distinta a cualquier otro canal, por eso tienen su propio nodo. El email, el SMS, las push y WhatsApp se envían a la persona. Un mensaje in-app se muestra cuando la persona vuelve a abrir tu aplicación, así que este nodo no "envía" nada: pone el mensaje en cola para ese usuario y tu aplicación lo muestra en la siguiente sesión apta.
Añádelo desde la ficha Mensaje in-app de la paleta del constructor.
Qué se configura
- Mensaje (obligatorio) - de dónde viene el contenido. El nodo se abre con la misma elección que el nodo de email:
- Escríbelo aquí - redactado en el nodo y usado solo por este paso. Elige un editor: Drag & drop (bloques visuales e imágenes), Clásico - estilo de app (titular, texto, imagen y botones que tu app dibuja con sus propias fuentes y colores, así se muestra incluso en apps que bloquean HTML) o HTML.
- Usar una campaña - reutiliza una campaña in-app que ya construiste, incluidas sus variantes.
- Desde plantilla - enlaza una plantilla in-app guardada de Brand Studio. El paso muestra la plantilla tal como está cuando el mensaje entra en cola, así que editar la plantilla actualiza todos los recorridos que la usan.
- Diseño - modal, banner, deslizante o pantalla completa (una plantilla creada para un diseño lo trae consigo).
- Prioridad - Urgente / Alta / Normal / Baja. Cuando varios mensajes in-app son aptos en el mismo momento, se muestra primero el de mayor prioridad; los empates se resuelven por antigüedad, así un mensaje en cola nunca queda sepultado por otros más nuevos. Los mensajes de journey y las campañas in-app compiten en la misma clasificación.
- Con qué frecuencia puede mostrarse - Mostrar una vez (predeterminado), Mostrar hasta N veces (con un intervalo mínimo opcional entre apariciones) o Mostrar hasta que se pulse o se descarte.
- Dejar de intentarlo después de N días - si la persona no abre la aplicación en ese plazo, el mensaje caduca sin verse. El valor predeterminado es 7 días.
- Esperar hasta que se muestre (opcional) - ver más abajo.
¿Cuándo continúa el journey?
De forma predeterminada, el journey continúa de inmediato tras poner el mensaje en cola: el mismo comportamiento de "enviar y seguir" que en los demás canales, porque no se puede saber cuándo volverá a abrir la aplicación.
Marca Esperar hasta que se muestre para retener a la persona en este paso hasta que vea realmente el mensaje. Si no abre la aplicación dentro de la ventana de espera (24 horas de forma predeterminada), el journey continúa igualmente: nunca se queda bloqueado por un mensaje que no se vio.
Usa Esperar hasta que se muestre cuando el paso siguiente solo tenga sentido después de que la persona haya visto el mensaje; por ejemplo, "muestra el consejo de bienvenida, espera y luego envía un email a quienes lo vieron". Déjalo desactivado para avisos de tipo enviar y olvidar.
Límite de frecuencia
Los mensajes in-app de un journey cuentan para el mismo límite de frecuencia in-app que las campañas: un único límite diario compartido por persona, más tu techo entre canales. Un mensaje bloqueado por el límite se omite y el journey sigue adelante. Los contactos suprimidos nunca reciben mensajes in-app.
Informes
El nodo informa como cualquier otro paso de mensaje, con terminología in-app:
- Mostrado cuenta como la entrega del nodo (en in-app, mostrarse es la entrega)
- Pulsado cuenta los toques en el mensaje
- No hay paso Abierto en in-app: el embudo es mostrado → pulsado
Las conversiones atribuidas al journey usan la misma ventana y el mismo modelo de atribución que los demás canales.
Nodos de espera
Los nodos de espera pausan el avance de la persona. Cuatro tipos de espera cubren los patrones habituales:
Tipos de espera
| Tipo | Cuándo usarlo |
|---|---|
| Duración | Espera un tiempo fijo después de que la persona llegue a este paso; por ejemplo, «esperar 7 días». |
| Fecha de calendario | Espera hasta una fecha y hora específicas; por ejemplo, «liberar el 2026-05-17 a las 10:00». Las personas que entren después salen del recorrido. |
| Día de la semana | Espera hasta la siguiente ocurrencia de un día de la semana y hora elegidos; por ejemplo, «el próximo lunes a las 12:00». |
| La mejor hora de la persona | Espera hasta la siguiente ocurrencia de la hora a la que esta persona suele abrir mensajes o suele pedir, opcionalmente unos minutos antes; por ejemplo, «su hora habitual de pedido, 30 min antes». Consulta La mejor hora de la persona. |
Duración
| Configuración | Descripción |
|---|---|
| Esperar | Número y unidad: minutos, horas, días o semanas. |
| Después esperar hasta una hora específica | Opcional. Una vez terminada la duración, sigue esperando hasta la hora elegida en la zona horaria seleccionada. |
| Zona horaria | Organización / hora local del usuario / UTC; se usa en la opción de hora del día. |
Fecha de calendario
| Configuración | Descripción |
|---|---|
| Fecha | Fecha ISO objetivo. Se elige desde el calendario en línea: haz clic en un día y usa las flechas para navegar por meses. |
| Hora | Selectores de hora y minuto. |
| Zona horaria | Organización / hora local del usuario / UTC. |
Día de la semana
| Configuración | Descripción |
|---|---|
| Día y hora | Día de la semana, hora y minuto. La fila de vista previa de 7 celdas de la parte superior del modal también es interactiva. |
| Zona horaria | Organización / hora local del usuario / UTC. |
| Si una persona llega después del límite | Wait - predeterminado - la pasa a la ocurrencia de la semana siguiente. Advance se activa de inmediato para que no pierda una semana. |
La mejor hora de la persona
Un win-back que llega a las 19:30 a alguien que suele pedir a las 20:00: este modo espera la siguiente ocurrencia de la hora punta propia de la persona, en su zona horaria, menos una antelación.
| Configuración | Descripción |
|---|---|
| Según | Cuando suele abrir mensajes (sus aperturas, lecturas, toques y clics, contados por canal, ver más abajo) o Cuando suele pedir (sus pedidos realizados). |
| Para el canal | Solo para aperturas. Canal del siguiente mensaje (automático) (predeterminado) lee el lienzo: el canal del siguiente paso de mensaje tras esta espera, cuando todos los caminos desde la espera llevan a un solo canal. O elige uno: Email, SMS, WhatsApp, Push, In-app, Viber. |
| Antelación | Minutos antes de la hora en que se libera a la persona (0-1440). 30 sobre una hora punta de 20:00 libera a las 19:30. |
| Zona horaria | Hora local del usuario (predeterminada: el atributo timezone de la persona, con la hora de la organización como respaldo) u Hora de la organización. |
Qué cuenta como «apertura» depende del canal: en email, aperturas y clics; en push, toques; in-app, clics (una visualización no es una apertura); en WhatsApp, confirmaciones de lectura y después clics; en Viber, «visto» y después clics. SMS no tiene apertura: solo cuentan los clics en enlaces, así que una persona necesita tres clics en enlaces de SMS antes de tener una hora de SMS propia.
Cómo se elige la hora para un canal, en orden:
- Su canal: la persona tiene al menos 3 eventos en este canal: la hora con más de ellos.
- Mismo dispositivo: si no, al menos 3 eventos en toda la familia de dispositivo del canal: la familia del móvil (push, WhatsApp, Viber, SMS, in-app) o la del escritorio (email). Dos clics de SMS y cinco toques de push dan a una espera de SMS la hora del push.
- Cualquier canal: si no, al menos 3 eventos en cualquier canal.
- Espacio de trabajo: si no, la hora punta de todo el espacio de trabajo para este canal y su familia de dispositivo (se actualiza cada 10 minutos).
- Predeterminada: un espacio de trabajo sin ningún historial: 10:00 para email, 19:00 para la familia del móvil.
Cuando suele pedir, y una espera de aperturas cuyo canal no puede deducirse del lienzo (sin paso de mensaje posterior, o ramas hacia canales distintos), usan la cadena corta: personal (3 eventos) - espacio de trabajo - predeterminada (10:00 para aperturas, 19:00 para pedidos).
Las personas sin historial suficiente usan la hora habitual del espacio de trabajo; nadie espera al azar. Si el instante objetivo ya pasó hoy, o faltan menos de cinco minutos, la persona espera al de mañana. El límite de 30 días se aplica como en toda espera.
La tarjeta Purchase Behavior del perfil de la persona muestra una tabla Mejor hora por canal: una fila por cada canal con historial en el espacio de trabajo, más Pedidos, con la hora y su origen («sus aperturas», «hábito del móvil», «cualquier canal», «patrón del espacio de trabajo», «predeterminada»), para ver qué haría un recorrido antes de publicarlo. Cada paso de espera registra el canal y el escalón que usó, de modo que el informe del recorrido pueda contar esperas personales frente a esperas del espacio de trabajo.
Personalizar espera
Un interruptor presente en todos los tipos. Al activarlo, la espera lee una variable por persona en lugar de un valor fijo:
| Fuente | Lee de |
|---|---|
| Variables de contexto | execution.context[varName]: el contexto entrante del recorrido - valor heredado predeterminado. |
| Atributo personalizado del usuario | user.attributes.<varName> y campos de usuario de nivel superior. |
| Propiedad de evento | Una propiedad del evento: el último evento que coincidió en una bifurcación de comportamiento, o si no el evento que inició el journey (waitDays o properties.waitDays). Si la propiedad falta o no es utilizable, la espera no espera - el paso lo registra como delayVariableMissing y se registra una advertencia. |
En Fecha de calendario o Día de la semana con una variable personalizada, también puedes configurar un desplazamiento - positivo o negativo, en horas, días o semanas; por ejemplo, «enviar 3 días antes de la fecha de renovación».
Una fecha personalizada sin zona horaria propia (2026-10-16T09:00:00, o solo una fecha como 2026-10-16, que significa medianoche) se lee en la Zona horaria alternativa del paso - Company, User local o UTC. Un valor que lleva su propio desfase (2026-10-16T09:00:00+03:00, o una Z al final) lo conserva.
Resolución de zona horaria
| Modo | Se resuelve como |
|---|---|
| Hora de la organización | La zona horaria del espacio de trabajo o, si no tiene, la de la organización en Ajustes; si tampoco, UTC. Es la misma zona que usan las campañas. |
| Hora local del usuario | user.attributes.timezone, establecida por el SDK. Si no existe, usa la hora de la organización. |
| UTC | UTC. |
Límites
- Todas las ramas de espera están limitadas a un máximo de 30 días. Una espera guarda los valores que muestra (7 días, la fecha, el día y la hora en pantalla). Una espera de Fecha del calendario sin fecha no se puede activar; cualquier otra espera incompleta se activa de inmediato en vez de bloquear el recorrido y registra una advertencia estructurada.
Ejemplo: espera 24 horas antes de enviar un email de seguimiento.
Nodos de ramificación
Los nodos de ramificación dirigen a las personas por rutas diferentes según sus atributos, historial de eventos, pertenencia a segmentos y más. Un único bloque integra tanto la antigua División de decisión - Sí / No - como la Ruta de audiencia - grupos ordenados con varias píldoras. Un interruptor del modal permite cambiar entre ambas.
El
nodeTypeinterno del bloque sigue siendoconditionpor compatibilidad con datos de recorridos existentes. Los recorridos nuevos se guardan comobranchMode: 'yesno' | 'multi'.
Dos modos
Sí / No: una ruta con nombre y Everyone else. Úsalo cuando la pregunta sea binaria: «¿esta persona compró, sí o no?».
Múltiple: hasta 10 grupos ordenados con nombre y Everyone else - 11 rutas en total. Úsalo cuando necesites más de dos rutas: «clientes VIP, visitantes frecuentes, compradores ocasionales, todos los demás». Convierte una rama Sí/No en Múltiple con Añadir un nuevo grupo en el panel del modal. Simplifícala de nuevo mediante Simplificar a Sí / No, visible cuando solo queda un grupo con nombre y Everyone else.
Resolución por prioridad ordenada
En modo Múltiple, los grupos se evalúan en orden. Gana el primer grupo que coincide. Las personas que no coinciden con ningún grupo con nombre se dirigen a Everyone else. Puedes arrastrar filas del panel para cambiar el orden.
«Salir de Canvas» por grupo
Cada grupo con nombre - y Everyone else - puede marcarse como Salir de Canvas en lugar de enrutar. Las personas que lleguen a ese grupo completan el recorrido en el paso de ramificación con exitReason: 'branch_exit:<group name>'. Es útil para «si se cumple la condición, no hace falta enviar nada: salir del flujo».
Filas de filtros
Cada ruta o grupo se configura con uno o más grupos de filtros. Los filtros dentro de un grupo se unen con un conector interno AND / OR; los propios grupos se unen con un groupOperator externo - normalmente OR.
El modal Ramificación utiliza el mismo componente <FilterRow> que emplean el editor de segmentos y el selector de audiencia de campañas, por lo que admite todos los tipos de filtro de esas interfaces:
| Tipo | Qué comprueba | Operadores |
|---|---|---|
attribute | user.attributes[field] | equals, not_equals, gt, gte, lt, lte, contains, not_contains, exists, not_exists, in, not_in |
default_attribute | Campos de usuario de nivel superior - email, phone, externalId, firstName, lastName, country, puntuaciones de ML y derivados de e-commerce | Igual que attribute |
event / behavioral | Historial de eventos con ventana temporal opcional | performed_event, not_performed_event, performed_event_in_last, not_performed_event_in_last, event_count_gte, event_count_lte |
segment | Pertenencia a segmento - recursiva; los segmentos pueden referenciar otros segmentos, hasta una profundidad de 5 | in, not_in |
canvas_execution | Ejecuciones de Canvas activas, completadas o con salida | in_canvas, not_in_canvas, in_any_canvas, not_in_any_canvas, completed_canvas, exited_canvas |
channel_subscription | user.subscriptions[channel].status | subscribed_to_channel, not_subscribed_to_channel, opted_in_to_channel |
list_membership | Registro de suscripción a una lista elegida | member_of_list, not_member_of_list |
bounce_status | Validez de email o estado de rebote duro o leve | email_valid, email_bounced, email_hard_bounced |
ecommerce | Segmento RFM, número de pedidos, gasto y estado del carrito | rfm_segment_equals, rfm_segment_in, has_purchased, never_purchased, total_orders_*, total_spent_*, average_order_value_*, days_since_last_order_*, has_active_cart, no_active_cart, cart_value_*, cart_abandoned |
entity | user.entityRecords[entity] | exists, not_exists |
app | user.appIds | has_app, not_has_app |
Los once tipos comparten un único evaluador - FilterEvaluator - que usan tanto el trabajador de ramificación de Canvas como el evaluador de campañas in-app. Los tipos nuevos que se añadan allí se habilitan automáticamente en todas partes.
Opciones de ventana temporal (filtros de evento)
withinMinutes: minutos - por ejemplo, 30.withinHours: horas - por ejemplo, 1 o 24.withinDays: días - por ejemplo, 7 o 30.eventTimeWindow: segundos, usado por el evaluador in-app.
También se admiten condiciones de propiedad; por ejemplo, «realizó Pedido completado en los últimos 30 días con valor ≥ 100»:
{
"type": "event",
"eventName": "Order Completed",
"operator": "performed_event_in_last",
"withinDays": 30,
"eventProperties": { "value": "100" }
}
Los valores del evento desencadenante
Dentro de un recorrido, una condición de propiedad de evento puede comparar con el valor que trajo el evento desencadenante en lugar de un valor fijo. Junto al cuadro de valor, elige Usar el valor del evento desencadenante; la fila se lee entonces "hotel es el hotel del evento desencadenante". En el cable el valor es la plantilla {{ trigger.properties.hotel }} (también se acepta la forma corta {{ trigger.hotel }}), resuelta a partir del evento desencadenante de la ejecución justo antes de evaluar la condición.
Una referencia que el desencadenante no puede responder - falta la propiedad, o el recorrido se inició por API y no tiene evento - hace esa condición falsa, y el runtime registra el nombre de la propiedad una vez. Nunca se trata como vacía.
Los segmentos no tienen desencadenante, así que la opción aparece solo en condiciones de recorrido.
Contar lo mismo
Los operadores de recuento (performed_count_gte, performed_count_lte) aceptan con los mismos valores de - de una a cinco propiedades del evento. El recuento se toma entonces por cada combinación distinta de esos valores, y la condición se cumple cuando cualquier combinación alcanza el número.
{
"type": "event",
"eventName": "hotel_viewed",
"operator": "performed_count_gte",
"value": 2,
"withinDays": 2,
"sameProperties": ["hotel", "check_in"],
"propertyConditions": [
{ "property": "hotel", "operator": "equals", "value": "{{ trigger.properties.hotel }}" },
{ "property": "check_in", "operator": "equals", "value": "{{ trigger.properties.check_in }}" }
]
}
En palabras: "realizó hotel_viewed al menos 2 veces en los últimos 2 días con el mismo hotel y check_in, donde hotel es el hotel del evento desencadenante y check_in es el check_in del evento desencadenante". Sin las dos condiciones de propiedad es "vio cualquier hotel dos veces para las mismas fechas" - la forma de segmento. Para un recorrido que deba iniciarse en la segunda mirada, usa la comprobación de repetición en el desencadenante en lugar de esta condición a mitad del recorrido.
En ClickHouse la forma agrupada es GROUP BY sobre las propiedades extraídas con HAVING count(DISTINCT event_id) >= N LIMIT 1; los nombres de propiedad se pasan como parámetros de la consulta, así que funciona cualquier nombre registrado (espacios, guiones, cualquier alfabeto; un nombre con punto lee primero la clave exacta y después la ruta anidada), y un nombre vacío hace fallar la condición (falsa).
Tarjeta de nodo de Canvas
La tarjeta de nodo se adapta al modo:
- Sí / No: dos puertos de salida en la parte inferior - verde = sí; rojo = no.
- Múltiple: un puerto de salida por grupo en el borde derecho de la tarjeta, con el nombre del grupo en la fila. La tarjeta crece verticalmente al añadir grupos.
Las etiquetas de conexión coinciden exactamente con el nombre de grupo; el trabajador lee las conexiones por nombre al enrutar. Si cambias el nombre de un grupo, la conexión sigue vinculada porque se usa el identificador de controlador de React Flow: cambiar nombre → guardar → sin roturas.
Ejemplo: flujo de carrito abandonado
- Desencadenante: Evento = «Producto añadido».
- Espera: espera 1 hora.
- Ramificación (Sí / No):
not_performed_event_in_last«Pedido completado» durante la última hora.- Sí: envía un email de recuperación.
- No (Everyone else): sale del flujo.
Ejemplo: enrutamiento RFM de varias rutas
- Ramificación (Múltiple) con 3 grupos con nombre y Everyone else:
- Clientes VIP -
ecommerce.rfm_segment_equals: champions- → envía una oferta exclusiva. - Visitantes frecuentes - evento Page Viewed en los últimos 7 días,
event_count_gte: 10- → envía una campaña de reactivación. - En riesgo -
ecommerce.days_since_last_order_gte: 60- → envía una campaña de recuperación. - Everyone else → sale de Canvas.
- Clientes VIP -
Nodos de bifurcación de comportamiento
Una bifurcación de comportamiento dirige a las personas según lo que hacen dentro de una ventana temporal. Mientras que Ramificación lee el estado en el momento de evaluación, la bifurcación de comportamiento deja a la persona en espera y observa el futuro: el primer evento que coincida - o el vencimiento de la ventana - decide qué ruta sigue.
Integra los antiguos bloques Ruta de acción - un solo evento y condición - y Ruta de audiencia basada en evento. Un concepto, dos estados.
Dos modos
| Modo | Cuándo usarlo |
|---|---|
| Hizo / No hizo | Una ruta «hizo» con nombre y la alternativa implícita «Sin evento en la ventana». Equivale a la antigua Ruta de acción de un evento. |
| Múltiple | Hasta 10 grupos ordenados con nombre y «Sin evento en la ventana». Convierte a múltiple con Añadir un nuevo grupo; vuelve a simplificar con Simplificar a Hizo / No hizo cuando quede un solo grupo con nombre. |
Ventana de espera
| Configuración | Comportamiento |
|---|---|
| Esperar hasta N unidades | Límite fijo: minutos, horas, días o semanas. |
| Personalizar | Ventana tomada de {{canvas.x}} - variable de contexto - o {{user.x}} - atributo de usuario. El valor debe resolverse como un número interpretado en la unidad elegida. |
La ventana es de nivel de bloque: todos los grupos de la misma bifurcación de comportamiento comparten el mismo límite. Las ventanas por grupo hacían incoherentes las configuraciones de varias rutas y rara vez se usaban, por lo que se eliminaron al rediseñar el nodo.
Modo de avance
| Modo | Comportamiento |
|---|---|
As soon as an event fires - predeterminado | Gana el primer evento que coincida con cualquier fila de desencadenante. La persona se enruta de inmediato. El orden sigue siendo el desempate para coincidencias simultáneas en un mismo ciclo de evento. |
At end of window | El bloque espera toda la ventana. Si una persona coincide con varios grupos durante ella, gana el grupo con mayor prioridad. Elígelo cuando el orden importe más que la rapidez. |
Selector de desencadenante
La lista de desencadenantes de cada grupo aparece en una tarjeta con un selector de tipo de desencadenante en la parte superior de cada fila. Los tipos nuevos se integran en el mismo selector sin modificar la configuración guardada.
| Tipo | Estado de ejecución |
|---|---|
| Realizar evento personalizado | Totalmente conectado. Elige cualquier evento del registro de eventos. Los filtros de propiedad unidos por AND acotan la coincidencia. |
| Realizar pedido / Iniciar sesión / Realizar compra (heredado) | Eventos predefinidos con etiquetas claras. Están conectados y se resuelven como nombres de evento canónicos: place_order, start_session, make_purchase_legacy. |
| Realizar evento de conversión | Se guarda, pero aún no está conectado; está pendiente del gancho de ejecución de eventos de conversión. |
| Añadir una dirección de email | Se guarda, pero aún no está conectado; está pendiente del flujo de eventos de asignación de atributos. |
| Cambiar valor de atributo personalizado | Se guarda, pero aún no está conectado; está pendiente del flujo de eventos de cambio de atributos. |
Los tipos sin conexión muestran un aviso ámbar en línea para que quienes crean el flujo no se sorprendan durante la ejecución.
Dentro de un grupo, las filas de desencadenante se unen mediante OR: basta con que coincida una para enrutar a la persona. Dentro de un desencadenante, los filtros de propiedad múltiples se unen mediante AND.
«Salir de Canvas» por grupo
Una casilla por grupo termina el recorrido al elegir esa ruta, en vez de dirigir a un nodo conectado. La ejecución se cierra con exitReason = "behavior_split_exit:<group_name>".
Tarjeta de nodo de Canvas
La tarjeta de bifurcación de comportamiento tiene una franja violeta en el encabezado - «BEHAVIOR SPLIT» - y una píldora de reloj que muestra la etiqueta de ventana - «3 días», «{{canvas.evaluation_window}} horas».
- Modo Hizo / No hizo: dos puertos inferiores con identificadores estables,
did- violeta - ytimed_out- gris azulado. Cambiar el nombre de la ruta en el modal no deja conexiones huérfanas. - Modo Múltiple: filas apiladas, una por grupo con nombre y la fila gris azulado «Sin evento en la ventana». Cada fila tiene su propio controlador de origen en el borde derecho de la tarjeta, con
id = group-name-slug; la fila de tiempo agotado utilizatimed_out.
Cuando la lista de desencadenantes de un grupo está vacía, la fila muestra una pequeña insignia de advertencia. Ese grupo nunca puede coincidir, por lo que el bloque no funcionará correctamente hasta que añadas un desencadenante o marques Exit canvas.
Ejemplos desarrollados
Ejemplo 1: carrito abandonado. Modo Hizo / No hizo. Desencadenante = purchase_completed. Ventana = 24 horas. Avance = As soon as an event fires. Conecta la salida timed_out a un email de recordatorio y la salida did a un agradecimiento. Quienes compren salen correctamente; quienes no, reciben un recordatorio después de un día.
Ejemplo 2: reactivación multicanal. Modo Múltiple. Tres grupos ordenados: 1. Realizó compra - evento=purchase_completed, 2. Visitó precios - evento=page_view + filtro de propiedad page=/pricing - y 3. Abrió email - evento=email_opened. Avance = At end of window. Ventana = 7 días. Conecta cada grupo a una secuencia de seguimiento distinta; la salida Sin evento en la ventana va a una ruta de nurturing más prolongada. El orden importa: una persona que haya comprado Y visitado precios sigue la ruta Realizó compra.
Nodos de experimento
Para pruebas A/B/n, fijar una ganadora, optimización de bandido multibrazo o personalización por persona impulsada por ML, usa el nodo Experimento. Consulta la guía del nodo de experimento para conocer todos los detalles.
El nodo independiente División A/B se ha eliminado. El nodo Experimento en modo de tipo de ruta «Estándar» cubre el mismo caso de uso con más flexibilidad: grupos de control, grupos de espera y elección opcional de ganadora.
Nodos de decisión con IA
El nodo Decisión con IA dirige a cada persona por la ruta que la IA predice que es mejor para esa persona: la decisión de «ajuste de oferta» individual dentro de un recorrido. Mientras que el nodo Experimento encuentra la ruta ganadora global, Decisión con IA elige una ruta diferente por persona según sus atributos y comportamiento.
Configuración:
- Rutas: las rutas entre las que elige la IA; cada una continúa en su propia rama posterior.
- Objetivo: Interacción - aperturas y clics, Conversión - un evento específico - o Ingresos - valor de compra. Determina qué optimiza el modelo.
- Evento de conversión: aparece cuando el objetivo es Conversión; es el evento que cuenta como éxito. Puede ser un evento personalizado como
signup.
Cómo decide - por persona: el modelo individual elige la mejor ruta - explotación; una pequeña parte explora rutas inciertas para seguir aprendiendo - de forma inteligente, no aleatoria. Antes de que el modelo haya aprendido las rutas, las personas se distribuyen de forma justa - inicio en frío. Los resultados se atribuyen de vuelta y el modelo se reentrena a diario.
Qué cuenta como «victoria» y de qué aprende. El éxito sigue tu objetivo: Interacción cuenta aperturas y clics; Conversión, el evento de conversión; e Ingresos, las compras. La victoria se acredita a la ruta por la que fue dirigida la persona, de modo que la IA aprende qué mensaje u oferta impulsa realmente el resultado, no solo cuál se abre. Para un objetivo de Conversión o Ingresos, una apertura o clic no es una «victoria» por sí sola: optimizaría lo equivocado; un mensaje de clickbait puede ganar aperturas y perder ventas. Las aperturas y clics siguen ayudando como entradas, a continuación. Para elegir una ruta individual, la IA analiza el comportamiento y perfil recientes a partir de tus datos existentes; no hay nada que etiquetar:
- Interacción: cuánto abren y hacen clic - email, Push e in-app, cuándo estuvieron activas por última vez, con qué frecuencia visitan - sesiones y páginas vistas, respuestas de WhatsApp y en qué horas o días suelen estar activas.
- Valor: lo que han comprado: pedidos, gasto total y medio y RFM - recencia / frecuencia / valor monetario.
- Perfil: país, antigüedad como cliente y canales por los que se les puede contactar - email / teléfono.
Se prepara por sí solo. Como las personas entran en un recorrido de forma continua, un nodo Decisión con IA aprende mientras se ejecuta el recorrido. Las primeras entradas se distribuyen de manera justa mientras recopila datos, y las posteriores reciben enrutamiento personalizado automáticamente. No requiere más configuración que definir rutas y objetivo. Los límites de frecuencia y las horas de silencio no se configuran en este nodo: se aplican en los nodos de mensaje o envío y a nivel de espacio de trabajo, porque un nodo de decisión solo enruta.
Envíos programados únicos: «Preparar antes del envío completo». Un recorrido programado para ejecutarse una vez para una audiencia fija no puede prepararse solo: todo el mundo entraría a la vez antes de que la IA hubiera visto un solo resultado. Para este caso, el nodo Decisión con IA incluye el interruptor Preparar antes del envío completo. El recorrido entrega primero a una pequeña muestra inicial de la audiencia, retiene al resto y después lo libera automáticamente con enrutamiento personalizado cuando el modelo ha aprendido las rutas - o tras el tiempo máximo de retención que definas. Los recorridos activados continuamente no lo necesitan porque ya se preparan solos.
Cómo se reparte el crédito - multitoque. Cuando una persona pasa por varios nodos de Decisión con IA en un recorrido y después convierte, el crédito se reparte entre esas decisiones, no se entrega por completo a la última. En un recorrido de varios pasos, las decisiones de enrutamiento anteriores también ayudaron a llegar al resultado. Las decisiones recientes reciben la mayor parte y las antiguas se desvanecen gradualmente - modelo de «decaimiento temporal». Un recorrido con una sola decisión acredita esa decisión íntegramente. Esto difiere de una campaña optimizada con IA, que es un envío único y acredita su única decisión más reciente: «último toque».
Nodos de Siguiente mejor mensaje
El nodo Siguiente mejor mensaje responde «qué mensaje» para cada persona: puntúa las plantillas guardadas del espacio de trabajo en los canales que permites y registra la que enviaría. Se lanza primero en modo sombra: el nodo no envía nada y el recorrido continúa por su única salida exactamente como antes, mientras cada paso registra la elección junto a lo que el recorrido envió realmente. Esa comparación decide si el nodo pasa a enviar bajo un grupo de control; léela en Ajustes, Modelos ML.
Configuración:
- Canales a considerar - email, in-app, push. Las plantillas de estos canales forman el conjunto para cada persona; un canal que las reglas de frecuencia retendrían para una persona se excluye para ella.
- Solo plantillas con estas etiquetas - reduce el conjunto a las plantillas que llevan una de las etiquetas (vacío significa todas).
- Objetivo y Evento de conversión - contra qué se mide después la elección registrada, como en el nodo de Decisión IA.
Cómo puntúa (por persona): el modelo compartido de Ajustes, Modelos ML valora cada plantilla por el comportamiento de la persona y las etiquetas de contenido de la plantilla (así una plantilla totalmente nueva recibe una puntuación real), el canal preferido de la persona conserva su puntuación mientras los demás se descuentan, y gana la puntuación más alta. Antes de entrenar un modelo compartido todas las plantillas puntúan igual y la elección es un sorteo justo, y así lo dice el registro.
Modo envío. Cambia el modo del nodo a Enviar cuando la comparación en sombra parezca correcta. Una proporción de grupo de control que eliges (20% por defecto) conserva el comportamiento actual y sale por la salida Grupo de control, que conectas a tu propio mensaje; el resto recibe la elección enviada desde el propio nodo (una plantilla de email o push, bajo las mismas reglas de consentimiento, horas de silencio y frecuencia que cualquier nodo de mensaje) y sale por la salida Enviado. Los dos brazos se comparan en Ajustes, Modelos ML con un rango probable cada uno y un veredicto de «sin pérdida de conversiones», que es el criterio para mantener el nodo en modo envío. Las plantillas in-app se puntúan pero el nodo no las envía.
Nodos de actualizar usuario
Los nodos Actualizar usuario tienen dos tipos de fila; elige uno para cada fila:
Actualizar un atributo
Establece, incrementa, reduce, añade o elimina un valor de un atributo de usuario. Los atributos proceden del registro del espacio de trabajo: empieza a escribir para filtrar; no hay texto libre, así que primero define atributos nuevos en Configuración → Atributos. Las operaciones disponibles se filtran automáticamente según el tipo de atributo: solo inc / dec para números, append / remove para matrices, etc.
Registrar un evento
Activa un evento registrado para la persona desde Canvas. Es útil para marcar hitos del recorrido - completed_onboarding, abandoned_checkout - que otros Canvas o segmentos pueden escuchar. El campo de nombre de evento se autocompleta con los eventos registrados del espacio de trabajo, pero acepta texto libre para nombres nuevos.
Puedes añadir varias filas a un nodo Actualizar usuario; se aplican en orden. Arrastra el controlador para reordenarlas.
Casos de uso
- Etiquetar a personas que completaron un flujo:
engagement_tag = 'onboarded'. - Actualizar puntuaciones:
engagement_score += 10. - Registrar eventos de recorrido para segmentación posterior: Registrar evento:
onboarding_completed. - Definir indicadores para segmentación futura:
feature_eligibility = true.
JSON personalizado
Además de las filas anteriores, un nodo Update User tiene un segundo modo: cambia Campos a JSON personalizado en la parte superior del nodo. Los nodos creados antes de que existiera este modo siguen en modo Campos.
En modo JSON personalizado escribes un objeto JSON con la misma forma que los campos attributes, subscriptions y events del cuerpo de la API POST /users. Un uso típico: una landing page de tu propio sitio envía un evento a través de la API, el evento inicia este recorrido y este paso añade a la persona a una lista, define atributos y registra un evento de seguimiento.
{
"attributes": { "firstName": "Dana" },
"subscriptions": [
{ "listId": "<list id>", "channel": "email", "status": "subscribed" }
],
"events": [
{ "name": "Free Gift Requested", "properties": { "source": "landing-page" } }
]
}
| Clave | Qué hace |
|---|---|
attributes | Define cada atributo en la persona, como la fusión de atributos de la API. |
subscriptions | Añade a la persona a listas de suscripción o la quita de ellas. listId es obligatorio; channel es email (por defecto), sms, whatsapp, push o viber; status es subscribed (por defecto) o unsubscribed. |
events | Registra eventos para la persona. name es obligatorio; properties y timestamp (fecha ISO o milisegundos epoch) son opcionales. Los eventos se registran igual que las filas Track an event. |
Usa Insertar ejemplo para empezar desde el ejemplo anterior y el selector de listas para insertar una de tus listas.
Siempre actualiza a la persona que entró en el paso. Los identificadores no se pueden definir ni cambiar: email, phone, externalId, userId, anonymousId, _id, id, aliases y las demás claves de identidad se rechazan, tanto como claves de nivel superior como nombres de atributo, en cualquier combinación de mayúsculas y con o sin _ o -. También se rechazan los atributos gestionados por la plataforma, como lastEventName, exactamente como en la API. En el nivel superior solo se permiten attributes, subscriptions y events.
Una baja se respeta. Si la persona se dio de baja de una lista en ese canal, un elemento subscribed para ella se omite y se informa ("opt-out kept"): un recorrido nunca vuelve a suscribir a nadie. Un "status": "unsubscribed" explícito siempre se aplica. Cada lista debe pertenecer a este espacio de trabajo; cualquier otro id de lista se omite.
Las listas con doble confirmación se tratan igual que a través de la API: la persona queda registrada como suscrita (origen journey) y este paso no envía un mensaje de confirmación.
Los límites son los de la API: como máximo 100 suscripciones y 25 eventos, y los límites de tamaño de la API para valores de atributos y propiedades de eventos. El propio JSON puede tener hasta 50.000 caracteres, 10 niveles de anidación y 5.000 valores; cada valor personalizado puede renderizarse en un máximo de 50.000 caracteres (500.000 en total).
Liquid en JSON personalizado
Usa Liquid dentro de valores de texto: el evento que inició el recorrido, el perfil de la persona y las variables del recorrido están disponibles, como en cualquier otro campo personalizado:
{
"attributes": {
"firstName": "{{ event.properties.first_name }}",
"giftSource": "{{ event.properties.source | default: 'landing-page' }}"
},
"subscriptions": [
{ "listId": "{{ event.properties.list_id }}", "channel": "email" }
],
"events": [
{ "name": "Free Gift Requested", "properties": { "plan": "{{ user.plan }}" } }
]
}
El JSON debe ser válido tal como está escrito: Liquid va solo dentro de valores entre comillas, nunca en claves ni como valor suelto. Cada valor se renderiza por separado y sigue siendo un valor de texto, así que los datos del evento nunca pueden cambiar la estructura del JSON ni llegar a un identificador. Como un valor renderizado siempre es texto, escribe los números y true / false de forma literal.
Cuándo se comprueba
- Al guardar: JSON no válido, claves desconocidas, identificadores y los límites se rechazan con un mensaje que nombra el paso. Un JSON personalizado vacío se puede guardar como borrador.
- Al activar: un JSON personalizado vacío y cualquier id de lista que no sea una lista de este espacio de trabajo.
- Al ejecutarse: los valores escritos con Liquid se comprueban después de renderizarlos. Si algo está mal, el paso no cambia nada, el motivo se registra en la ejecución del recorrido de la persona y la persona continúa al paso siguiente.
- La pestaña Test renderiza el JSON con una persona de ejemplo sin escribir nada.
Nodos de Issue coupon
Un nodo Issue coupon entrega a la persona un código de un programa de cupones - creado en ese momento en la tienda conectada - y lo guarda con ella. Cada mensaje posterior del recorrido que use {{ coupons.<slug>.code }} muestra ese mismo código, en cualquier canal.
- Program - elige un programa activo. El nodo no hace nada más: pon el código en los mensajes que siguen.
- Dos salidas: Issued (la persona tiene un código) y Could not issue (la tienda no pudo crear uno, o el programa está en pausa). Dirige la segunda salida a un mensaje sin cupón, o termina ahí el recorrido.
- Un reintento del nodo nunca crea un segundo código y, con "reutilizar el código abierto de la persona" activado en el programa, quien vuelve a entrar en el recorrido con su código todavía abierto recibe el mismo código.
Nodos de webhook
Los nodos de webhook realizan llamadas HTTP a servicios externos.
Configuración
| Configuración | Descripción |
|---|---|
| Método y URL | GET / POST / PUT / PATCH / DELETE y la URL del endpoint. La URL admite Liquid. |
| Autenticación | Ninguna / Bearer / Básica / Clave de API / Firmada (HMAC). Bearer, Básica y clave de API se convierten en el encabezado correcto al guardar - por ejemplo, Authorization: Bearer <token>. Firmada - HMAC - añade el encabezado X-Joryio-Signature, un HMAC SHA-256 del cuerpo de solicitud, para que quien recibe pueda comprobar que la llamada procede de Joryio. Firmada (HMAC) usa el secreto de firma que introduces. Los secretos se cifran al guardar y vuelven como un campo oculto: déjalo para conservar el secreto, bórralo para eliminarlo o escribe un valor nuevo para sustituirlo. Un secreto guardado solo se conserva para la dirección con la que se guardó: si cambias el esquema, el host o el puerto de la URL, vuelve a introducir el secreto antes de guardar. Un secreto necesita una dirección literal: sin Liquid, usuario ni contraseña en el esquema, el host o el puerto (Liquid en la ruta o la consulta está permitido). Al enviar, el secreto solo se adjunta si la URL renderizada sigue apuntando a esa dirección; si no, la solicitud sale sin él y la vista de la ejecución lo indica. Los encabezados personalizados que parecen credenciales (Authorization, o un encabezado cuyo nombre indica token, secret o API key) se ocultan del mismo modo. En Journey Runs, el paso de webhook de una persona muestra el código HTTP, si fue correcto o fallido, la duración y los campos de respuesta guardados en variables del recorrido. Una llamada fallida también muestra un bloque Respuesta debajo del estado (ver Comportamiento del webhook más abajo); el cuerpo de una respuesta correcta nunca se guarda. |
| Encabezados personalizados | Filas clave/valor. Los valores admiten Liquid. Content-Type se añade cuando la solicitud lleva cuerpo y se puede anular; un Content-Type que definas tú siempre se envía. |
| Cuerpo de solicitud | JSON, codificado como formulario - application/x-www-form-urlencoded - o Ninguno (sin cuerpo y sin Content-Type - para GET/DELETE). El cuerpo JSON se valida en línea mientras escribes; un cuerpo que es solo una etiqueta Liquid (p. ej. {{ user.id }}) muestra "No se garantiza que sea JSON tras el renderizado". |
| Tratamiento de respuesta | Opcional: extrae un valor del cuerpo de respuesta - una ruta $.a.b, por ejemplo $.user.crm_id - a una variable de recorrido - por ejemplo, crm_id - para que un paso posterior pueda ramificar o usarlo en una plantilla. Para guardarlo en el usuario, añade un paso Actualizar usuario que lea la variable. |
| Reintentos y tiempo de espera | Máximo de reintentos y tiempo de espera de solicitud por nodo. La espera sigue siendo exponencial y los reintentos se activan con errores 5xx y de red; consulta Comportamiento de webhook abajo. |
| Llamada de sistema: omitir horas de silencio y límites de frecuencia | Desactivada de forma predeterminada: los webhooks esperan las ventanas de silencio y respetan límites de frecuencia como cualquier mensaje. Actívala solo para llamadas puras entre sistemas que no deben retrasarse por las horas de silencio de una persona. Las listas de supresión se aplican de cualquier forma y los destinatarios de webhook son perfiles activos facturables independientemente de esta opción. |
Cuerpo enviado literalmente
El cuerpo que configuras se envía tal cual al receptor. No hay ningún sobre de Joryio que lo envuelva.
Si quieres incluir metadatos de canvas, ejecución o usuario en la solicitud, añádelos tú con Liquid:
{
"event": "user_signup",
"user_id": "{{ user.id }}",
"email": "{{ user.email }}",
"canvas_id": "{{ canvas.id }}",
"execution_id": "{{ execution.id }}",
"node_id": "{{ node.id }}"
}
Joryio también añade automáticamente tres encabezados de metadatos (para que el receptor pueda usarlos sin cambiar la forma del cuerpo):
X-Joryio-Canvas-Id: <canvas id>
X-Joryio-Execution-Id: <execution id>
X-Joryio-Node-Id: <node id>
El cuerpo se envía byte a byte, exactamente como se renderizó: un cuerpo que se renderiza vacío no se envía (nunca como "" vacío), y el texto que no es JSON - por ejemplo un id suelto de {{ user.id }} - se envía tal cual, sin comillas. La firma HMAC cubre exactamente esos bytes. Send test muestra la solicitud enviada y avisa cuando un cuerpo JSON no es JSON válido tras el renderizado; el envío real nunca se modifica.
Espacios de nombres de Liquid
Disponibles en la URL, los valores de encabezado y el texto del cuerpo JSON:
| Espacio de nombres | Contiene |
|---|---|
user.* | Campos de usuario de nivel superior (user.id, user.email, user.phone) y todos los atributos personalizados (user.firstName, user.plan, …). |
event.* / trigger.* | La carga del evento de activación que inició esta ejecución. |
canvas.* | canvas.id, canvas.name. |
execution.* | execution.id, execution.startedAt. |
node.* | node.id, node.type, node.label. |
Las claves planas heredadas ({{ canvasId }}, {{ executionId }}) siguen resolviéndose.
Comportamiento de webhook
Un nodo de webhook se ejecuta en uno de dos modos, según esté activado o no el Tratamiento de respuesta:
El canvas avanza inmediatamente después de poner el webhook en cola, sin esperar la respuesta HTTP. Es ideal para llamadas de disparar y olvidar (notificar a un CRM, iniciar una tarea posterior).
Cuando asignas un campo de respuesta a una variable de recorrido, el nodo se ejecuta de forma síncrona: el recorrido se pausa en el nodo de webhook hasta que llega la respuesta (o hasta un tiempo de espera de 15 segundos), de modo que la variable esté lista para el siguiente paso. Es de fallo abierto: si hay tiempo de espera o error, el recorrido continúa igualmente (la variable queda sin definir; si conectaste una salida de error, el fallo se dirige allí). La ejecución queda aparcada (no retiene un worker), por lo que escala para audiencias grandes.
En ambos modos:
- Los fallos de webhook nunca detienen el flujo de Canvas (fallo abierto).
- Los webhooks asíncronos se reintentan ante errores 5xx y de red con espera exponencial, hasta el máximo de intentos del nodo. Las respuestas 4xx fallan de inmediato y no se reintentan; las 429 respetan el encabezado
Retry-After. - Las respuestas fallidas se conservan para depurar. Cuando una llamada falla con una respuesta que no es 2xx, Joryio guarda el código de estado, el tipo de contenido y los primeros 2 KB del cuerpo de la respuesta, con los valores que parecen secretos (tokens Bearer / Basic, JWT, campos
token/secret/password/api_key/authorization, cadenas hex o base64 largas) ocultos antes de guardarlos. Cualquier credencial que la propia solicitud envió (su token, contraseña, clave de API o firma) también se elimina dondequiera que la respuesta la repita, incluidas sus formas base64, URL-encoded, JSON-escaped y hex. Las cabeceras de la solicitud nunca se guardan. Un tiempo de espera agotado o un error de red guarda solo su mensaje de error. Abre el bloque Respuesta en el paso de webhook de Journey Runs (o en el evento de fallo de la cronología del destinatario de una campaña de webhook) para leerla. El cuerpo solo se muestra a quien tiene acceso a datos personales (el permisopii:view), porque una respuesta puede contener datos de un contacto; los demás ven el estado y el error con una nota de que la respuesta está oculta. Las respuestas guardadas se eliminan automáticamente a los 30 días. El cuerpo de una respuesta correcta (2xx) nunca se guarda. El equipo de Joryio puede desactivar, a petición, el guardado de cuerpos de respuesta para tu organización; el estado, la duración y el error se siguen registrando. - Solo una respuesta 2xx cuenta como entregada. Un 3xx o 4xx (por ejemplo 401 o 404) es un fallo: aparece como fallido en la ejecución del recorrido y en el outbox, y un webhook síncrono toma su salida de error, nunca la ruta de éxito.
- Los webhooks síncronos fallan rápido (sin bucle de reintento) para mantener el recorrido aparcado en movimiento; un endpoint que tarde más de 15 segundos agota el tiempo de espera y falla abierto. Una red de seguridad reanuda cualquier recorrido cuya respuesta se haya perdido, para que un contacto nunca quede aparcado para siempre.
- Un interruptor de circuito por host se activa tras fallos repetidos de salud del host (tiempos de espera, red o 5xx) hacia el mismo host y corta las llamadas posteriores durante un breve período de enfriamiento. Así, durante una caída del endpoint, las llamadas síncronas fallan abiertas al instante en lugar de esperar todas el tiempo completo, y no se sobrecarga un host caído. Se recupera automáticamente cuando el host vuelve a responder. (Los 4xx/429 no lo activan porque indican que el host está activo.)
Nodos de conector
Los nodos de conector sincronizan usuarios con audiencias de plataformas publicitarias externas durante la ejecución del canvas.
Configuración
| Configuración | Descripción |
|---|---|
| Integración | Selecciona una integración conectada de sincronización de audiencias |
| Acción | Añadir a audiencia, Eliminar de audiencia o Sincronizar audiencia |
| Audiencia | Audiencia objetivo en la plataforma externa |
Plataformas compatibles
- Meta Ads (Custom Audiences)
- Google Ads (Customer Match)
- TikTok Ads (Custom Audiences)
- LinkedIn Ads (Matched Audiences)
- Criteo Ads (Contact Lists)
Comportamiento del conector
Las acciones del conector se ponen en cola y se procesan de forma asíncrona. El canvas avanza inmediatamente después de poner la acción en cola. Las acciones fallidas se reintentan hasta tres veces con espera exponencial.
Los datos de usuario (email, teléfono e ID externo) se someten a hash según los requisitos de cada plataforma antes de enviarse.
Nodos de salida
Los nodos de salida terminan el flujo de Canvas para un usuario.
Motivos de salida
| Motivo | Descripción |
|---|---|
| Objetivo alcanzado | El usuario completó la acción deseada |
| Canceló la suscripción | El usuario se dio de baja |
| Ya no cumple los requisitos | El usuario ya no cumple los criterios |
| Salida manual | Finalización explícita del flujo |
Orden de procesamiento
Cuando varios usuarios entran simultáneamente en un canvas:
- Los workers de Canvas procesan a los usuarios en paralelo.
- La ruta de cada usuario es independiente.
- El envío de mensajes se distribuye en colas específicas por canal.
- Los escenarios de gran volumen (más de un millón de usuarios) se gestionan eficientemente.
Variables de plantilla de comercio electrónico
Al enviar mensajes desde Canvas, los datos de comercio electrónico están disponibles automáticamente para personalización.
Datos del carrito
| Variable | Descripción |
|---|---|
{{ cart.items }} | Matriz de artículos del carrito |
{{ cart.itemCount }} | Número total de artículos |
{{ cart.value }} | Valor total del carrito |
{{ cart.subtotal }} | Subtotal de los artículos, antes de envío e impuestos (cart.value es el total que envió la tienda, que puede incluir el envío) |
{{ cart.currency }} | Código de moneda (USD, EUR, etc.) |
{{ cart.checkoutUrl }} | URL para reanudar el checkout |
{{ cart.abandoned }} | Si el carrito está abandonado |
Ejemplo: email de carrito abandonado
<h2>¡Has dejado artículos en el carrito!</h2>
{% for item in cart.items %}
<div style="margin: 10px 0;">
<img src="{{ item.imageUrl }}" width="80" />
<strong>{{ item.name }}</strong>
<span>${{ item.price }} x {{ item.quantity }}</span>
</div>
{% endfor %}
<p><strong>Total: ${{ cart.value }}</strong></p>
<a href="{{ cart.checkoutUrl }}" style="background: #007bff; color: white; padding: 12px 24px;">
Completa tu compra
</a>
Campos de artículos del carrito
Cada artículo de cart.items contiene:
| Campo | Descripción |
|---|---|
productId | Identificador del producto |
name | Nombre del producto |
price | Precio unitario |
quantity | Cantidad en el carrito |
total | precio × cantidad |
imageUrl | URL de imagen del producto |
sku | SKU del producto |
variantId | Identificador de variante |
Contenido relacionado
Nodos de Agente de IA
Un nodo Agente de IA ejecuta uno de tus agentes de IA para la persona del recorrido y guarda la respuesta en una variable del recorrido (ver Salida del agente).
- Un agente de Escribir tiene dos ramas: Éxito y Error.
- Un agente de Clasificar tiene una rama por etiqueta, más No seguro para una respuesta de la que el agente no está seguro, más Error.
Error es una sola rama a propósito. El motivo del fallo (un tiempo de espera, un límite de tasa, una clave mal configurada, un presupuesto agotado, un error del proveedor) se escribe en agent.<variable>_outcome y agent.<variable>_error, así que un nodo Rama después del agente puede enrutar por él cuando el recorrido lo necesite. Una rama sin conectar pasa al siguiente paso por defecto con el valor de reserva del agente, de modo que un recorrido nunca se detiene por un fallo del agente. El nodo muestra lo que cuesta una ejecución, unos X por 1.000 ejecuciones, junto al selector de agente.