Vai al contenuto principale

Nodo di codice in un dialogo

Aggiornato oltre 6 mesi fa

Il nodo Codice consente agli sviluppatori di eseguire logica JavaScript personalizzata all'interno di un flusso di conversazione. È il nodo più potente e flessibile di Convos, che consente di interrogare le API, eseguire trasformazioni complesse, gestire la logica condizionale e creare messaggi dinamici.


Cosa fa questo nodo?

Ogni volta che viene eseguito, il nodo riceve informazioni dal contesto del dialogo, consentendo allo sviluppatore di accedere a:

  • Dati del contatto.

  • Variabili precedentemente acquisite o definite.

  • Informazioni sulla campagna transazionale.

  • Messaggi in arrivo.

Alla fine del blocco di codice, il nodo deve chiamare la funzione output(), che indica cosa fare successivamente: salvare lo stato, acquisire nuove variabili, inviare messaggi, ecc.


Variabili disponibili

Queste variabili sono disponibili globalmente nello script e rappresentano il contesto del flusso:

Variabile

Descrizione

variables

Oggetto con tutte le variabili precedentemente acquisite nel dialogo, sia dai nodi di acquisizione che generate dal codice.

persisted

Informazioni persistenti da campagne transazionali. Ad esempio: persisted.input.orderId. Utile per continuare i flussi basati sulle campagne.

contact

Informazioni del profilo del contatto. Accessibili tramite contact.phone, contact.firstname, contact.field_1, fino a contact.field_100.

state

Un oggetto che memorizza informazioni di stato tra le esecuzioni dello stesso nodo. Permette di suddividere la logica in fasi (stage).

inboundMessage

Oggetto completo del messaggio ricevuto dal sistema. Contiene metadati, tipo, ecc.

inboundMessageBody

Solo il testo semplice del messaggio in arrivo. Utile per catturare risposte rapide.

Metodi disponibili

output({ state, variables, messages, ticket })

Questo è obbligatorio. Chiude il nodo di codice e consente di:

  • Mantenere un nuovo stato (state) per le future esecuzioni dello stesso nodo.

  • Creare o modificare variabili (variables) accessibili ad altri nodi.

  • Inviare messaggi al contatto (messages).

Esempio:

output({
state: {
stage: 1,
wait: true
},
variables: {
age: inboundMessageBody
},
messages: [
{
type: 'text',
text: {
body: 'Quanti anni hai?'
}
}
],
ticket: {}
});

wait: true indica che il nodo deve essere rieseguito la prossima volta che il contatto risponde.

fetch(url, options)

Consente di effettuare chiamate HTTP sincrone (tipo await fetch). Ideale per utilizzare API esterne e personalizzare il flusso.

Esempio:

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)

Consente di inviare un'email. Ideale per notifiche email o integrazioni.

Esempio:

const html = '<h1>Nuovo registro</h1>';
mail(‘[email protected]’, 'Nuovo registro', html);

Struttura dei messaggi

È possibile inviare solo messaggi interattivi (non template pre-approvati da Meta).

Invio di messaggi facoltativo

L'invio di messaggi all'interno del nodo di codice non è obbligatorio.

È possibile utilizzare questo nodo esclusivamente per eseguire la logica di programmazione, ad esempio:

• Calcolo di variabili complesse.

• Esecuzione di convalide silenziose.

• Interrogazione di API esterne.

• Arricchimento del dialogo con dati prima di continuare.

Questo è particolarmente utile quando non è necessario interagire direttamente con l'utente in quel punto del flusso, ma piuttosto preparare le informazioni per i passaggi successivi.

Esempio senza messaggi:

const risultato = 42;

output({
state: { wait: false },
variables: {
risultato: risultato
}
});

⚠️ Ricorda che anche se non invii messaggi, devi comunque eseguire output() per terminare correttamente il nodo.

Lista dei messaggi interattivi disponibili

Tipo

Struttura

text

{
"type": "text",
"text": {
"body": "Grazie per averci contattato."
}
}

image

{
"type": "image",
"media": {
"link": "https://domain.com/example/image.png",
"caption": "Immagine di esempio",
}
}

contacts

