https://d226lax1qjow5r.cloudfront.net/blog/blogposts/inbound-voice-call-campaign-tracking-dr/call-tracking-1.png

Seguimiento de campañas de llamadas de voz entrantes con Mixpanel

Publicado el May 18, 2021

Tiempo de lectura: 9 minutos

El seguimiento de campañas es imprescindible para cualquier campaña de marketing o publicidad. Sin la capacidad de realizar un seguimiento preciso del número de usuarios que interactúan con cada anuncio no se puede calcular el coste por adquisición (CPA), por lo que en última instancia no se puede determinar qué campañas tienen éxito y cuáles están haciendo perder dinero a la empresa; CPA mayor que ARPU (ingresos medios por usuario).

Could he be any more asleep?

(Business Intelligence utiliza aún peores acrónimos y jerga que la tecnología).

Dada la enorme cantidad de páginas web con soporte publicitario, no es de extrañar que las herramientas de gestión de campañas online estén ya bastante desarrolladas. Pero cuando queremos hacer un seguimiento de los "clics" de la publicidad impresa u otro tipo de publicidad offline, tenemos que recurrir a URL promocionales únicas o códigos de cupón.

Sin embargo, una vez que el usuario ha introducido nuestra URL promocional o código de cupón, podemos realizar su seguimiento con las mismas herramientas de análisis e inteligencia empresarial de eficacia probada que cualquier otra campaña en línea.

Pero ¿qué pasa con llamadas telefónicas entrantes? Podría decirse que los usuarios que deciden llamar a nuestra empresa ya están más comprometidos con nuestra marca que alguien que simplemente ha hecho clic en un enlace, pero las herramientas existentes para el seguimiento de estas interacciones son propensas a errores o, en el caso de los equipos de gestión de llamadas de las empresas, son prohibitivamente caras.

El seguimiento de llamadas entrantes tiene la misma dificultad que las URL impresas, el salto de lo analógico a lo digital. Necesitamos un punto de entrada único para cada campaña, algo que sea tan barato y fácil de configurar como una URL única, pero que nos permita hacer un seguimiento de nuestras campañas de voz entrantes en nuestra plataforma CRM o BI existente.

Los números virtuales Nexmo son perfectos en esta situación. Son baratos, fáciles de configurar y podemos crear un número virtual único para cada campaña para que podamos rastrear dónde vio el usuario cada número y, en última instancia, qué campaña está proporcionando el mejor ROI (retorno de la inversión). También se pueden comprar números locales en 66 países diferentes para que sean específicos de cada región, y este número no deja de aumentar.

Requisitos

Si desea ejecutar el ejemplo localmente necesitará:

  1. a Mixpanel Accountla versión gratuita es suficiente para este ejemplo

  2. una manera de exponer su aplicación local Flask a la Internet pública. Tiendo a usar ngrok para esto durante el desarrollo

Algunos conocimientos de Python/Flask sería útil, pero no es necesario. El código es bastante sencillo, así que incluso si prefieres Ruby, PHP, JavaScript, etc. deberías ser capaz de seguirlo sin demasiada dificultad.

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.

¿Qué queremos rastrear?

Mindmap showing what elements we want to track

La campaña inbound

Necesitamos saber a qué campaña llamó el usuario. Podemos tener varias campañas diferentes que se ejecutan en diferentes canales, por lo que necesitamos identificar la campaña para que podamos adjuntar cualquier acción del usuario a la misma correctamente.

La persona que llama

Idealmente, nos gustaría saber su nombre, pero esto sólo será sólo es posible en determinados territorios.. Pero utilizando la Number Insight API siempre podremos identificar el tipo de número desde el que llaman, el país en el que se encuentran y la frecuencia de sus llamadas.

Al utilizar su número de teléfono como identificador único, también podemos seguir sus acciones más allá de esta llamada. Si durante el registro en nuestro sitio web capturamos el número de teléfono del usuario, que podemos confirmar con la API de verificación de números.podremos cotejar cualquier acción que realice en el futuro con la llamada que haya hecho a nuestro número virtual.

La llamada

En este ejemplo, sólo vamos a rastrear las llamadas completadas, pero podríamos rastrear los diferentes estados de las llamadas, como tiempo de espera, fallida, rechazada, ocupada. Otra información que debemos registrar es la duración de la llamada y su coste. Con esto, podemos empezar a calcular el coste por adquisición de nuestros nuevos clientes a través de esta campaña.

