Acciones de workflow de código personalizado

En los workflows, usa la acción Código personalizado para escribir y ejecutar JavaScript o Python (en versión beta). Con acciones de código personalizado, puedes extender la funcionalidad de workflow dentro y fuera de HubSpot. Para obtener más información sobre las API de HubSpot, puedes consultar la documentación para desarrolladores de las últimas versiones o la documentación para desarrolladores heredada de nuestras API más antiguas. Para ver ejemplos de acciones de código personalizado comunes, consulta el Catálogo de ejemplos de uso de automatización programable de HubSpot.

Las acciones de código personalizado admiten JavaScript que use el marco de tiempo de ejecución Node 16.x. Si estás usando Python para tu acción de código personalizado, la acción de código personalizado usará el marco de tiempo de ejecución de Python 3.9. Cuando se ejecuta una acción, el cálculo de tiempo de ejecución se administra a través de una función sin servidor por HubSpot y AWS Lambda.

Si encuentras algún problema general para implementar tu acción de código personalizado, puedes ponerte en contacto con asistencia técnica de HubSpot. Sin embargo, si tienes algún problema con tu código personalizado escrito, te recomendamos que busques y escribas una publicación en el Foro para desarrolladores de HubSpot para obtener consejos, sugerencias o ayuda con la solución de problemas de tu código.

Bibliotecas compatibles con Node.js

Si estás usando Node.js, las siguientes bibliotecas están disponibles para usarse dentro de la acción de código. Estas bibliotecas se pueden cargar usando la función normal require()  en la parte superior de tu código.

  • @hubspot/api-client ^10
  • async ^3.2.0
  • aws-sdk ^2.744.0
  • axios ^1.2.0
  • lodash ^4.17.20
  • mongoose ^6.8.0
  • mysql ^2.18.1
  • redis" ^4.5.1
  • request" ^2.88.2
  • bluebird ^3.7.2
  • random-number-csprng ^1.0.2
  • googleapis ^67.0.0
Nota: la API de asociaciones v4 es compatible con la versión 9.0.0 o posterior del cliente NodeJS HubSpot y en la versión 8 del cliente NodeJS HubSpot.
 

Bibliotecas compatibles con Python

Si usas Python, puedes cargar las siguientes bibliotecas con una declaración de importación en la parte superior de tu código. La declaración de importación debe formatearse como from [libraryname] import [item], tal como from redis.client import redis.

  • requests 2.28.2
  • @hubspot/api-client ^8
  • google-api-python-client 2.74.0
  • mysql-connector-python 8.0.32
  • redis 4.4.2
  • nltk 3.8.1

Si usas algo de la biblioteca estándar, puedes usar import, como import os.

Get started

Usa los ejemplos de código a continuación para comenzar a usar acciones de workflow de código personalizadas. 

Code samples

