Obtención de Leads desde su Sitio Web
Instrucciones para integrar el formulario de su sitio web con ReactiveCRM: captura de envíos de formularios como leads, envío de eventos de atribución de marketing y verificación del resultado.
1. Descripción general
El flujo recomendado consta de dos solicitudes:
- El sitio envía los datos del formulario a su propio backend.
- El backend del sitio crea un lead en el CRM mediante
POST /api/leads/create. - Después de la creación exitosa, el backend envía un evento de marketing
lead_submitteda través dePOST /api/dashboard/marketing/events, pasando elleadIdrecibido. - El CRM almacena las etiquetas UTM, los identificadores publicitarios y el referente para la atribución de marketing.
Formulario del sitio web
|
v
Backend del sitio / proxy del lado del servidor
| POST /api/leads/create
v
ReactiveCRM -> leadId
| POST /api/dashboard/marketing/events
v
Atribución de marketing y panel de control
No envíe el JWT del CRM ni los secretos directamente desde el navegador. Utilice el backend del sitio o una función serverless para que el token del CRM y los identificadores de servicio nunca queden expuestos al visitante.
2. Autenticación y URL base
Todas las solicitudes se ejecutan en el contexto del inquilino correspondiente y requieren autorización del CRM:
Authorization: Bearer <CRM_ACCESS_TOKEN>
Content-Type: application/json
En los ejemplos se utiliza:
CRM_BASE_URL=https://crm.example.com
Reemplácelo con la URL de su entorno.
3. Datos para recopilar en el sitio
Datos del lead
Para crear un lead, la API admite:
| Campo | Requerido | Descripción |
|---|---|---|
message | no | Mensaje o texto de la consulta del formulario |
ownerId | sí | UUID del usuario del CRM responsable del lead |
authorId | sí | UUID del usuario del CRM que creó el lead |
clientId | no | UUID de un cliente existente |
contactId | no | UUID de un contacto existente |
leadSourceId | no | UUID de un nodo en el árbol de fuentes de leads |
statusId | no | UUID del estado inicial |
quality | no | HOT, WARM, COOL o COLD |
ownerId y authorId son UUIDs de usuarios del CRM. Para un formulario público en el sitio web, no permita que el visitante establezca estos valores por sí mismo: el backend debe proporcionarlos desde la configuración de integración.
Datos de la visita de marketing
Antes de que se envíe el formulario, almacene lo siguiente en cookies, almacenamiento de sesión o en el backend:
utm_source→utmSourceutm_medium→utmMediumutm_campaign→utmCampaignutm_content→utmContentutm_term→utmTermgclid— identificador de Google Adsfbclid— identificador de Meta/Facebook- URL de la página de destino →
landingUrl - URL de la página anterior →
referrer - Sus propios identificadores de visitante y sesión →
visitorId,sessionId
Guarde los valores en la primera visita y no los sobrescriba con parámetros vacíos al navegar dentro del sitio.
4. Creación de un lead
Endpoint
POST /api/leads/create
Ejemplo de solicitud
curl -X POST "$CRM_BASE_URL/api/leads/create" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "Consulta desde el sitio web: solicitud de asesoría",
"ownerId": "11111111-1111-1111-1111-111111111111",
"authorId": "11111111-1111-1111-1111-111111111111",
"quality": "WARM"
}'
Ejemplo de respuesta 201 Created
{
"id": "22222222-2222-2222-2222-222222222222",
"message": "Consulta desde el sitio web: solicitud de asesoría",
"quality": "WARM",
"dealId": null,
"createdAt": "2026-09-05T20:00:00Z",
"updatedAt": "2026-09-05T20:00:00Z",
"version": 0,
"author": {
"id": "11111111-1111-1111-1111-111111111111",
"firstName": "CRM",
"lastName": "Bot"
},
"owner": {
"id": "11111111-1111-1111-1111-111111111111",
"firstName": "CRM",
"lastName": "Bot"
}
}
Guarde el id de la respuesta: este valor se pasa en el campo leadId del evento de marketing.
5. Envío del evento de lead enviado
Endpoint
POST /api/dashboard/marketing/events
Ejemplo de solicitud
curl -X POST "$CRM_BASE_URL/api/dashboard/marketing/events" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"eventType": "lead_submitted",
"occurredAt": "2026-09-05T20:00:00Z",
"visitorId": "visitor-8b7f",
"sessionId": "session-31ac",
"leadId": "22222222-2222-2222-2222-222222222222",
"externalId": "site-form-submit-20260905-000123",
"source": "website",
"channel": "paid",
"utmSource": "google",
"utmMedium": "cpc",
"utmCampaign": "summer-consulting",
"utmContent": "banner-a",
"utmTerm": "crm consultation",
"gclid": "EAIaIQobChMI-example",
"landingUrl": "https://www.example.com/consultation",
"referrer": "https://www.google.com/",
"metadata": {
"formName": "consultation",
"pageType": "landing"
}
}'
Ejemplo de respuesta
{
"accepted": true,
"duplicate": false,
"eventId": "33333333-3333-3333-3333-333333333333"
}
Si el mismo externalId ya ha sido procesado para este par de source e inquilino, la API devuelve una respuesta exitosa con duplicate: true. Trátelo como un éxito, no como un error, y no cree un segundo lead.
6. Ejemplo de manejador del lado del servidor
A continuación se muestra un ejemplo simplificado en Node.js. Los datos del formulario deben ir al backend del sitio, no directamente al CRM desde el navegador.
async function createWebsiteLead(form, attribution) {
const headers = {
Authorization: `Bearer ${process.env.CRM_ACCESS_TOKEN}`,
'Content-Type': 'application/json',
};
const leadResponse = await fetch(
`${process.env.CRM_BASE_URL}/api/leads/create`,
{
method: 'POST',
headers,
body: JSON.stringify({
message: form.message || `Consulta desde el sitio web: ${form.subject || 'sin asunto'}`,
ownerId: process.env.CRM_LEAD_OWNER_ID,
authorId: process.env.CRM_LEAD_AUTHOR_ID,
quality: 'WARM',
}),
},
);
if (!leadResponse.ok) {
throw new Error(`La creación del lead en CRM falló: ${leadResponse.status}`);
}
const lead = await leadResponse.json();
const externalId = `website-${form.requestId}`;
const eventResponse = await fetch(
`${process.env.CRM_BASE_URL}/api/dashboard/marketing/events`,
{
method: 'POST',
headers,
body: JSON.stringify({
eventType: 'lead_submitted',
occurredAt: new Date().toISOString(),
visitorId: attribution.visitorId,
sessionId: attribution.sessionId,
leadId: lead.id,
externalId,
source: 'website',
channel: attribution.channel || 'direct',
utmSource: attribution.utmSource,
utmMedium: attribution.utmMedium,
utmCampaign: attribution.utmCampaign,
utmContent: attribution.utmContent,
utmTerm: attribution.utmTerm,
gclid: attribution.gclid,
fbclid: attribution.fbclid,
landingUrl: attribution.landingUrl,
referrer: attribution.referrer,
metadata: { formName: form.formName || 'website' },
}),
},
);
if (!eventResponse.ok) {
// El lead ya está creado. Ponga el evento en cola y reinténtelo
// con el mismo externalId en lugar de crear un segundo lead.
throw new Error(`El evento de marketing de CRM falló: ${eventResponse.status}`);
}
return { leadId: lead.id, marketingEvent: await eventResponse.json() };
}
7. Idempotencia y reintentos
- Genere un
externalIdestable para cada envío de formulario. Por ejemplo, use un UUID creado antes de la primera solicitud, o unrequestIdúnico del formulario. - En caso de error de red, reintente la solicitud del evento de marketing con el mismo
externalId. - No genere un nuevo
externalIdal reintentar: eso crearía un evento duplicado. - Si la solicitud de creación del lead termina con un resultado desconocido debido a un tiempo de espera, no cree un nuevo lead a ciegas. Primero use su propio
requestIdy un mecanismo de deduplicación en el backend del sitio, o busque el lead creado en el CRM. - Un error al enviar el evento no debe hacer que el usuario vuelva a enviar el formulario sin verificar el resultado de la creación del lead.
8. Datos personales y metadata
Está prohibido pasar datos personales y contenidos del formulario en metadata:
- correo electrónico
- teléfono
- nombre y apellido
- dirección
- texto del mensaje
- cookies con identificadores que contengan datos personales
Los datos personales deben pasarse únicamente en las entidades del CRM diseñadas para ello — por ejemplo, en un contactId/clientId previamente creado. Mantenga solo atributos técnicos en metadata: nombre del formulario, tipo de página, variante del banner, etc.
9. Respuestas y errores típicos
| HTTP | Situación | Qué hacer |
|---|---|---|
201 | Lead creado | Guarde el id y envíe lead_submitted |
200 + duplicate: false | Evento aceptado | Guarde el eventId en el registro de integración |
200 + duplicate: true | El evento ya fue aceptado | Trátelo como procesado; no lo envíe de nuevo |
400 | Datos inválidos o PII en metadata | Corrija los datos; reintentar sin cambios no ayudará |
401 | Token inválido o faltante | Actualice el token del CRM en el backend |
403 | El token no tiene permiso para la operación | Verifique el rol y el inquilino |
5xx / timeout | Error transitorio del CRM o de la red | Reintente con el mismo externalId; para leads use una cola |
10. Verificación de resultados en el CRM
Después de la integración, verifique:
- El lead aparece a través de
GET /api/leads/{id}o en la listaGET /api/leads/paged. - El propietario, autor y hora de creación del lead son correctos.
- La respuesta del evento de marketing tiene
duplicateigual afalseen el primer envío. - El reenvío del mismo envío devuelve
duplicate: true. - En el panel de marketing, los datos aparecen en el período, canal y campaña correctos.
Obtención del lead creado
curl "$CRM_BASE_URL/api/leads/$LEAD_ID" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
Obtención de leads para listas o conciliación
curl "$CRM_BASE_URL/api/leads/paged?page=0&size=20&createdAtFrom=2026-09-05T00:00:00Z&createdAtTo=2026-09-05T23:59:59Z&sort=createdAt,desc" \
-H "Authorization: Bearer $CRM_ACCESS_TOKEN"
El parámetro page comienza en 0; el size predeterminado es 20. Para obtener leads del sitio web, utilice además los filtros message, createdAtFrom/createdAtTo, contactEmail o search si los datos relevantes ya están almacenados en el CRM.
Reactive CRM