Seguimiento de campañas de voz entrantes, todo el proceso

process diagram showing the complete call tracking flow

El diagrama de secuencia anterior puede parecer bastante desalentador, pero vayamos por partes.

Contestación de llamadas entrantes

Cuando un usuario marca un número virtual Nexmo, la API Nexmo solicitará un objeto de control de llamada Nexmo (NCCO) desde la URL que le proporcionemos. Este archivo JSON NCCO contendrá una lista de acciones que Nexmo debe ejecutar cada vez que se reciba una llamada.

La primera acción que queremos realizar es transmitir un mp3 a la persona que llama; este archivo de sonido le informará de que podemos grabar la llamada.

[
  {
    "action": "stream", 
    "streamUrl": [
      "https://example.com/audio/calls-recorded.mp3"
    ]
  }
]

Grabación y conexión de la llamada con nuestro agente

En la segunda parte del diagrama de secuencia, comenzamos la grabación de nuestra llamada y luego conectamos a la persona que llama con el agente que gestiona las llamadas de esa campaña.

[
  {
    "action": "stream", 
    "streamUrl": [
      "https://example.com/audio/calls-recorded.mp3"
    ]
  }, 
  {
    "action": "record", 
    "eventUrl": [
      "https://example.com/record/"
    ]
  }
]

La página acción de registro en la OCN es sencilla. Sólo tenemos que especificar la URL que debe recibir una notificación cuando la grabación de la llamada esté disponible. Cuando finalice la llamada, la grabación se detendrá automáticamente.

Conectar la llamada

Al utilizar la acción de conexión, nuestro número de origen debe ser un número virtual de Nexmo. En este caso, utilizaremos el número de la campaña de voz entrante a la que llama el usuario.

[
  {
    "action": "stream", 
    "streamUrl": [
      "https://example.com/audio/calls-recorded.mp3"
    ]
  }, 
  {
    "action": "record", 
    "eventUrl": [
      "https://example.com/record/"
    ]
  }, 
  {
    "action": "connect", 
    "endpoint": [
      {
        "number": "441632960616", 
        "type": "phone"
      }
    ], 
    "from": "441632960277"
  }
]

Puede especificar diferentes tipos de puntos finales a los que conectarse, como un WebSocketpero como queremos hacer una llamada proxy, vamos a usar el tipo "teléfono" y luego el número al que queremos conectarnos.

Creación de nuestra primera vista Flask

En el ejemplo anterior, NCCOs, todos nuestros valores están codificados. Pero en una situación real, muchos de los valores cambiarán dependiendo del número virtual que haya marcado el usuario. En primer lugar, tendremos que identificar la campaña por la que llaman y, a continuación, actualizar la ubicación del archivo mp3 y el número de teléfono del agente entrante.

También hay que considerar el caso de que no tengamos una campaña activa para un número. Tal vez se trate de un anuncio antiguo y la campaña de marketing ya no esté en marcha. Puede que no tengamos agentes disponibles para atender llamadas sobre esta campaña, pero no queremos liberar el número virtual. En nuestro código de ejemplo, utilizaremos la acción acción de texto a voz para informar al usuario de que el número ya no está activo, sin embargo, en su aplicación en vivo podría redirigir al usuario a su centralita principal o realizar otra acción que proporcione una mejor experiencia al usuario.

Veamos primero cómo encontrar la campaña correspondiente.

def get_campaign(number_to):
    Campaign = Query()
    campaigns = db.search(
        (Campaign.inbound_number == number_to) | (Campaign.redirect_number == number_to)
    )
    return campaigns[0] if campaigns else None

@app.route('/')
def answer():
    number_to = request.args.get('to')
    campaign = get_campaign(number_to)

Estamos utilizando tinydb en nuestro ejemplo; es un motor de base de datos simple para Python diseñado para sistemas embebidos. Es perfecto para nuestro ejemplo, ya que se basa en un único archivo plano (JSON) como base de datos, pero puedes cambiarlo fácilmente por SQLAlchemy u otro ORM de tu elección.

Cuando Nexmo solicita nuestra OCN, incluye el número llamado en el formato internacional E.164 como parte de la cadena de consulta. Utilizaremos este número cuando consultemos nuestra base de datos para la campaña correspondiente, por lo que debe asegurarse de utilizar también el formato E.164 cuando guarde la información de su campaña en su base de datos.

