Captación de leads

Nivel : Básico/ Integración privada sin widget

Introducción

Este tutorial ayudará a los principiantes a entender cómo construir una aplicación. Encontrarás respuestas a tus preguntas sobre:

  • las entidades de Kommo y cómo interactúan entre sí

  • la creación de una integración privada

  • la autorización

  • cómo probar una aplicación

  • la información básica de la API de Kommo

Es importante tener en cuenta que no te enseñaremos programación general ni desarrollo backend, sino a comprender Kommo y crear integraciones que resuelvan los problemas de los clientes sin causar ningún daño.

Solicitud de un cliente

Imaginemos que recibes una solicitud de un cliente. Ellos tienen una escuela de idiomas en línea para niños, y su equipo no es muy grande. El equipo está compuesto por un gerente de la escuela, gerentes de ventas, maestros y asistentes de maestros. Tienen un sitio web con un formulario a través del cual generan leads (los potenciales clientes completan el formulario para inscribirse en clases).

Por algún motivo, no pueden utilizar las integraciones de formularios existentes. Necesitan una solución que recoja todos los leads y los importe a su cuenta de Kommo.

Entonces, le dices a tu cliente que la mejor manera de resolver su problema es crear una integración privada.

Guía paso a paso

Aquí puedes encontrar una guía sobre cómo construir una aplicación en la cuenta de un cliente.

1. Obtener la información de la cuenta

Para crear una solución funcional, deberás realizar solicitudes a la API de Kommo.

Para solicitar una cuenta, debes incluir el subdominio de la cuenta en la URL.

Por ejemplo,

https://littletreeschool.kommo.com/api/v4/lead

Puedes iniciar sesión en tu cuenta y encontrar el subdominio de la cuenta en la URL.

2. Crea una integración privada

📘

Una integración privada existe solo en una cuenta. Si se crea en una cuenta, no tendrá acceso a otras cuentas.

Entonces, una integración privada debe ser creada en la cuenta en la cual se utilizará, es decir, en la cuenta de tu cliente.

No necesitas una cuenta técnica para comenzar a desarrollar integraciones privadas.

Para crear una integración privada, debes dirigirte al Menú lateralAjustesIntegración → botón Crear integración en la esquina superior derecha.

Luego, estarás a un clic de una integración privada.

3. Autorización

Existen dos tipos de autorización:

OAuth 2.0 es más complicado. No nos centraremos en él en este tutorial.

Se utilizará un token de larga duración para la integración en la que estamos trabajando.

Abre una integración que se haya creado en un paso anterior y haz clic en la pestaña Llaves y alcances.

El único elemento que utilizarás es el token de larga duración.

Click "Generate long-lived token"

Haz clic en "Generar token de larga duración"

Cómo puedes obtener este token:

  • Puedes obtener este token tú mismo si el administrador de la cuenta te otorga esos derechos (derechos de administrador). Luego, generas el token y lo guardas en un lugar seguro. Si el administrador de la cuenta simplemente te quita los derechos de administrador, aún podrás utilizar el token. Si ya no desean que tengas acceso a su cuenta a través de la integración, también deberán revocar el acceso en la pestaña Autorización .

  • Un administrador de la cuenta puede crear una integración por sí mismo, generar un token de larga duración y compartirlo contigo.

🚧

¡Guarda tu token de larga duración en un lugar seguro!

4. ¿Existe un entorno de pruebas?

Cuando creas una integración en la cuenta de un cliente, siempre existe el riesgo de que algo salga mal y afecte los datos en la cuenta (si tu aplicación no es solo de lectura).

Lo mejor que puedes hacer para crear un buen producto (tu aplicación) es practicar en un entorno de pruebas.

Una cuenta de prueba puede convertirse en un entorno de pruebas, ya que no tiene las limitaciones de una cuenta técnica.

Para crear otra cuenta de prueba, ve a kommo.com, haz clic Ir a tu cuenta in the top right corner → Crear una nueva cuenta. ¡No olvides que solo dura 14 días!

5. Conceptos básicos de solicitudes y respuestas

Una vez que hayas completado los pasos anteriores, es hora de aprender los conceptos básicos sobre solicitudes y respuestas.

Métodos

Utiliza el formato JSON para las solicitudes a la API.

Debes realizar todas las solicitudes a la API a través del punto de enlace seguro (HTTPS).

La API de Kommo utiliza los siguientes verbos HTTP:

