El nodo de código permite a los desarrolladores ejecutar lógica personalizada en JavaScript dentro de un flujo de conversación. Es el nodo más potente y flexible de Convos, ya que permite consultar APIs, realizar transformaciones complejas, manejar lógica condicional y construir mensajes dinámicos.
¿Qué hace este nodo?
Cada vez que se ejecuta, el nodo recibe información del contexto del diálogo, permitiendo al desarrollador acceder a:
Datos del contacto.
Variables previamente capturadas o definidas.
Información de campañas transaccionales.
Mensajes entrantes.
Al finalizar el bloque de código, el nodo debe invocar la función output(), que indica qué hacer a continuación: guardar estado, capturar nuevas variables, enviar mensajes, etc.
Variables disponibles
Estas variables están disponibles globalmente en el script y representan el contexto del flujo:
Variable | Descripción |
variables | Objeto con todas las variables capturadas previamente en el diálogo, tanto desde nodos de captura como generadas por código. |
persisted | Información persistida desde campañas transaccionales. Por ejemplo: persisted.input.orderId. Útil para continuar flujos basados en campañas. |
contact | Información del perfil del contacto. Se accede como contact.phone, contact.firstname, contact.field_1, hasta contact.field_100. |
state | Objeto que guarda información de estado entre ejecuciones del mismo nodo. Permite dividir la lógica en etapas (stage). |
inboundMessage | Objeto completo del mensaje recibido por el sistema. Contiene metadata, tipo, etc. |
inboundMessageBody | Solo el texto plano del mensaje entrante. Útil para capturar respuestas rápidas. |
Métodos disponibles
output({ state, variables, messages, ticket })
Es obligatorio. Cierra el nodo de código y permite:
Persistir un nuevo estado (state) para futuras ejecuciones del mismo nodo.
Crear o modificar variables (variables) accesibles por otros nodos.
Enviar mensajes al contacto (messages).
Ejemplo:
output({
state: {
stage: 1,
wait: true
},
variables: {
age: inboundMessageBody
},
messages: [
{
type: 'text',
text: {
body: '¿Cuál es tu edad?'
}
}
],
ticket: {}
});✅ wait: true indica que el nodo debe volver a ejecutarse la próxima vez que el contacto responda.
fetch(url, options)
Permite hacer llamadas HTTP síncronas (tipo await fetch). Ideal para consumir APIs externas y personalizar el flujo.
Ejemplo:
const params = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email: contact.email })
};
const response = await fetch('https://api.miapp.com/user', params);
const data = JSON.parse(response);
mail(to, subject, html)
Permite hacer un envío de mail. Ideal para realizar notificaciones o integraciones vía mail.
Ejemplo
const html = '<h1>Nuevo registro</h1>';
mail(‘[email protected]’, 'Nuevo registro', html);
Estructura de mensajes
Solo se pueden enviar mensajes interactivos (no templates pre aprobados de Meta).
Envío de mensajes opcional
El envío de mensajes dentro del nodo de código no es obligatorio.
Podés usar este nodo únicamente para ejecutar lógica de programación, como:
• Calcular variables complejas.
• Realizar validaciones silenciosas.
• Consultar APIs externas.
• Enriquecer el diálogo con datos antes de continuar.
Esto es especialmente útil cuando no necesitás interactuar directamente con el usuario en ese momento del flujo, sino preparar información para pasos posteriores.
Ejemplo sin mensajes:
const resultado = 42;
output({
state: { wait: false },
variables: {
resultado: resultado
}
});
⚠️ Recordá que, aunque no envíes mensajes, siempre es necesario ejecutar output() para finalizar el nodo correctamente.
Listado de mensajes interactivos disponibles
Tipo | Estructura |
text | { |
image | { |
contacts | { |
document | { |
location | { |
buttons | { |
list | { |
También puedes enviar múltiples mensajes
messages: [
{
type: 'image',
media: { link: 'https://...' }
},
{
type: 'text',
text: { body: 'Gracias por tu compra' }
}
];
Estructura de ticket
Si necesita crear un ticket dede el nodo codigo puede utilizar la key de ticket
output({
state: {
wait: true
},
variables: {},
messages: [
{
type: 'text',
text: {
body: 'Lo conectamos con un agente para que lo ayude'
}
}
],
ticket: {
inboxId: 1,
tags: ['vip']
}
});
Variables:
inboxId: La variable inboxId es requerida para saber a que bandeja de entrada se debe asignar el ticket.
tags: La variable tags es opcional, se puede utilizar para agregar etiquetas al ticket de maner automatica.
Casos de uso comunes
Recolección por etapas
Utilizando state.stage, podés dividir el flujo en múltiples pasos:
if (!state.stage || state.stage === 0) {
output({
state: { stage: 1, wait: true },
messages: [{ type: 'text', text: { body: '¿Cuál es tu edad?' } }]
});
} else if (state.stage === 1) {
output({
state: { stage: 2, wait: true },
variables: { age: inboundMessageBody },
messages: [{ type: 'text', text: { body: '¿Cuál es tu DNI?' } }]
});
} else {
output({
state: { wait: false },
variables: { document: inboundMessageBody },
messages: [{ type: 'text', text: { body: '¡Gracias por responder!' }}]
});
}
Envío de feedback con datos transaccionales
const params = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contact: persisted.input.phone,
rating: variables.rating,
feedback: variables.feedback ?? ''
})
};
await fetch('https://api.externo.com/feedback', params);
output({ state: { wait: false } });
Consulta de órdenes por email o ID
let search = variables.value_to_search;
let isEmail = search.includes('@');
let query = isEmail
? `{ orders(first: 1, query: "email:${search}") { edges { node { id, fulfillments { trackingInfo { url } } } } } }`
: `{ order(id: "gid://shopify/Order/${search}") { id, fulfillments { trackingInfo { url } } } }`;
const response = await fetch('https://shopify.com/graphql', {
method: 'POST',
headers: { Authorization: 'Basic XXXXXX' },
body: JSON.stringify({ query })
});
const data = JSON.parse(response);
const link = isEmail
? data.data.orders.edges[0]?.node.fulfillments[0]?.trackingInfo[0]?.url
: data.data.order?.fulfillments[0]?.trackingInfo[0]?.url;
output({
state: { wait: false },
messages: [{
type: 'text',
text: { body: link ? `Tu código de seguimiento es: ${link}` : 'No encontramos tu orden.' }
}]
});
Buenas prácticas
Usar state.wait = true cuando el flujo espera otra respuesta del usuario.
Evitar declarar una variable llamada state dentro del código (ya está reservada).
Usar try/catch si se realiza fetch para evitar errores de ejecución.
Si se usan datos sensibles, asegurarse de no exponerlos en mensajes al cliente.
Utilizar nombres de variables claros y semánticos para facilitar el mantenimiento del flujo.
Utilizar punto y comas al finalizar cada línea de programación para asegurar su correcto funcionamiento.
Estructura base recomendada
try {
// lógica principal
output({
state: { wait: false },
variables: { ... },
messages: [ ... ]
});
} catch (error) {
output({
state: { wait: false },
messages: [{
type: 'text',
text: { body: 'Ocurrió un error inesperado. Por favor, intenta nuevamente más tarde.' }
}]
});
}