Nuestra función get_campaign devolverá la primera campaña que coincida, o si no se encuentra ninguna devolveremos None.

Respondiendo con nuestro objeto de control de llamadas Nexmo

Siempre que hayamos encontrado una campaña que coincida con los pasos anteriores, rellenaremos nuestra OCNC con los datos correctos streamUrl, from y endpoint. Si no encontramos ninguna campaña que coincida, utilizaremos la API de texto a voz y una voz sintetizada para informar al usuario; El número marcado no ha sido reconocido".

if campaign:
    ncco = [
        {
            'action': 'stream',
            'streamUrl': ['https://example.com/{message}'.format(
                message=campaign['welcome_message']
            )]
        },
        {
            'action': 'record',
            'eventUrl': ['https://example.com/record/']
        },
        {
            'action': 'connect',
            'from': campaign['inbound_number'],
            'endpoint': [{
                'type': 'phone',
                'number': campaign['redirect_number']
            }]
        }
    ]
    return jsonify(ncco)
else:
    return jsonify([{
        'action': 'talk',
        'text': 'The number dialled has not been recognised. Please check and try again'
    }])

Seguimiento de la información de las llamadas entrantes

Una vez finalizada la llamada, no sólo terminará la grabación de la llamada, sino que Nexmo activará nuestro webhook con la información pertinente.

Este evento completado, sin embargo, no contendrá información sobre el usuario que realizó la llamada. Para ello, tendremos que utilizar la Number Insight API de Nexmo.

Una vez que tengamos toda la información que necesitamos: sobre qué campaña han llamado, quién ha llamado e información sobre la llamada en sí, almacenaremos esta información en Mixpanel.

En este ejemplo estamos utilizando Mixpanel, pero eso no significa que sólo puedas utilizar Mixpanel. Envía los datos a cualquier herramienta que desees, o a múltiples aplicaciones al mismo tiempo utilizando una herramienta como Segment. No importa si utiliza Mixpanel, KISSmetrics, Periscope, Chartio, Salesforce o incluso un sistema de BI o CRM hecho a medida. Si puede recibir datos, podrá utilizar este mismo enfoque para realizar un seguimiento de sus llamadas entrantes.

@app.route('/event', methods=['POST'])
def callevent():
    event = json.loads(request.data)

    if event['status'] == 'completed':
        campaign = get_campaign(event['to'])

En primer lugar, estamos especificando que este endpoint sólo acepta POST ya que esto es lo que recibiremos de Nexmo. El cuerpo de esta POST será una cadena JSON, por lo que tendremos que convertirla en un objeto Python.

Como se mencionó anteriormente, en este ejemplo sólo estamos interesados en las llamadas que tienen un estado de completado. Existen muchos otros estados que podríamos recibir como ocupado o fallido, y estos estados podrían ser muy importantes de rastrear si, por ejemplo, estuvieras escribiendo un software para rastrear llamadas de soporte entrantes. Pero por ahora, vamos a centrarnos sólo en las llamadas completadas.

También vamos a rastrear únicamente las solicitudes de las campañas existentes. Así que antes de hacer nada, utilizaremos nuestra función get_campaign y comprobaremos que el usuario ha llamado sobre una campaña activa.

Creación de nuestros clientes Mixpanel y Nexmo

Para buscar información sobre nuestro llamante necesitaremos una instancia del cliente API Nexmo para poder utilizar la API Number Insight. Siguiendo la metodología de aplicación de 12 factoreshe creado variables de entorno que contienen mi clave y secreto de la API Nexmo, así como el token de mi proyecto Mixpanel.

mix = Mixpanel(os.environ['MIXPANEL_TOKEN'])
client = nexmo.Client(
    key=os.environ['NEXMO_API_KEY'],
    secret=os.environ['NEXMO_API_SECRET']
)

Recuperación y seguimiento de la información sobre nuestro interlocutor

Vamos a utilizar la API avanzada de Number Insight para obtener toda la información disponible sobre la persona que llama. Esta información incluirá datos como el país desde el que han marcado, el tipo de red y, si está disponible, el nombre de la persona que llama.