MétodoDescripción
GETSolicitar datos al servidor.
POSTCrear nuevos datos en el servidor.
PATCHActualizar datos existentes en el servidor.
DELETEEliminar datos del servidor.

Por ejemplo, la solicitud POST /api/v4/leads on los datos correspondientes en el cuerpo de la solicitud agregará un lead a la cuenta.

Límites

Hay un límite en la cantidad de llamadas API por segundo que puedes realizar. Este límite se aplica a la dirección IP que se utiliza para hacer las llamadas.

❗️

No debes realizar más de 7 solicitudes por segundo.

¿Qué sucede si superas el límite?

Si envías demasiadas solicitudes en un corto período de tiempo, recibirás el código de estado HTTP 429 Too Many Requests.

Si las restricciones se infringen varias veces, tu dirección IP será bloqueada y se devolverá el código de estado HTTP 403 Forbidden para cualquier solicitud.

6. ¿Qué hago con el subdominio y el token?

Entonces tienes tu subdominio y tu token, pero no está claro cuál es el lugar correcto para usarlos.

Este es un ejemplo de una solicitud GET. Pasa tu subdominio como valor de la variable SUBDOMINio y tu token de larga duración como valor de la variable CLAVE_API.

import requests

SUBDOMINIO = ''
CLAVE_API = ''


GET_LEAD_URL = f'{SUBDOMINIO}.kommo.com/api/v4/leads'

headers = {
    'Authorization' : f'Bearer {CLAVE_API}',
    'Content-Type': 'application/json'
}

requests.get(GET_LEAD_URL, headers=headers)

También hay una receta que podría ayudarte con esto:

Si deseas usar nuestras referencias de la API para practicar, es aún más fácil.

7. Diagrama entidad-relación y por qué lo necesitamos

Un diagrama entidad-relación (ERD), también conocido como modelo entidad-relación, es una representación gráfica que muestra las relaciones entre personas, objetos, lugares, conceptos o eventos dentro de un sistema de tecnología de la información (TI).

Account ERD

El diagrama ERD nos puede ayudar a describir el negocio de un cliente en términos que se utilizan en el CRM de Kommo.

El cliente que mencionamos al principio tiene una escuela en línea para jóvenes aprendices.

Entonces podemos decir que

  • la entidad Cuenta representa la escuela.
  • los Usuarios representan a los gerentes de ventas.
  • la entidad Lead representa a un estudiante (como son muy jóvenes, los Contactos son sus padres).
  • las Etiquetas son esenciales porque ayudan a los gerentes de ventas a ubicar correctamente a los estudiantes en grupos para las clases.
  • existen Campos personalizados como la Edad que también ayudan a asignarlos adecuadamente.
  • hay diferentesPipelines para los diferentes idiomas.
  • las Etapas muestran el estado de un lead dentro de un canal (si el estudiante está agendado para una clase demostrativa o está a punto de firmar un contrato).

8. Añadir un lead

Una escuela puede funcionar y tener sentido si hay estudiantes. Los estudiantes están representados por leads en el CRM de Kommo, por lo que comenzaremos con una acción como la adición de un lead.

Puedes crear un lead con una simple solicitud POST incluso con solo un parámetro en el cuerpohttps://{YOUR_SUBDOMAIN}.kommo.com/api/v4/leads.

Sin embargo, debemos tener en cuenta que esos leads se importarán desde un formulario completado en el sitio web de la escuela, por lo que contendrán más información que solo el nombre de un estudiante.

Primero, echemos un vistazo a los parámetros del cuerpo del método.

[
    {
        "name": "Ana Castro",
        "pipeline_id": 8244687,
        "status_id": 65625139,
        "responsible_user_id": 10618939,
        "custom_fields_values": [
            {
                "field_id": 1551478,
                "values": [
                    {
                        "value": 7
                    }
                ]
            }
        ]
    }
]
  • name - es el nombre del estudiante que proviene del formulario.

  • pipeline_id- es el ID de un pipeline al que se añadirá el lead. Puedes obtener una lista de pipelines y establecer uno por defecto, ya que todos los leads provienen del mismo formulario.

  • status_id - puedes obtener una lista de etapas y elegir una etapa para todos estos leads.

  • responsible_user_id- puedes obtener una lista de usuarios, ordenarlos por grupo (equipo de ventas) y escribir tu lógica para la distribución de leads entre los gerentes de ventas.

  • custom_fields_values - puedes pasar información adicional del formulario, como la edad del estudiante. Para hacerlo, necesitas conocer los ID de los campos personalizados. Puedes obtener una lista de campos personalizados de leads y elegir el que necesites.