NODE16X, v8
const hubspot = require('@hubspot/api-client'); exports.main = async (event, callback) => { /***** How to use secrets Secrets are a way for you to save API keys or private apps and set them as a variable to use anywhere in your code Each secret needs to be defined like the example below *****/ const hubspotClient = new hubspot.Client({ accessToken: process.env.SECRET_NAME }); let phone; try { const ApiResponse = await hubspotClient.crm.contacts.basicApi.getById(event.object.objectId, ["phone"]); phone = ApiResponse.properties.phone; } catch (err) { console.error(err); // We will automatically retry when the code fails because of a rate limiting error from the HubSpot API. throw err; } /***** How to use inputs Inputs are a way for you to take data from any actions in your workflow and use it in your code instead of having to call the HubSpot API to get that same data. Each input needs to be defined like the example below *****/ const email = event.inputFields['email']; /***** How to use outputs Outputs are a way for you to take data from your code and use it in later workflows actions Use the callback function to return data that can be used in later actions. Data won't be returned until after the event loop is empty, so any code after this will still execute. *****/ callback({ outputFields: { email: email, phone: phone } }); } /* A sample event may look like: { "origin": { // Your portal ID "portalId": 1, // Your custom action definition ID "actionDefinitionId": 2, }, "object": { // The type of CRM object that is enrolled in the workflow "objectType": "CONTACT", // The ID of the CRM object that is enrolled in the workflow "objectId": 4, }, "inputFields": { // The property name for defined inputs }, // A unique ID for this execution "callbackId": "ap-123-456-7-8" } */
NODE16X, v3
const hubspot = require('@hubspot/api-client'); exports.main = async (event, callback) => { /***** How to use secrets Secrets are a way for you to save API keys or private apps and set them as a variable to use anywhere in your code Each secret needs to be defined like the example below *****/ const hubspotClient = new hubspot.Client({ apiKey: process.env.SECRET_NAME }); let phone; try { const ApiResponse = await hubspotClient.crm.contacts.basicApi.getById(event.object.objectId, ["phone"]); phone = ApiResponse.body.properties.phone; } catch (err) { console.error(err); // We will automatically retry when the code fails because of a rate limiting error from the HubSpot API. throw err; } /***** How to use inputs Inputs are a way for you to take data from any actions in your workflow and use it in your code instead of having to call the HubSpot API to get that same data. Each input needs to be defined like the example below *****/ const email = event.inputFields['email']; /***** How to use outputs Outputs are a way for you to take data from your code and use it in later workflows actions Use the callback function to return data that can be used in later actions. Data won't be returned until after the event loop is empty, so any code after this will still execute. *****/ callback({ outputFields: { email: email, phone: phone } }); } /* A sample event may look like: { "origin": { // Your portal ID "portalId": 1, // Your custom action definition ID "actionDefinitionId": 2, }, "object": { // The type of CRM object that is enrolled in the workflow "objectType": "CONTACT", // The ID of the CRM object that is enrolled in the workflow "objectId": 4, }, "inputFields": { // The property name for defined inputs }, // A unique ID for this execution "callbackId": "ap-123-456-7-8" } */
PYTHON (igual para todas las versiones)
import os from hubspot import HubSpot from hubspot.crm.contacts import ApiException def main(event): # How to use secrets # Secrets are a way for you to save API keys or private apps and set them as a variable to use anywhere in your code # Each secret needs to be defined like the example below hubspot = HubSpot(access_token=os.getenv('SECRET_NAME')) phone = '' try: ApiResponse = hubspot.crm.contacts.basic_api.get_by_id(event.get('object').get('objectId'), properties=["phone"]) phone = ApiResponse.properties.get('phone') except ApiException as e: print(e) # We will automatically retry when the code fails because of a rate limiting error from the HubSpot API. raise # How to use inputs # Inputs are a way for you to take data from any actions in your workflow and use it in your code instead of having to call the HubSpot API to get that same data. # Each input needs to be defined like the example below email = event.get('inputFields').get('email') # How to use outputs # Outputs are a way for you to take data from your code and use it in later workflows actions # Use the callback function to return data that can be used in later actions. # Data won't be returned until after the event loop is empty, so any code after this will still execute. return { "outputFields": { "email": email, "phone": phone } } # A sample event may look like: # { # "origin": { # # Your portal ID # "portalId": 1, # # Your custom action definition ID # "actionDefinitionId": 2, # }, # "object": { # # The type of CRM object that is enrolled in the workflow # "objectType": "CONTACT", # # The ID of the CRM object that is enrolled in the workflow # "objectId": 4, # }, # "inputFields": { # # The property name for defined inputs # }, # # A unique ID for this execution # "callbackId": "ap-123-456-7-8" # }

Crear una acción de código personalizado

Para agregar una acción de código personalizado a un workflow:

  • En tu cuenta de HubSpot, navega a Automatización > Workflows.
  • Haz clic en el nombre de un workflow o crea un nuevo workflow
  • Haz clic en el ícono + más para agregar una acción de workflow.
  • En el panel derecho, selecciona Código personalizado.
 

custom-code-action-select

  • En el panel derecho, configura la acción:
    • De manera predeterminada, las acciones de código personalizado utilizarán Node.js 16.x. Si estás en la versión beta de Python y quieres crear una acción con Python, haz clic en el menú desplegable Idioma y selecciona Python.
    • Para agregar un nuevo secreto, como una ficha de acceso a una aplicación privada, haz clic en Agregar secreto. La aplicación también debe incluir los respectivos alcances de los datos que estés intentando extraer de HubSpot, como contacts o forms.  Más información sobre las aplicaciones privadas de HubSpot.
    • En el cuadro de diálogo, escribe el Nombre del secreto y el Valor del secreto.
    • Haz clic en Guardar. Ahora puedes seleccionar este secreto en futuras acciones de código personalizado.
    • Para editar o eliminar los secretos existentes, haz clic en Administrar secretos.
  • Para incluir propiedades en tu código personalizado, haz clic en el menú desplegable Elegir propiedad y luego selecciona una propiedad. Puedes utilizar propiedades existentes o valores de propiedad formateados previamente en el workflow. Después de seleccionar tu propiedad, introduce un nombre de propiedad para usarlo en el código. Descubre cómo  hacer referencia a las propiedades en tu código personalizado.
  • Para agregar otra propiedad, haz clic en Agregar propiedad. Cada propiedad solo puede agregarse una vez y debe tener un ID de variable único.  Puedes usar hasta 50 propiedades con tu código personalizado. 
  • Para eliminar una propiedad, haz clic en el ícono de eliminación.
  • En el campo del código, escribe tu JavaScript o Python.
  • Para definir las salidas de datos que se pueden usar como entradas más tarde en el workflow: por ejemplo, con la acción Copiar valor de propiedad:
    • En la sección Salidas de datos, haz clic en el menú desplegable Tipo de datos y selecciona un tipo de datos.
    • En el campo Nombre, escribe un nombre para la salida de datos.
    • Para agregar varias salidas, haz clic en Agregar salida.
  • Haz clic en Guardar.

workflow-custom-code

 

Nota: el campo de código no mostrará errores de lint al usar Python. 

Al crear acciones de código personalizado, ten en cuenta lo siguiente: 

  • La función def main(event): se llama cuando se ejecuta la acción del fragmento de código.
  • El argumento event es un objeto que contiene detalles de la ejecución del workflow.
  • La función callback() se utiliza para pasar datos de vuelta al workflow. Se debe llamar en la función exports.main. Esto solo se puede usar con Node.js. 

El objeto event contendrá los siguientes datos:

//example payload { "origin": { // Your portal ID "portalId": 1, // Your custom action definition ID "actionDefinitionId": 2, }, "object": { // The type of CRM object that is enrolled in the workflow "objectType": "CONTACT", // The ID of the CRM object that is enrolled in the workflow "objectId": 4, }, // A unique ID for this execution. "callbackId": "ap-123-456-7-8" }

Probar la acción

Al agregar una acción de código personalizado a un workflow, puedes probar la acción para asegurarte de que el código se ejecute como se esperaba antes de activar el workflow.

Al probar una acción de código personalizado, comenzarás seleccionando un registro para probar el código y luego ejecutarlo. Esta prueba ejecutará solo el código en tu acción personalizada, no ninguna de las otras acciones en el workflow. Cuando el código haya terminado de ejecutarse, podrás ver las salidas del código y el registro de tu prueba.

Nota: al probar tu código personalizado, el código se ejecutará y los cambios se aplicarán al registro de prueba seleccionado. Se recomienda crear un registro de prueba dedicado si deseas evitar actualizar los registros activos. 

Para probar una acción de código personalizado:

  • En la cronología del workflow, haz clic en la acción de código personalizado.
  • En la parte inferior de la barra lateral derecha, haz clic en Probar acción para expandir la sección de pruebas.
    workflow-custom-code-test-expand
  • Selecciona un registro con el que probar el código haciendo clic en el menú desplegable [Objeto], y luego selecciona un registro.
    workflow-custom-code-action-test2
  • Si usas valores de propiedad con formato anterior en el workflow, introduce un valor de prueba para los datos con formato.   

  • Para ejecutar el código, haz clic en Probar.
  • En el cuadro de diálogo, confirma que deseas probar tu código con respecto al registro seleccionado haciendo clic en Probar.
  • Una vez que tu código haya terminado de ejecutarse, la barra lateral mostrará los resultados de la prueba:
    • Estado: el estado de éxito o error de tu acción de código personalizado.
    • Salidas de datos: los valores que resultaron para las salidas de los datos definidos. Aparecerá una alerta junto a las salidas que el código haya generado y que no se haya definido ni en la sección Salidas de datos ni en el editor de códigos. Deberás agregar esas salidas para usarlas más adelante en el workflow.
    • Registros: información sobre la prueba en sí, como cuánta memoria usó la acción para ejecutarse y el tiempo de ejecución total. 

      workflow-custom-code-action-test0results0
  • Para actualizar tu acción de código personalizado, haz clic en Crear acción para expandir el editor de acciones. Continúa actualizando y probando tu código según sea necesario.
  • Cuando termines de probar la acción, haz clic en Guardar para guardar los cambios.

Secretos

Hay veces que querrás que tu código haga referencia a algo que no se debe compartir ampliamente. La mayoría de las veces, se trata de un medio de autentificación, como una ficha de acceso a aplicaciones privadas. Puedes administrar los secretos a los que tu función tiene acceso directamente en la definición de acción del workflow. Cuando se utilizan varios secretos dentro de un código personalizado, la longitud total de todos los valores secretos no debe exceder los 1000 caracteres.

workflow-custom-code-secrets

Los secretos, una vez agregados, estarán disponibles como variables de entorno, a las que puedes acceder en el código personalizado, como se muestra a continuación:

const hubspot = require('@hubspot/api-client'); exports.main = (event, callback) => { return callback(processEvent(event)); };function processEvent(event) { // secrets can be accessed via environment variables const hubspotClient = new hubspot.Client({ accessToken: process.env.secretName }); hubspotClient.crm.contacts.basicApi.getById(event["object"]["objectId"], ["email", "phone"]) .then(results => { let email = results.body["properties"]["email"] let phone = results.body["properties"]["phone"] // ... }) .catch(err => { console.error(err) }) }

Agrega propiedades de HubSpot a tu código personalizado

A veces, es posible que debas recuperar las propiedades del objeto en tu acción de código personalizado. En lugar de usar las API de HubSpot, puedes agregar estas propiedades directamente en la definición de acción del workflow. Agrega propiedades y establece nombres de propiedades para hacer referencia a las propiedades en el código. Puedes agregar hasta 50 propiedades en cada acción de código personalizado.  

Una vez agregada la propiedad, se puede hacer referencia a esta en el código personalizado. 

const email = event.inputFields['email']; email = event.get('inputFields').get('email')

Registro

Una herramienta importante para los desarrolladores es la capacidad de imprimir salidas desde su código. Esto ayuda a depurar problemas y proporciona un mejor apoyo a tus usuarios finales. Para ver la salida de los registros, puedes encontrarlos en la pestaña «Historial» del workflow.  

custom_code_logs

How to Define Outputs

En la función, define los campos de salida que deseas usar más adelante en el workflow. Luego, en la barra lateral derecha, selecciona el tipo de salida de datos (por ejemplo, número, cadena, booleano, fecha y hora, enumeración, número de teléfono, fecha) e introduce el campo que deseas generar.

Los campos de salida deben ser parte de un objeto json formateado en consecuencia, según el idioma utilizado:

callback({ outputFields: { email: email, phone: phone } }); return { "outputFields": { "email": email, "phone": phone } }
custom-code-output

Puedes usar la salida de tu acción de código como en la entrada de la acción Copiar valor de propiedad. Esto elimina la necesidad de realizar otra llamada de API para almacenar el valor como una propiedad en tu objeto.

Ten en cuenta lo siguiente al definir una salida:

  • Si el tipo de salida de datos está en formato de cadena, el límite para los valores de salida de cadena es de 65.000 caracteres. Exceder este límite ocasionará un error OUTPUT_VALUES_TOO_LARGE
  • Si estás usando la acción Copiar valor de propiedad, toma nota también de las las propiedades de origen y destino compatibles.
  • Al copiar propiedades hasta la fecha:
    • Si estás copiando una salida a una propiedad de fecha y hora, la salida deberá estar en formato Unix en milisegundos.
    • Si estás copiando una salida a una propiedad hasta la fecha en lugar de fecha y hora, la salida deberá estar en formato Unix de milisegundos y la hora de la fecha deberá establecerse en medianoche UTC.
currentDate.setUTCHours(0,0,0,0)
custom_code_actions_output_usage

Limitations

Las acciones de código personalizado deben terminar de ejecutarse en un lapso de 20 segundos, y solo puedes usar hasta 128 MB de memoria. Exceder estos límites ocasionará un error. 

Retries

Es posible que debas obtener las propiedades del objeto usando la API de HubSpot o llamar a otros puntos de terminación de la API de HubSpot en tu acción de código personalizado. Como cualquier otra llamada a la API, deberás cumplir con los límites de tasa de API de HubSpot.

  • Si estás usando Node.js y encuentras un error de limitación de velocidad, pero quieres que HubSpot vuelva a intentar la llamada, deberás incluir el error en el bloque catch de la acción de código personalizado.

  • Si usas Python y encuentras un error de limitación de velocidad, pero quieres que HubSpot vuelva a intentar tu llamada, deberás generar el error en el bloque except de la acción de código personalizado.

Nota: si la llamada falla debido a un error de limitación de tasa o a un error 429 o 5XX de axios o @hubspot/api-client, HubSpot volverá a intentar ejecutar tu acción hasta por tres días, comenzando un minuto después de la falla. Las fallas posteriores se volverán a intentar a intervalos cada vez mayores, con un intervalo máximo de ocho horas entre los intentos.

Caveats

Si estás usando Node.js en tu código personalizado, ten en cuenta las siguientes advertencias:

  • Generar números aleatorios: es común usar Math.random para generar números aleatorios, pero los usuarios pueden ver los mismos números generados en diferentes ejecuciones. Esto se debe a que Math.random se proporciona según la hora actual. Dado que HubSpot puede inscribir muchos objetos en un workflow al mismo tiempo y borrar el estado en cada ejecución, diferentes ejecuciones terminan proporcionando Math.random de la misma manera. En cambio, puedes usar la biblioteca random-number-csprng 1.0.2, que garantiza la generación de números pseudoaleatorios criptográficamente seguros.
  • Reutilización de variables: para ahorrar memoria, cualquier variable declarada fuera de la función exports.main puede ser reutilizada para futuras ejecuciones de la acción de código personalizado. Esto es útil cuando se conecta a servicios externos, como una base de datos, pero cualquier lógica o información que deba ser única para cada ejecución de la acción de código personalizado debe estar dentro de la función exports.main.

Si estás usando Python para tu código personalizado, ten en cuenta las siguientes advertencias:

  • Reutilización de variables: al igual que el caso anterior, cualquier variable declarada fuera de la función def main puede ser reutilizada para futuras ejecuciones de la acción de código personalizado.
    • Si declaraste una variable fuera de la función def main, pero no planeas alterarla, puedes hacer referencia a la variable directamente.
    • Si planeas alterar una variable, puedes declarar la variable dentro de la función def main con una clave global antes de hacer referencia a esta.
a = 1 def main(event): global a a += 1

¿Te resultó útil este artículo?
Con este formulario puedes enviar tu opinión sobre nuestros documentos para desarrolladores. Si tienes comentarios sobre el producto de HubSpot, puedes enviarlos al Foro de ideas.