{
"type": "contacts",
"contacts": [
{
"org": {
"title": "Manager",
"company": "Growlat",
"department": "Convos"
},
"name": {
"prefix": null,
"suffix": null,
"lastName": null,
"firstName": "contatto",
"middleName": null,
"formattedName": "contatto"
},
"urls": [
{
"url": "https://help.convos.la/",
"type": "HOME|WORK"
}
],
"emails": [
{
"email": "[email protected]",
"type": "PERSONAL|WORK"
}
],
"phones": [
{
"type": "CELL|MAIN|IPHONE|HOME|WORK",
"waId": null,
"phone": "+541155138711"
}
],
"birthday": "1995-08-18",
"addresses": [
{
"street": "Via Mazzini 158",
"city": "Roma",
"state": "Lazio",
"zip": "00155",
"country": "Italia",
"countryCode": "it",
"type": "HOME|WORK"
}
]
}
]
}

document

{
"type": "document",
"media": {
"link": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
}
}

location

{
"type": "location",
"location": {
"name": "Casa",
"address": "Maipú 2944",
"latitude": "-32.9720076",
"longitude": "-60.6440044"
}
}

buttons

{
"type": "interactive",
"interactive": {
"body": {
"text": "Corpo del pulsante"
},
"type": "button",
"action": {
"buttons": [
{
"id": "si",
"type": "reply",
"title": "Sí"
},
{
"id": "no",
"type": "reply",
"title": "No"
},
{
"id": "quizas",
"type": "reply",
"title": "Forse"
}
]
},
"footer": {
"text": "Footer del uplsante"
},
"header": {
"text": "Encabezado del botón",
"type": "text"
}
}
}

list

{
"type": "interactive",
"interactive": {
"body": {
"text": "Seleziona una opzione"
},
"type": "list",
"action": {
"button": "Opzioni",
"sections": [
{
"rows": [
{
"id": "operatore",
"title": "Operatore",
"description": "Quiero hablar con un humano."
},
{
"id": "mappa",
"title": "Mappa",
"description": "Vorrei conoscere la vostra ubicazione."
},
{
"id": "allegato",
"title": "Allegato",
"description": "Vorrei ricevere un allegato."
},
{
"id": "custom",
"title": "Custom",
"description": "Vorrei eseguire codice Javascript."
},
{
"id": "cattura",
"title": "Cattura",
"description": "Vorrei che raccolgano i miei dati."
},
{
"id": "webhook",
"title": "Webhook",
"description": "Vorrei inviare un webhook."
},
{
"id": "contatto",
"title": "Contatto",
"description": "Vorrei ricevere un contatto."
},
{
"id": "boton",
"title": "Botón",
"description": "Vorrei vedere un messaggio di tipo pulsante."
},
{
"id": "split",
"title": "Split",
"description": "Vorrei un messsaggio con percentuali."
}
],
"title": "Opciones"
}
]
},
"footer": {
"text": "Grazie"
},
"header": {
"text": "Opzioni di aiuto",
"type": "text"
}
}
}

Puoi anche inviare più messaggi:

messages: [
{
type: 'image',
media: { link: 'https://...' }
},
{
type: 'text',
text: { body: 'Gracias por tu compra' }
}
];

Estructura de ticket

Se hai bisogno di creare un ticket dal nodo codice puoi usare la key 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']
}
});

Variabili:

  • inboxId: la variabile inboxId è necessaria per determinare a quale casella di posta assegnare il ticket.

  • tag: la variabile tags è facoltativa e può essere utilizzata per aggiungere automaticamente tag al ticket.

Casi d'uso comuni

Raccolta a stadi

Utilizzando state.stage, è possibile suddividere il flusso in più fasi:

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!' }}]
});
}

Invio di feedback con dati transazionali

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 } });

Ricerca di ordine tramite e-mail 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.' }
}]
});

Procedure consigliate

  • Utilizzare state.wait = true quando il flusso è in attesa di un'altra risposta dall'utente.

  • Evitare di dichiarare una variabile denominata state all'interno del codice (è già riservata).

  • Utilizzare try/catch durante il fetch per evitare errori di runtime.

  • Se si utilizzano dati sensibili, assicurarsi che non vengano esposti nei messaggi al cliente.

  • Utilizzare nomi di variabile chiari e semantici per facilitare la manutenzione del flusso.

  • Utilizzare punti e virgola alla fine di ogni riga di codice per garantirne il corretto funzionamento.

Struttura di base consigliata

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.' }
}]
});
}

Hai ricevuto la risposta alla tua domanda?