Or you can go to a **lead card** → **Setup **→ your custom field → copy the ID

O puedes ir a una tarjeta de leadConfigurar → tu campo personalizado → copia el ID

🚧

Ten en cuenta que los ID de campos personalizados/pipelines/etapas no son universales. Si intentas enviar el cuerpo de la solicitud del ejemplo anterior, recibirás el código de estado HTTP 400 porque un campo personalizado/pipeline/etapa con ese ID no existe en tu cuenta.

9. Control de duplicados

El control de duplicados es la capacidad de una aplicación para verificar las instancias de entidades que se añaden y asegurarse de que no haya duplicados.

Vamos a revisar un fragmento de código que verifica si un contacto del lead es nuevo o ya existe en la cuenta.

Puedes verificar duplicados en cualquier entidad, solo ten en cuenta que las capacidades de filtrado son limitadas y, en algunos casos, deberás utilizar el parámetro query para buscar una instancia de la entidad que necesitas.

Lenguaje del fragmento de código - Python

Definir variables de la cuenta

# Pon el subdominio de tu cuenta aquí
SUBDOMINIO = ''

# Pon tu token de larga duración o token de acceso aquí
CLAVE_API = ''

Aquí debemos definir las variables que utilizaremos más adelante en el fragmento. Son SUBDOMINIO (el subdominio de tu cuenta) y CLAVE_API (es tu token de larga duración o tu token de acceso).

Define las variables de la URL

URL_BASE_LEAD = f"https://{SUBDOMINIO}.kommo.com/api/v4/leads/complex"
URL_BASE_CONTACTO = f"https://{SUBDOMINIO}.kommo.com/api/v4/contacts"
URL_BASE_CAMPOPERSONALIZADO_CONTACTO = f"https://{SUBDOMINIO}.kommo.com/api/v4/contacts/custom_fields"

Definimos las variables que utilizaremos más adelante en el código.

URL_BASE_LEAD se utilizarán para añadir leads con contactos y empresas.

URL_BASE_CONTACTO se utilizará para obtener una lista de contactos.

URL_BASE_CAMPOPERSONALIZADO_CONTACTO se utilizará para obtener una lista de campos personalizados de contactos.

Verificar contactos existentes

nuevoNumeroDeTelefonoDeContacto = '+18305803077'

params = {
	'query' : nuevoNumeroDeTelefonoDeContacto
}

response = requests.get(URL_BASE_CONTACTO, params=params, headers=headers)

Aquí obtenemos un número de teléfono (+18305803077) y lo añadimos como clave al valor de 'query'.

Luego obtenemos una respuesta de una solicitud GET con un parámetro de consulta.

Obtienes el código de estado HTTP 204 (Sin contenido)

if (response.status_code == 204):
    response = requests.get(URL_BASE_CAMPOPERSONALIZADO_CONTACTO, params=params, headers=headers)
    respuestaCamposPersonalizadosDeContacto = response.json()
    print(respuestaCamposPersonalizadosDeContacto)

Si recibes el código HTTP 204 (Sin contenido), significa que no existe un contacto con ese número.
Lo primero que hacemos es enviar una solicitud GET para obtener los campos personalizados del contacto y guardar la respuesta comorespuestaCamposPersonalizadosDeContacto.

    camposPersonalizadosDeContacto = respuestaCamposPersonalizadosDeContacto["_embedded"]['custom_fields']

    idCampoTelefono = ''
    for field in camposPersonalizadosDeContacto:
      if (field['code'] == 'PHONE'):
         idCampoTelefono = field['id']
         break

De respuestaCamposPersonalizadosDeContacto solo necesitamos un arreglo de objetos de campos personalizados, por lo que guardamos el arreglo como camposPersonalizadosDeContacto.

Declaramos una variable llamada idCampoTelefono y le asignamos un valor inicial de cadena vacía. Es importante hacer esto para evitar perder datos en el siguiente bucle for . Cada contacto puede tener múltiples campos personalizados, pero esta variable almacenará específicamente el ID del campo personalizado de número de teléfono.

El bucle for itera a través de cada objeto (field) en el arreglo camposPersonalizadosDeContacto y verifica si el valor de 'code' en field es igual a 'PHONE'. Si es verdadero, el id de ese field se guarda en idCampoTelefono, y el bucle se detiene.


    body = [{
        'name': "Ejemlo lead 1",
        '_embedded': {
                "contacts" : [
                    {
                        "name" : "Nuevo contacto",
                        "custom_fields_values" : [{
                           "field_id": idCampoTelefono,
                           "values": [
                                {
                                    "value": nuevoNumeroDeTelefonoDeContacto
                                }
                            ]
                        }]
                    }
                ]
            }
        }]


    respuestaNuevoLead = requests.post(URL_BASE_LEAD, json=body, headers=headers).json()

    print(respuestaNuevoLead)

