Sincronizar envíos de formularios de HubSpot a Salesforce en Jitterbit Studio
Introducción
Los envíos de formularios de HubSpot llegan como una lista paginada en la que cada envío contiene una matriz de pares nombre/valor (un par por cada campo del formulario) en lugar de un registro plano con propiedades nombradas. Esta guía muestra cómo recuperar esos envíos mediante la API de Envíos de Formularios de HubSpot a través del conector HTTP v2, distribuirlos uno a la vez mediante el patrón de bucle SelectNodes de Studio, extraer la dirección de correo electrónico, el nombre y el apellido de la matriz de valores, buscar en Salesforce un cliente potencial existente, y crear o actualizar un registro de Cliente potencial según el resultado.
Esta guía utiliza:
- El conector HTTP v2 para llamar a la API de Envíos de Formularios de HubSpot.
- Almacenamiento temporal de Studio para mantener el lote de envío completo entre el paso de búsqueda y el bucle de distribución por registro.
SelectNodesyReadFilepara iterar a través de registros XML almacenados.SfLookupAllpara detectar clientes potenciales duplicados por dirección de correo electrónico.- Las actividades Crear y Actualizar del conector de Salesforce para escribir el registro de Cliente potencial.
Esta guía asume una cuenta de HubSpot con una aplicación privada y un token de acceso. Se necesita el GUID del formulario cuyos envíos se desean sincronizar. Cada formulario de HubSpot tiene un GUID único visible en la URL del editor de formularios o a través de la API de Formularios de HubSpot.
Patrón de diseño
La integración se ejecuta en dos etapas: una búsqueda por lotes que recupera todos los envíos de un formulario y los almacena como XML, y un bucle por registro que procesa cada envío individualmente.
Initialize variables
Set form path"] --> B["HTTP v2 GET
HubSpot submissions
for [$hubspot.form.guid]"] B --> C["Transformation
Write to
temp storage (batch)"] C --> D["Script
ReadFile + SelectNodes
loop over submissions"] D --> E["Per-record operation
(transformation + scripts)"] E --> F{"Email found
in Salesforce?"} F -- Yes --> G["Salesforce
Update Lead"] F -- No --> H["Salesforce
Create Lead
+ optional ZoomInfo enrich"]
La búsqueda por lotes se ejecuta una vez por sincronización de formulario. El bucle por registro se ejecuta una vez por envío.
Parte 1: Configurar variables del proyecto y la conexión HTTP v2
Paso 1: Crear variables del proyecto
Almacenar el token de acceso de HubSpot y el GUID del formulario como variables del proyecto para que puedan actualizarse sin editar scripts. Abrir el menú de acciones del proyecto y seleccionar Project Variables. Luego agregar:
| Nombre | Valor predeterminado | Descripción |
|---|---|---|
hubspot.access.token |
(el token de acceso de la aplicación privada de HubSpot) | Token de portador utilizado para autenticar todas las llamadas a API |
hubspot.form.guid |
(el GUID del formulario de HubSpot) | GUID del formulario cuyos envíos se desean sincronizar |
Marcar hubspot.access.token como oculto. Para obtener orientación sobre cómo almacenar credenciales de forma segura, consultar Manage endpoint credentials.
Paso 2: Configurar la conexión HTTP v2
-
En Studio, abrir el proyecto y hacer clic en la pestaña Project endpoints and connectors en la paleta de componentes de diseño.
-
Hacer clic en el conector HTTP v2 para abrir la pantalla de configuración de conexión.
-
Connection Name: Ingresar
HubSpot API. -
Base URL: Ingresar
https://api.hubapi.com. -
Authorization: Seleccionar Bearer Token e ingresar
[$hubspot.access.token]como el valor del token. -
Hacer clic en Test para verificar la conexión, luego hacer clic en Save Changes.
Paso 3: Crear la actividad GET Forms Submissions
-
Desde la conexión HubSpot API, arrastrar una actividad GET al lienzo de diseño.
-
Name: Ingresar
HubSpot - GET Form Submissions. -
Path: Ingresar
/form-integrations/v1/submissions/forms/[$hubspot.form.guid].Studio sustituye
[$hubspot.form.guid]con el valor de la variable del proyecto en tiempo de ejecución. Para sincronizar un formulario diferente, actualizar la variable del proyecto sin modificar la configuración de la actividad. -
En la pestaña Request, agregar un encabezado:
- Key:
Content-Type - Value:
application/json
- Key:
-
Haz clic en Finished (Listo).
Part 2: Recuperar envíos y escribirlos en almacenamiento temporal
Step 1: Crear la operación de recuperación
Crea una operación llamada HubSpot - Fetch Form Submissions con estos pasos en orden:
-
Script: Inicializa las variables utilizadas en el procesamiento por registro:
// Reset per-run staging variables $hubspot.email = ""; $hubspot.firstName = ""; $hubspot.lastName = ""; WriteToOperationLog("Starting HubSpot form submission sync for form: " + [$hubspot.form.guid]); -
GET activity: Coloca la actividad
HubSpot - GET Form Submissionscomo paso de origen. -
Transformation: Agrega una transformación después de la actividad GET con una actividad Temporary Storage Write como destino. Asigna el esquema JSON de origen al esquema de destino en los niveles de bucle
results/itemyresults/item/values/itemde modo que todos los registros de envío se escriban en almacenamiento temporal en una sola pasada.Asigna el nombre
HubSpot - Write Submissions to Temp Storagea la transformación y el nombreWrite HubSpot Submissionsa la actividad Temporary Storage Write.
La actividad Temporary Storage Write almacena los registros de envío como XML. Studio escribe cada elemento en el nivel de bucle más interno como un elemento DocInfo, que es el formato que el bucle de distribución lee en Part 3.
Step 2: Controlar el caso en que no se encuentren envíos
Agrega un paso Script después de la transformación. Verifica el recuento de envíos antes de distribuir el bucle:
$count = Length(SelectNodes(
ReadFile("<TAG>activity:tempstorage/HubSpot Temp Storage/tempstorage_read/Read HubSpot Submissions</TAG>"),
"//DocInfo"
));
If($count == 0,
WriteToOperationLog("No HubSpot submissions found. Exiting.");
CancelOperation("<TAG>operation:HubSpot - Fetch Form Submissions</TAG>");
,
WriteToOperationLog("Found " + $count + " submission(s) to process.");
);
CancelOperation cancela la operación actual de manera ordenada sin generar un error cuando no hay envíos presentes.
Part 3: Distribuir envíos uno a la vez
Step 1: Agregar el script de distribución
Agrega un paso Script a la operación HubSpot - Fetch Form Submissions después de la verificación de recuento. Este script lee el lote almacenado, extrae registros de envío individuales utilizando SelectNodes y llama a una operación por registro una vez por envío:
data = ReadFile("<TAG>activity:tempstorage/HubSpot Temp Storage/tempstorage_read/Read HubSpot Submissions</TAG>");
nodes = SelectNodes(data, "//DocInfo");
counts = Length(nodes);
WriteToOperationLog("Dispatching " + counts + " submission(s).");
i = 0;
While(i < counts,
node = nodes[i];
// Wrap the single node so the per-record operation has a valid XML source
xml = "<SubmissionBatch><Submissions>" + String(node) + "</Submissions></SubmissionBatch>";
WriteFile(
"<TAG>activity:tempstorage/HubSpot Temp Storage 2/tempstorage_write/Write Single HubSpot Submission</TAG>",
xml
);
FlushFile(
"<TAG>activity:tempstorage/HubSpot Temp Storage 2/tempstorage_write/Write Single HubSpot Submission</TAG>"
);
RunOperation("<TAG>operation:HubSpot - Process Single Submission</TAG>");
i = i + 1;
);
El contenedor <SubmissionBatch><Submissions> es un contenedor externo fijo que proporciona a la transformación de origen de la operación por registro un elemento raíz predecible. El nodo DocInfo extraído se convierte en el elemento interno que la transformación asigna.
FlushFile fuerza la finalización de la escritura antes de que RunOperation llame a la operación por registro. Sin el vaciado, la operación puede leer los datos del registro anterior.
Importante
RunOperation está sujeto a un límite de nivel de agente en las llamadas síncronas realizadas desde dentro de un único bucle While (50 de forma predeterminada). Si un lote tiene más de 50 envíos, este bucle de distribución alcanza ese límite a mitad de camino: RunOperation devuelve false para el envío 51 en adelante y los envíos restantes en el lote no se procesan. Consulta la nota en RunOperation para saber cómo configurar o anular este límite para GUID de formularios que regularmente reciben más de 50 envíos por sincronización.
Step 2: Configurar almacenamiento temporal para distribución por registro
Configura un segundo punto de conexión de Temporary Storage (por ejemplo, HubSpot Temp Storage 2) con:
- Una actividad Write llamada
Write Single HubSpot Submission. - Una actividad Read llamada
Read Single HubSpot Submission, utilizada como origen en la operación por registro.
Los dos puntos de conexión mantienen el lote completo y el búfer por registro separados de modo que el bucle de distribución no sobrescriba los datos de origen sobre los que está iterando.
Part 4: Extraer valores de campo del envío
Los envíos de formularios de HubSpot almacenan valores de campo como una matriz values de objetos de nombre/valor. El nombre del campo (email, firstname, lastname) se encuentra en el campo name y el valor enviado se encuentra en el campo value. La transformación debe iterar en ambos niveles (results/item para cada envío y el anidado values/item para cada campo) y leer el campo name para saber qué variable completar.
Paso 1: Crear la operación por registro
Crear una operación llamada HubSpot - Process Single Submission. Su origen es la actividad de lectura de almacenamiento temporal Read Single HubSpot Submission.
Paso 2: Crear la transformación de extracción de campos
Agregar una transformación a la operación por registro llamada HubSpot - Extract Submission Fields. Definir dos niveles de bucle en la transformación:
- Bucle externo:
results/itemen el origen, asignado a la ruta de destino correspondiente. - Bucle interno:
results/item/values/itemen el origen, anidado dentro del bucle externo.
En el bucle interno, agregar estos scripts de asignación:
Para el nodo de destino values/item/name:
$hubspot.fieldName = json$results$item.values$item.name$
Para el nodo de destino values/item/value:
If($hubspot.fieldName == "email",
$hubspot.email = json$results$item.values$item.value$
);
If($hubspot.fieldName == "firstname",
$hubspot.firstName = json$results$item.values$item.value$
);
If($hubspot.fieldName == "lastname",
$hubspot.lastName = json$results$item.values$item.value$
);
Para el nodo de destino externo results/item/pageUrl (que se ejecuta después de que el bucle interno se completa para cada envío), llamar a la operación de verificación de Salesforce:
If(Length(Trim($hubspot.email)) > 0,
$hubspot.email = ToLower(Trim($hubspot.email));
RunOperation("<TAG>operation:HubSpot - Check Salesforce Lead</TAG>");
,
WriteToOperationLog("Submission missing email field. Skipping.");
);
La asignación de pageUrl se ejecuta una vez por registro de envío, después de que todos sus elementos secundarios de values/item hayan sido procesados. Esto la convierte en el lugar correcto para activar la operación de Salesforce descendente. Normalizar el correo electrónico a minúsculas antes de la búsqueda evita discrepancias sensibles a mayúsculas y minúsculas con los registros de Salesforce.
Parte 5: Verificar Salesforce para un cliente potencial existente
Paso 1: Crear la operación de verificación de Salesforce
Crear una operación llamada HubSpot - Check Salesforce Lead. Agregar un paso de Script como único paso de operación:
$sf.existingLeadId = "";
$result = SfLookupAll(
"<TAG>endpoint:salesforce/Salesforce</TAG>",
"SELECT Id FROM Lead WHERE Email = '"
+ $hubspot.email
+ "' AND IsConverted = false LIMIT 1"
);
If(Length($result) > 0,
$sf.existingLeadId = $result[0][0];
WriteToOperationLog("Existing lead found: " + $sf.existingLeadId);
RunOperation("<TAG>operation:HubSpot - Update Salesforce Lead</TAG>");
,
WriteToOperationLog("No existing lead for: " + $hubspot.email);
RunOperation("<TAG>operation:HubSpot - Create Salesforce Lead</TAG>");
);
SfLookupAll devuelve un arreglo bidimensional: cada arreglo interno es una fila de resultado, y cada elemento es un valor de campo en el orden especificado en la cláusula SELECT. $result[0][0] es el campo Id de la primera (y única) fila devuelta. LIMIT 1 evita que coincidencias múltiples causen un error de índice de arreglo cuando el mismo correo electrónico aparece en más de un registro de cliente potencial.
IsConverted = false excluye clientes potenciales que ya han sido convertidos en contactos, oportunidades o cuentas. Actualizar un cliente potencial convertido en Salesforce genera un error, por lo que es más seguro omitirlos y dejar que la ruta de creación maneje el caso extremo por separado si es necesario.
Para el patrón de consulta SOQL, ver Consultar registros de Salesforce mediante SOQL.
Parte 6: Crear o actualizar el cliente potencial de Salesforce
Paso 1: Crear el registro de cliente potencial
Crear una operación llamada HubSpot - Create Salesforce Lead. Agregar un paso de Transformación que asigne las variables de almacenamiento provisional a una actividad de Creación de Salesforce dirigida al objeto Lead:
| Expresión de origen | Campo del cliente potencial de Salesforce |
|---|---|
$hubspot.firstName |
FirstName |
$hubspot.lastName |
LastName |
$hubspot.email |
Email |
"HubSpot" (literal) |
LeadSource |
Establecer un valor literal para LeadSource para etiquetar todos los clientes potenciales creados por esta integración con fines de generación de reportes.
La actividad de creación de Salesforce devuelve la identificación del nuevo registro. Capturarla para uso en el paso de enriquecimiento opcional:
$sf.newLeadId = TrimChars(
GetJSONString($jitterbit.response, "/id"),
"\""
);
WriteToOperationLog("Created Salesforce lead: " + $sf.newLeadId);
Después de capturar la identificación, llamar a la operación de enriquecimiento de ZoomInfo para rellenar campos adicionales (ver Parte 7):
If(Length($sf.newLeadId) > 0,
RunOperation("<TAG>operation:ZoomInfo - Enrich Lead</TAG>")
);
Paso 2: Actualizar el registro de cliente potencial existente
Crear una operación llamada HubSpot - Update Salesforce Lead. Agregar un paso de Transformación que se asigne a una actividad de Actualización de Salesforce dirigida al objeto Lead. La actividad de actualización requiere el campo Id para identificar el registro:
| Expresión de origen | Campo del cliente potencial de Salesforce |
|---|---|
$sf.existingLeadId |
Id |
$hubspot.firstName |
FirstName |
$hubspot.lastName |
LastName |
$hubspot.email |
Email |
Mapea solo los campos que posee la integración. Omitir campos de la transformación preserva los valores existentes en el registro de Salesforce.
Parte 7: Enriquecer leads nuevos con ZoomInfo
Después de crear un lead nuevo en Salesforce, un paso de enriquecimiento opcional utiliza ZoomInfo para completar el puesto de trabajo actual del contacto, empresa y número de teléfono directo. La operación de enriquecimiento llama al endpoint de enriquecimiento de ZoomInfo usando el email del lead y el nombre de la empresa como claves de búsqueda, luego actualiza el lead de Salesforce con los datos devueltos.
Para la configuración de la conexión de la API de ZoomInfo y el patrón de enrutador de recursos utilizado por este paso, consulta Enriquecer datos de contacto usando ZoomInfo.
Verificar la integración
-
En HubSpot, abre el formulario que estás sincronizando y envía una entrada de prueba con una dirección de email única que no existe en Salesforce. Ejecuta
HubSpot - Fetch Form Submissionsmanualmente y revisa los registros de operaciones. Confirma que el registro muestra el recuento de envíos correcto y queHubSpot - Create Salesforce Leadse ejecutó para el envío de prueba. -
En Salesforce, busca el registro Lead por la dirección de email de prueba. Confirma que
FirstName,LastNameyEmailestán rellenados y queLeadSourceestá establecido enHubSpot. -
Envía una segunda entrada de prueba usando la misma dirección de email. Ejecuta la operación de búsqueda nuevamente y confirma que
HubSpot - Update Salesforce Leadse ejecutó en lugar de la operación de creación, y que el lead de Salesforce existente se actualizó en lugar de duplicarse. -
Prueba el caso de envío vacío ejecutando la operación contra un formulario sin envíos. Confirma que los registros de operaciones muestren "No HubSpot submissions found" y que no se hayan llamado operaciones de Salesforce.
-
Para probar un envío sin el campo de email, añade temporalmente un envío de prueba sin email. Confirma que el registro muestre "Submission missing email field. Skipping." y que no se ejecutaron operaciones de Salesforce para ese registro.
-
Si la actividad GET devuelve un error 401, confirma que
[$hubspot.access.token]esté establecido y que el token de acceso de la aplicación privada no haya expirado. Los tokens de aplicación privada de HubSpot no expiran por defecto, pero se pueden rotar. Verifica el token en la configuración de la aplicación privada de HubSpot. -
Si
SelectNodesdevuelve cero nodos a pesar de que la actividad GET devuelve datos, confirma que la transformación en Parte 2 está iterando en el nivelresults/itemy que la actividad Temporary Storage Write se completó antes de que se ejecutara el script de envío.