PearlPBX2
← Todas las publicaciones

Retener al cliente en línea: espera útil en Asterisk

El cliente marca tu número, oye los tonos y espera. Uno, dos, tres. Hacia el cuarto, muchos cuelgan, porque desde su lado es igual que si nadie contestara. Mientras tanto, tus operadores pueden estar libres y a punto de descolgar, pero la llamada ya está perdida.

La culpa no es del cliente: los tonos no le dicen nada. Así que, en lugar de tonos, hay que darle algo útil y dejarle claro qué está pasando. Aquí vemos cómo hacerlo en Asterisk, con ejemplos de dialplan en AEL para PearlPBX2.

La idea

El cliente oye algo útil desde el primer segundo, y a los operadores se les llama al mismo tiempo, no cuando el mensaje termina. Para lograrlo no se pone un Playback aparte antes de la cola: el saludo y las frases útiles van como primeros archivos de la clase de música en espera. El dialplan contesta la llamada y la pasa directamente a Queue:

&call_limit();
NoOp(CALL BEGIN >>>> :'${CALLERID(name)}'@<${CALLERID(num)}>);
Set(CHANNEL(language)=es);
Set(TIMEOUT(absolute)=3600);
if (${LEN(${CALLERID(name)})} > 7) {
    Set(CALLERID(num)=${CALLERID(name)});
}
&callerid_normalization();
AGI(agi://127.0.0.1:4573/blacklist,${CALLERID(num)});
if ( ${BLACKLISTED} > 0) {
    Hangup(17);
}
AGI(agi://127.0.0.1:4573/whitelist,${CALLERID(num)});
if ( ${WHITELISTED} > 0) {
    Set(QUEUE_PRIO=10);
}
AGI(agi://127.0.0.1:4573/mixmonitor,${CALLERID(num)},${EXTEN});
&lc_partday();
Set(CHANNEL(musicclass)=my_moh_class_${PARTDAY});
Answer();
Wait(1);
Queue(support,tT,,,90,crm_integration_agi.py);
NoOp("QUEUESTATUS=${QUEUESTATUS}");
if ("${QUEUESTATUS}" = "TIMEOUT") {
    Playback(all_operators_busy);
}
Hangup();

Fíjate en el final del script. Entre Answer() y Queue() no hay ningún Playback, solo una pausa de un segundo. El saludo suena dentro de la música en espera, así que el cliente lo escucha mientras Asterisk ya está llamando a los operadores. Si hay un operador libre, la conversación empieza sin perder un segundo. Si no hay ninguno, el cliente oye algo útil en lugar de tonos vacíos.

Todo lo que va antes de la cola son filtros:

  • &call_limit() y &callerid_normalization() son macros del editor de dialplan: un límite de llamadas y la normalización del número del llamante.
  • blacklist rechaza a los llamantes no deseados antes de contestar, y whitelist sube la prioridad en la cola (QUEUE_PRIO=10).
  • mixmonitor activa la grabación según las reglas configuradas en el administrador.
  • &lc_partday() fija PARTDAY (morning, day, evening, night), que determina la clase de música.

Después de Queue, el script registra QUEUESTATUS en el log. Si nadie contestó en 90 segundos (TIMEOUT), el cliente oye all_operators_busy antes de que termine la llamada.

Cómo montar la clase de música

La clase my_moh_class_morning (y lo mismo para _day, _evening, _night) se crea en el administrador en modo Files con orden Alpha. Los archivos se nombran de modo que la frase útil vaya primera por orden alfabético:

01_greeting.wav
02_music_1.wav
03_music_2.wav

Así cada cliente empieza por 01_ y no por un punto aleatorio de la lista. Una clase fijada con CHANNEL(musicclass) tiene prioridad sobre la clase de la propia cola: el musiconhold.conf que genera PearlPBX2 incluye preferchannelclass=yes. Por eso una sola cola puede atender cualquier número de clases, y es el dialplan quien elige.

En el primer archivo conviene decir que el cliente ha llegado al sitio correcto, que los operadores están atendiendo y que la respuesta llegará pronto. Los escenarios siguientes completan este básico.

Por qué los tonos pierden

Los tonos le dicen al cliente una sola cosa: la línea está libre y nadie ha descolgado todavía. No puede saber cuánto esperar, si hay alguien al otro lado o si se ha equivocado de número. Así que decide a ciegas si sigue esperando, y cuanto más largo es el silencio, más a menudo la respuesta es no.

Cuando contestas la llamada (Answer), ya puedes hablar con el cliente. Eso no pone a ningún operador en la línea, pero el cliente te oye a ti en lugar de silencio.

Paso 1. La variante simple: una frase antes de la cola

Si prefieres no tocar la clase de música, hay una versión mínima: contestar, hacer una pausa breve, decir una frase y poner la llamada en cola. El inconveniente es que la frase suena antes de que empiece la llamada a los operadores, y cada segundo suyo es un segundo en que nadie está sonando. Mantenla corta.

Set(CHANNEL(language)=es);
Answer();
Wait(1);
Playback(welcome-hold);
Queue(Support,tT,,,90);
Playback(sorry-call-later);
Hangup();

Wait(1) evita que se pierda el inicio de la frase mientras se asienta la conexión. welcome-hold es tu propia grabación de la biblioteca de sonidos del administrador, sin extensión. La frase debe decirle al cliente si ha llegado al sitio correcto, qué va a pasar y si merece la pena esperar. Por ejemplo: «Ha llamado a soporte. Todos los operadores están atendiendo ahora mismo y responderemos en un minuto. Por favor, no cuelgue».

En Queue(Support,tT,,,90) el quinto argumento es el tiempo de espera en segundos. Si nadie contesta en 90 segundos, Queue devuelve el control al dialplan, y el último Playback le pide al cliente que llame más tarde en lugar de dejarlo en silencio.

Paso 2. Dar información mientras espera

Los ajustes de cola de PearlPBX2 ya cubren esto, y no hace falta código en el dialplan:

  • La posición en la cola (announce_position) y el tiempo estimado (announce_holdtime): el cliente oye que es el tercero y que debe esperar unos dos minutos. La duda de «¿hay alguien ahí?» desaparece.
  • Un anuncio periódico (periodic_announce junto con periodic_announce_frequency): una lista de archivos separados por comas que se reproduce con la frecuencia indicada. Sirve lo que los clientes le preguntan igualmente al operador: horario, dirección del sitio web, dónde consultar el estado de un pedido.
  • Música en espera según la hora del día: la clase se elige con CHANNEL(musicclass), y también puede llevar información. Cómo integrar el saludo en la música para que suene mientras ya se llama a los operadores se explica en otro artículo sobre llamadas entrantes en cola.

Todo esto se configura en el formulario de la cola, en el administrador. Qué activar depende de tu flujo de llamadas. Dos o tres frases cortas funcionan mejor que una larga.

Paso 3. No poner en cola a ciegas

Si todos los operadores están ocupados y ya hay varias personas esperando, es más honesto decirlo desde el principio y ofrecer una salida. El servidor FastAGI de PearlPBX2 tiene para esto el manejador queue-status, que fija READYTORECEIVE (cuántos operadores están disponibles) y QUEUECALLERS (cuántos clientes ya esperan).

Answer();
Wait(1);
AGI(agi://127.0.0.1:4573/queue-status,Support);
if (${READYTORECEIVE} > 0) {
    Playback(welcome-hold);
    Queue(Support,tT,,,90);
} else {
    Playback(all-busy-wait);
    Queue(Support,tT,,,120);
}

El manejador toma los datos de Redis, donde los escribe el servicio del panel. Si el panel no está en marcha o Redis no está disponible, consulta AMI directamente.

Las ramas se distinguen por la frase. Cuando hay un operador libre, basta una frase corta y la llamada se conecta en segundos. Cuando no hay ninguno, la frase debe avisar con franqueza de la espera.

Paso 4. Ofrecer una devolución de llamada en lugar de espera

Lo mejor es no hacer esperar en absoluto. El manejador add-callback guarda una solicitud de devolución de llamada en la base de datos, y el demonio de devolución llama al cliente a través de AMI. El cliente pulsa una tecla y cuelga.

Answer();
Wait(1);
AGI(agi://127.0.0.1:4573/queue-status,Support);
if (${READYTORECEIVE} > 0) {
    Playback(welcome-hold);
    Queue(Support,tT,,,90);
} else {
    Read(CALLBACK_CHOICE,busy-offer-callback,1,,1,5);
    if ("${CALLBACK_CHOICE}" = "1") {
        AGI(agi://127.0.0.1:4573/add-callback,${CALLERID(num)},${EXTEN},Support,30);
        if (${CALLBACK_ADDED} = 1) {
            Playback(callback-scheduled);
            Hangup();
        }
    }
    Playback(welcome-hold);
    Queue(Support,tT,,,120);
}
Playback(sorry-call-later);
Hangup();

Qué ocurre aquí:

  • Read reproduce una grabación del tipo «Todos los operadores están ocupados, pulse 1 y le devolveremos la llamada» y espera una tecla hasta cinco segundos. El valor queda en CALLBACK_CHOICE.
  • La variable va entre comillas en la comparación. Si el cliente no pulsa nada, la variable queda vacía, y sin comillas la expresión ${CALLBACK_CHOICE} = 1 se convierte en un error de sintaxis para Asterisk.
  • Los argumentos de add-callback son el número del cliente, el número marcado, el nombre del servicio de devolución y el retraso en segundos. Debe existir un servicio con ese nombre en la configuración de devoluciones.
  • CALLBACK_ADDED vale 1 si la solicitud se guardó. Solo entonces el cliente oye «le devolveremos la llamada» y la llamada termina. Si no, entra en la cola como antes.

Si el cliente no pulsa nada, no pierde nada: entra en la cola con el mismo tiempo de espera.

Paso 5. Qué hacer tras el tiempo de espera

Cuando Queue devuelve el control, el motivo está en ${QUEUESTATUS} (por ejemplo TIMEOUT). El Playback(sorry-call-later) final del script anterior es el mínimo. La oferta de devolución de llamada se puede repetir aquí, en el mismo bloque, para que quien esperó dos minutos no se vaya con las manos vacías.

Qué aporta esto

Nada de esto añade operadores, pero cambia lo que le ocurre al cliente en esos mismos segundos. Oye una voz de inmediato y sabe que ha llegado al sitio correcto. Sabe más o menos cuánto esperar. Y si no quiere esperar, tiene una salida.

En PearlPBX2 esto se arma con piezas que ya existen: el editor de dialplan con validación antes de aplicar, los manejadores FastAGI queue-status y add-callback, el demonio de devolución de llamadas y los ajustes de anuncios de la cola. El panel muestra cuántos clientes esperan ahora mismo en una cola, y los informes muestran las llamadas perdidas.