Luego, necesitamos crear el cuerpo de la solicitud. Dado que es una adición compleja del lead, no solo agregamos los datos del lead, sino también los datos del contacto. EstablecemosidCampoTelefono como el ID del campo personalizado del nuevo contacto y agregamos nuevoNumeroDeTelefonoDeContacto como su valor.

Finalmente, enviamos una solicitud POST para añadir el lead.

Existe un contacto con ese número

Estamos asumiendo que solo hay un contacto asociado con el número de teléfono proporcionado. Sin embargo, si anteriormente no has verificado los leads duplicados o si el número de teléfono está asociado con una compañía, es posible que se muestren varios contactos.

Two contacts with such a phone number already exist

Ya existen dos contactos con ese número de teléfono.

else:
    respuestaContactosExistentes = response.json()
    contactosExistentes = respuestaContactosExistentes["_embedded"]['contacts']

Si hay un contacto con ese número, obtendremos un cuerpo de respuesta y guardaremos el arreglo de contactos como contactosExistentes. Si hay varios contactos con el mismo número de teléfono, habrá varios objetos en el arreglo. Debido a la forma en que funciona el filtrado, todos los resultados relevantes para la consulta se mostrarán.

    def encontrarContactoDuplicado(contacts, query) -> str:
    	for contact in contacts:
       	camposPersonalizadosDeContacto = contact['custom_fields_values']
       
       	if (camposPersonalizadosDeContacto):
           	 for campoPersonalizado in camposPersonalizadosDeContacto:
               	 values = campoPersonalizado['values']
                	if (values):
                    	for value in values:    
                       	 data = value['value']
                       	 if (data == query):
                            	return contact['id']
      return ''

Luego, necesitamos declarar una función encontrarContactoDuplicado que devolverá el ID del contacto que encontramos.

Veamos más de cerca lo que hace.

El bucle for recorre todos los elementos del arreglo contacts y establece solo el arreglo 'custom_fields_values' del contacto como una variable camposPersonalizadosDeContacto.

Si camposPersonalizadosDeContacto existe y no es null, utilizamos otro bucle for para recorrer todos los objetos de los campos personalizados. Si uno de los valores de custom_fields_values['values']['value'] es igual a la consulta que pasamos a la función, la función devuelve el ID del contacto. Parece un poco complicado, pero repasemos cómo se ve custom_fields_values.

"custom_fields_values": [  
          {  
            "field_id": 1698052,  
            "field_name": "Phone",  
            "field_code": "PHONE",  
            "field_type": "multitext",  
            "values": [  
              {  
                "value": "+18305803077",  
                "enum_id": 1037745,  
                "enum_code": "MOB"  
              }  
            ]  
          }  
        ]

... y deberíamos regresar al Control de duplicados.

idDeContactoDuplicado = encontrarContactoDuplicado(contactosExistentes, nuevoNumeroDeTelefonoDeContacto)

Llamamos a encontrarContactoDuplicadoy pasamos una lista de contactos y el número de teléfono, guardando el resultado como idDeContactoDuplicado.

    body = [{
        'name': "Ejemplo lead 1",
        '_embedded': {
                "contacts" : [
                    {
                        "id" : idDeContactoDuplicado
                    }
                ]
            }
        }]


    respuestaNuevoLead = requests.post(URL_BASE_LEAD, json=body, headers=headers).json()

    print(respuestaNuevoLead)

Luego, creamos el cuerpo de la solicitud, configuramos idDeContactoDuplicado como el ID del contacto y enviamos una solicitud POST para añadir el lead con el contacto.

Puedes encontrar el código completo en la receta Crear un lead con un contacto con control de duplicados.

10. Incluir UTMs

Un módulo de seguimiento Urchin (UTM) es un fragmento de código añadido a una URL con el propósito de rastrear el rendimiento del marketing en línea y comprender mejor el comportamiento de la audiencia. Estas URL personalizadas, conocidas como códigos UTM, proporcionan a los especialistas en marketing información detallada sobre cómo está funcionando una campaña, pieza de contenido o canal específico.

👍

Los campos personalizados UTM se crean automáticamente con la cuenta.