Almacenaremos esta información junto con su número de teléfono como identificador único del usuario. De esta manera podemos vincular este evento, y todos los eventos posteriores a la misma cuenta de usuario en Mixpanel. Si ya existe un usuario con ese número de teléfono, en lugar de crear un nuevo perfil de usuario, Mixpanel actualizará su perfil con los datos recibidos de nuestra solicitud de conocimiento del número, garantizando que siempre esté actualizado.

# Fetch people data
insight = client.get_advanced_number_insight(number=event['from'])
uid = event['from']

# Create/Update user in Mixpanel
mix.people_set(
    uid,
    {
        '$phone': '+' + event['from'],
        '$first_name': insight.get('first_name'),
        '$last_name': insight.get('last_name'),
        'Country': insight.get('country_name'),
        'Country Code': insight.get('country_code_iso3'),
        'Valid Number': insight.get('valid_number'),
        'Reachable': insight.get('reachable'),
        'Ported': insight.get('ported'),
        'Roaming': insight.get('roaming').get('status'),
        'Carrier Name': insight.get('current_carrier').get('name'),
        'Network Type': insight.get('current_carrier').get('network_type'),
        'Network Country': insight.get('current_carrier').get('country'),
    }
)

También vamos a utilizar un par de otros métodos de la API de Mixpanel people_track_charge y people_increment. Utilizaremos estos métodos para saber cuánto hemos gastado en atender las llamadas de ese usuario y el número de veces que ha llamado.

# Useful for Mixpanel revenue tracking
mix.people_track_charge(uid, float(data.get('price')) * -1)

# Track number of times user calls
mix.people_increment(uid, {'Number of Calls': 1})

Envío de nuestro evento de llamada entrante a Mixpanel

Por último, vamos a rastrear la llamada en sí. Utilizaremos de nuevo el número de teléfono de la persona que llama como identificador para almacenar el evento con el usuario correcto. También haremos un seguimiento de la campaña por la que llamaron para poder segmentar fácilmente nuestros datos y ver el rendimiento de cada campaña.

# Track call data in Mixpanel
mix.track(
    uid,
    'Inbound Call',
    {
        'Campaign Name': campaign['name'],
        'Duration': int(data.get('duration')),
        'Start Time': data.get('start_time'),
        'End Time': data.get('end_time'),
        'Cost': float(data.get('price'))
    }
)

Pruébelo usted mismo

Todo el código de este artículo está disponible en Github. Utiliza Python, Flask y tinydb. Así que asegúrese de instalar las dependencias en requirements.txt usando pip primero.

También hay un ejemplo campaigns.jsonEste es el archivo utilizado por tinydb. Tendrás que actualizarlo con los valores correctos. Ver la documentación tinydb para saber cómo añadir filas adicionales a su base de datos si desea añadir más de una campaña.

Nexmo application creation screen

También necesitará un número virtual Nexmo y una aplicación de voz configurada. Recientemente hemos lanzado nuestro panel de aplicaciones de vozpuede más información sobre él y sobre cómo crear una nueva aplicación de voz en nuestro blog.

Una vez que tengas todo configurado correctamente puedes ejecutar la aplicación Flask con los siguientes comandos:

export FLASK_APP=app.py
flask run

Si te encuentras con algún error, prueba a activar el modo de depuración en Flask antes de volver a intentarlo. Ah, ¡y no olvides crear las variables de entorno requeridas por los clientes Mixpanel y Nexmo!

export FLASK_DEBUG=1
export MIXPANEL_TOKEN="<YOUR MIXPANEL PROJECT TOKEN>"
export NEXMO_API_KEY="<YOUR NEXMO API KEY>"
export NEXMO_API_SECRET="<YOUR NEXMO API SECRET>"

¿Y ahora qué?

Pruebe a añadir notificaciones por SMS cuando finalice una llamadao cambiar el seguimiento de Mixpanel por Segment. Puede obtener más información sobre la Voice API y la Number Insight API utilizadas en los ejemplos anteriores en nuestro sitio para desarrolladores. Asegúrese también de revisar las otras acciones disponibles en las OCN.

Compartir:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Aaron BassettAntiguos alumnos de Vonage

Aaron era un defensor de los desarrolladores en Nexmo. Ingeniero de software experimentado y aspirante a artista digital, Aaron suele crear cosas con código o electrónica; a veces ambas cosas. Cuando está trabajando en algo nuevo, suele percibir el olor a componentes quemados en el aire.