Puedes encontrarlos en la sección de Estadísticas de la tarjeta de un lead.

Definir variables

import requests
from urllib import parse

SUBDOMINIO= ''
CLAVE_API = ''

URL_BASE_LEAD = f'https://{SUBDOMINIO}.kommo.com/api/v4/leads'
URL_BASE_CAMPOPERSONALIZADO_CONTACTO = f'https://{SUBDOMINIO}.kommo.com/api/v4/leads/custom_fields'

headers = {
    'Authorization': f'Bearer {CLAVE_API}',
    'Content-Type': 'application/json'
}

SUBDOMINIO es el subdominio de tu cuenta.

CLAVE_API es tu token de larga duración o token de acceso.

URL_BASE_LEAD se utilizará para añadir leads.

URL_BASE_CAMPOPERSONALIZADO_CONTACTO se utilizará para obtener una lista de los campos personalizados de los contactos.

Crear una URL con UTMs

URL_UTM  = 'https://YOUR_WEBSITE.com/?utm_source=google&utm_medium=cpc&utm_campaign=form&utm_content=youtube&utm_term=utm'

URL_UTM es un ejemplo de una URL que contiene UTMs.

Si lo observamos, podemos aprender que el valor de utm_source es google y el valor de utm_campaign es form.

Puedes utilizar una herramienta gratuita como https://tilda.cc/utm/ para crear una URL con UTMs.

Parsear la URL

def parseURL(url) -> dict:
    return parse.parse_qs(parse.urlparse(url.lower()).query)

utms = parseURL(UTM_URL)

Primero, debemos definir una función (ParseURL) que tome una URL como argumento y devuelva un objeto.

Si parseas la [UTM_URL], devolverá {'utm_source': ['google'], 'utm_medium': ['cpc'], 'utm_campaign': ['form'], 'utm_content': ['youtube'], 'utm_term': ['utm']}.

Obtener una lista de campos personalizados

response = requests.get(URL_BASE_CAMPOPERSONALIZADO_LEAD, headers=headers)
respuestaCamposPersonalizadosDelLead= response.json()
print(respuestaCamposPersonalizadosDelLead)

customFields = respuestaCamposPersonalizadosDelLead['_embedded']['custom_fields']

Enviamos una respuesta GET para obtener una lista de campos personalizados para la entidad de lead. Solo necesitamos el arreglo de campos personalizados de la respuesta, por lo que lo guardamos como camposPersonalizado.

Cambiar el formato de los campos UTM

cuerpoCamposPersonalizadosDelLead = []

for customField in customFields:
    if (customField['type'] == 'tracking_data'):
        clave = customField['code']

        valorUtm = utms.get(clave.lower())

        if (utmValue):
            cuerpoCamposPersonalizadosDelLead.append(
                {
                    'field_id' : customField['id'],
                    'values' : [
                        {
                            'value' : valorUtm[0]
                        }
                    ]
                }
            )

Utilizamos un bucle FOR para crear un arreglo cuerpoCamposPersonalizadosDelLead de objetos.
Veamos más de cerca qué es lo que hace exactamente.

El bucle revisa cada elemento del arreglo de campos personalizados y determina si el tipo de campo personalizado es 'tracking_data'. Si es así, declara una variable clave con el valor customField["code"].

Si miramos utms.get(key.lower()), vemos que devuelve el valor de una clave de utms que es igual a la variable clave pero en minúsculas.

Luego declara valorUtm con el valor de esa clave.

Luego agrega un objeto con un field_id y su value a cuerpoCamposPersonalizadosDelLead.

Crear un lead con UTMs

body = [{
        "name": "Miguel Torres",
        "status_id": 2343875,
        "pipeline_id": 5347887,
        "created_by": 10618939,
        "responsible_user_id": 10618939,
        "_embedded": { 
          "tags": [
                {
                    "id": 2936577,
                    "name": "Grado_2"
                },
            		{
                    "id": 2943611,
                    "name": "9_años"
                }
          ] 
         },
  			'custom_fields_values' : cuerpoCamposPersonalizadosDelLead
    }]

nuevaRespuestaLead = requests.post(URL_BASE_LEAD, json=body, headers=headers).json()
print(nuevaRespuestaLead)

Finalmente, creamos el cuerpo de nuestro futuro lead, donde agregamos leadCustomFieldsBodya la clave custom_fields_valuesy lo enviamos con la solicitud POST.

Puedes encontrar el código completo en Agregar un lead con UTMs.