Saltar al contenido principal

Integración GoHighLevel

Integración completa y funcional con GoHighLevel (GHL) para sincronización automática de contactos, oportunidades y tags.

Estado:100% IMPLEMENTADO | Listo para configurar y usar

Última actualización: 2026-05-08 Versión: 3.0 (Production-Ready: Health Check, ghl_id, Retry Scheduler)

Resumen Ejecutivo

La integración con GoHighLevel permite:

  • ✅ Sincronización bidireccional de contactos
  • ✅ Custom Field id_floutic como Master Key
  • ✅ Gestión automática de etiquetas con limpieza de estado
  • ✅ Tags de whitelist (emp-early, exp-early)
  • ✅ Lead Score dinámico (0-100)
  • ✅ Estado del contacto calculado automáticamente
  • ✅ Sincronización de campos básicos y personalizados
  • ✅ Webhooks bidireccionales
  • ✅ Creación automática de oportunidades
  • ✅ Health Check endpoint para diagnóstico en tiempo real (7 checks)
  • ✅ Campo ghl_id en modelo User para fast-path de sincronización
  • ✅ Retry Scheduler automático para webhooks fallidos
  • ✅ Sincronización de username/email en actualizaciones de usuario
  • ✅ Pipelines y stages configurables

Campos Sincronizados

Campos Básicos (7)

  • phone, location, email, username
  • company_name, company_website, contact_person

Campos Personalizados - Comunes (3)

  • id_floutic - Master Key para actualizaciones
  • tipo_de_usuario - "Empresa", "Experto" o "Empresa y Experto"
  • estado_del_contacto - Calculado dinámicamente

Campos Personalizados - Empresas (14)

  • company_type, industry, company_size, preferred_language
  • cif, company_email, tax_id
  • fiscal_name, fiscal_address, fiscal_postal_code
  • fiscal_city, fiscal_province, fiscal_country, fiscal_data_complete

Campos Personalizados - Expertos (17)

  • main_area, work_language, experience_years, expert_level
  • availability, internal_rating, portfolio_url, linkedin_url
  • hourly_rate, tax_id, fiscal_name, fiscal_address
  • fiscal_postal_code, fiscal_city, fiscal_province
  • fiscal_country, fiscal_data_complete

Etiquetas Automáticas

Las etiquetas se generan automáticamente según eventos:

Etiquetas de Registro (4)

  • registro-incompleto - Usuario registrado pero sin perfil creado (contacto mínimo en GHL)
  • empresa-pendiente - Usuario con rol empresa que aún no completó su perfil
  • experto-pendiente - Usuario con rol experto que aún no completó su perfil
  • marketing-opt-in - Usuario aceptó recibir comunicaciones comerciales

Etiquetas de Empresa (15)

  • emp-early - Registro desde whitelist/early adopters
  • emp-nuevo-registro - Al registrar empresa (registro normal)
  • emp-activo - Empresa verificada con proyectos
  • emp-inactivo, emp-reactivado - Cambios de estado
  • emp-recontacto, emp-baja, emp-baja-confirmada - Gestión de contactos
  • emp-eliminado - Usuario eliminado definitivamente
  • emp-borrador-creado, emp-proyecto-en-validación - Estados de proyecto
  • emp-proyecto-publicado, emp-proyecto-en-ejecución, emp-proyecto-completado - Ciclo de proyecto
  • emp-cliente-recurrente - Múltiples proyectos completados

Etiquetas de Experto (14)

  • exp-early - Registro desde whitelist/early adopters
  • exp-solicitud - Al crear perfil de experto
  • exp-activo - Experto verificado con actividad
  • exp-pre-evaluación, exp-verificado - Estados de verificación
  • exp-inactivo, exp-eliminado - Gestión de estado
  • exp-nivel-global, exp-nivel-pro, exp-nivel-enterprise - Niveles
  • exp-invitado-proyecto, exp-propuesta-enviada, exp-proyecto-asignado, exp-proyecto-finalizado - Ciclo de proyecto

Etiquetas de Fuente (4)

  • src-ads, src-linkedin, src-referral, src-web

Ver Listado Completo de Etiquetas para más detalles.

Funcionalidades Principales

Sincronización Automática

  • Registro de usuarios → Crea contacto mínimo en GHL inmediatamente (en background) con tags registro-incompleto, empresa-pendiente/experto-pendiente según el rol, y marketing-opt-in si aceptó comunicaciones. El contacto se crea con datos básicos (email, username) antes de que el usuario complete su perfil.
  • Creación de perfil → Enriquece el contacto GHL existente con todos los datos del perfil (nombre, teléfono, empresa, custom fields, etc.). Se reemplazan los tags de registro por los definitivos (emp-nuevo-registro o exp-solicitud) y se calculan lead score y estado del contacto.
  • Añadir nuevo rol → Actualiza contacto existente en GHL añadiendo etiquetas del nuevo rol y actualizando tipo_de_usuario a "Empresa y Experto"
  • Verificación de expertos → Actualiza etiquetas (exp-verificado, exp-solicitud)
  • Eliminación de usuarios → Actualiza etiquetas en GHL antes de eliminar:
    • Empresas: Remueve emp-baja y emp-baja-confirmada, añade emp-eliminado
    • Expertos: Añade exp-eliminado
    • Registra evento user_deleted en ghl_sync_log
    • Si GHL falla, no bloquea la eliminación (solo registra warning)
  • Cambio de nivel de experto → Actualiza etiquetas de nivel (exp-nivel-*)
  • Activación/desactivación → Actualiza etiquetas de estado
  • Publicación de proyecto → Crea oportunidad en GHL
  • Asignación de experto → Actualiza oportunidad y etiquetas

Sincronización Multi-Rol

Cuando un usuario tiene múltiples roles (empresa y experto), GHL gestiona un único contacto para ese usuario:

Flujo actual (con contacto al registro):

  1. Usuario se registra con uno o ambos roles → Se crea contacto mínimo en GHL inmediatamente con tags registro-incompleto + empresa-pendiente y/o experto-pendiente
  2. Al crear el primer perfil → Se enriquece el contacto GHL existente con datos completos del perfil. Se remueven registro-incompleto y el tag pendiente del rol creado, se agregan tags definitivos (emp-nuevo-registro o exp-solicitud).
  3. Al crear el segundo perfil → Se actualiza el contacto existente:
    • Se añade la etiqueta del nuevo rol (emp-nuevo-registro o exp-solicitud)
    • Se actualiza el campo personalizado tipo_de_usuario a "Empresa y Experto"

Detección de escenarios:

  • El sistema usa event_type="registration_minimal" en ghl_sync_log para identificar contactos creados al registro
  • event_type="profile_enriched" previene enriquecimiento duplicado en retries
  • Si no existe log de registro, se asume contacto legacy (pre-migración) y se crea/actualiza normalmente

Etiquetas acumulativas:

  • Si el usuario tiene ambos roles, tendrá ambas etiquetas: emp-nuevo-registro y exp-solicitud
  • Las etiquetas se acumulan, no se reemplazan
  • El campo tipo_de_usuario refleja si tiene uno o ambos roles

Ejemplo:

  • Usuario se registra → Contacto GHL mínimo creado con tags registro-incompleto, empresa-pendiente, marketing-opt-in, estado: "Nuevo - Registro incompleto"
  • Usuario completa perfil de empresa → Contacto GHL enriquecido: tags reemplazados por emp-nuevo-registro, marketing-opt-in, datos fiscales, lead score calculado, estado actualizado
  • Usuario crea perfil de experto → Contacto GHL actualizado con etiqueta exp-solicitud añadida, tipo_de_usuario: "Empresa y Experto"

Lead Score Dinámico

El Lead Score se calcula automáticamente (0-100) basado en:

  • Proyectos completados (30% del peso)
  • Reviews y ratings (25% del peso)
  • Verificación de perfil (20% del peso)
  • Actividad reciente (15% del peso)
  • Tiempo en la plataforma (10% del peso)

Sugerencias de nivel basadas en Lead Score:

  • Global: 0-50 puntos
  • Pro: 51-75 puntos
  • Enterprise: 76-100 puntos

Estado del Contacto Dinámico

Se calcula automáticamente según:

  • Proyectos activos/completados
  • Verificación de perfil
  • Hitos pendientes
  • Estado del usuario

Health Check

El endpoint de Health Check permite a los administradores diagnosticar el estado de la integración GHL en tiempo real.

Endpoint

GET /api/integrations/ghl/health-check?detail_level=quick|full

Requiere permisos de admin.

Checks Disponibles

#CheckDescripciónModo
1ConfigVerifica que todas las variables de entorno GHL estén configuradasquick
2Sync LogsAnaliza últimos 100 sync logs buscando errores recientesquick
3Last SyncVerifica cuándo fue la última sincronización exitosaquick
4API PingHace una llamada real a la API de GHL para verificar conectividadfull
5Tag DriftCompara tags en GHL vs las que debería tener según Flouticfull
6Custom FieldsVerifica que los custom fields necesarios existan en GHLfull
7Webhook CoverageVerifica cobertura de eventos de webhookfull

Niveles de Detalle

  • quick (default): Ejecuta checks 1-3 + 8 (aggregate). Rápido, sin llamadas externas.
  • full: Ejecuta todos los checks (1-8). Incluye llamadas reales a la API de GHL.

Respuesta

{
"status": "healthy|degraded|unhealthy",
"checks": [
{
"name": "config",
"status": "pass|fail|warning",
"message": "Todas las variables configuradas",
"details": {}
}
],
"summary": {
"total": 7,
"passed": 5,
"warnings": 1,
"failed": 1
},
"checked_at": "2026-05-08T10:00:00Z"
}

Campo ghl_id en User

El modelo User incluye un campo ghl_id (nullable, unique, indexed) que almacena directamente el ID del contacto en GHL.

Funcionamiento

  1. Al registrar un usuario y crear el contacto en GHL → se guarda el ghl_id en el User
  2. Al buscar el contacto GHL de un usuario → primero se consulta user.ghl_id (fast path)
  3. Si ghl_id es None → fallback a búsqueda en GHLSyncLog

Ventajas

  • Performance: Elimina query a GHLSyncLog para la mayoría de operaciones
  • Simplicidad: Un solo campo en User, no requiere joins
  • Resiliencia: Fallback a GHLSyncLog si el campo no está poblado

Migración

docker compose exec backend alembic upgrade head

La migración a1b2c3d4e5f7_add_ghl_id_to_users agrega el campo sin afectar datos existentes.

Retry Scheduler

El Retry Scheduler reintenta automáticamente los webhooks fallidos cada 30 minutos (configurable).

Configuración

VariableDefaultDescripción
GHL_RETRY_ENABLEDtrueHabilita/deshabilita el scheduler
GHL_RETRY_INTERVAL_MINUTES30Minutos entre cada ejecución

Comportamiento

  • Se ejecuta al iniciar la aplicación (startup event)
  • En cada ciclo, procesa hasta 10 webhooks fallidos
  • Cada webhook tiene un retry_count que se incrementa en cada intento
  • Los eventos se categorizan por tipo (contact, tag, opportunity, etc.)
  • Ciertos eventos se omiten automáticamente (SKIP_EVENTS)

Dispatch Table

El retry usa una dispatch table que enruta cada tipo de evento a su handler correspondiente:

CategoríaEventosHandler
Contactregistration_minimal, profile_enriched, contact_updateSync de contacto
Tagtag_add, tag_remove, user_deletedGestión de tags
Opportunityopportunity_create, opportunity_updateGestión de oportunidades

Sincronización de Usuario

Cuando un usuario actualiza su username o email, el sistema sincroniza automáticamente los cambios con GHL.

Comportamiento

  • Cambio de username: Envía PUT a GHL con name, firstName, lastName
  • Cambio de email: Envía PUT a GHL con email
  • El helper _sync_ghl_contact es fire-and-forget: errores se loguean pero no bloquean la operación principal
  • Se registra cada sincronización en GHLSyncLog

Campos Prohibidos en PUT

El PUT a GHL /contacts/{id} NO acepta locationId ni source (causan 422). Solo se envían en POST /contacts/.

Conversión de Tipos

  • project.budget es Decimal de PostgreSQL → siempre se convierte a float() antes de enviar a GHL
  • Fallar esta conversión causa "Object of type Decimal is not JSON serializable"

Configuración

1. Variables de Entorno

Añadir en backend/.env:

# GoHighLevel Integration
GHL_API_KEY=tu_api_key_aqui
GHL_API_URL=https://services.leadconnectorhq.com
GHL_LOCATION_ID=tu_location_id
GHL_WEBHOOK_SECRET=tu_secret_seguro

# Retry Scheduler (opcional)
GHL_RETRY_ENABLED=true
GHL_RETRY_INTERVAL_MINUTES=30

# Pipelines (opcional, para gestión de oportunidades)
GHL_PIPELINE_EMPRESAS_ID=id_pipeline_empresas
GHL_PIPELINE_EXPERTOS_ID=id_pipeline_expertos
GHL_PIPELINE_PROYECTOS_ID=id_pipeline_proyectos
GHL_PIPELINE_PROYECTOS_STAGE_INITIAL=uuid_stage_inicial

IMPORTANTE: Private Integrations vs API Keys

  • Private Integrations (recomendado): Token se usa con "Bearer" en el header Authorization
  • URL base: https://services.leadconnectorhq.com (para instancias estándar)
  • Para instancias personalizadas: https://services.[tu-dominio] (ej: https://services.suitesapiens.com)

2. Ejecutar Migración

docker compose exec backend alembic upgrade head

3. Configurar Webhook en GHL

  1. Ir a Settings → Integrations → Webhooks en GHL
  2. Añadir nuevo webhook:
    • URL: https://tu-dominio.com/api/webhooks/ghl
    • Secret: (el mismo que GHL_WEBHOOK_SECRET)
    • Eventos: Contact Create, Contact Update, Contact Tag Update, Opportunity Create, Opportunity Update

API Endpoints

Administración (Solo Admin)

Sincronización Manual

  • POST /api/integrations/ghl/contact - Sincronizar contacto manualmente
  • POST /api/integrations/ghl/opportunity - Crear oportunidad
  • POST /api/integrations/ghl/tag - Añadir tags

Diagnóstico

  • GET /api/admin/users/{user_id}/ghl-diagnosis - Diagnóstico completo de sincronización GHL
  • POST /api/admin/users/{user_id}/ghl-sync-tags - Forzar sincronización manual de tags

Health Check

  • GET /api/integrations/ghl/health-check?detail_level=quick|full - Diagnóstico en tiempo real de la integración GHL (solo admin)

Sync Logs

  • GET /api/integrations/ghl/sync-logs - Historial de sincronizaciones GHL (solo admin)
  • GET /api/integrations/ghl/status/{contact_id} - Estado de contacto en GHL (solo admin)

Webhooks

  • POST /api/webhooks/ghl - Recibe eventos de GHL (validación HMAC)

Testing

Total: 282 tests pasando (21 archivos de test)

Tests de Servicios

  • test_ghl_registration_contact.py - Tests de registro, contacto, enriquecimiento, serialización Decimal, sync de usuario (282 tests)
  • test_ghl_health_check.py - Tests del servicio de Health Check (51 tests)
  • test_ghl_create_task.py - Tests de create_task (4 tests)
  • test_ghl_id_user.py - Tests de ghl_id en User (4 tests)
  • test_ghl_retry_dispatch.py - Tests de dispatch table de retry (14 tests)
  • test_ghl_retry_scheduler.py - Tests del scheduler de retry (6 tests)

Tests de Endpoints

  • test_ghl_integration.py - Tests de integración general
  • test_ghl_sync.py - Tests de sincronización en endpoints admin
  • test_ghl_project_tags.py - Tests de etiquetas de proyecto
  • test_ghl_contact_status.py - Tests de estado de contacto
  • test_ghl_lead_score.py - Tests de lead score
  • test_ghl_lead_score_integration.py - Tests de integración de lead score
  • test_ghl_sync_complete_fields.py - Tests de sincronización de campos completos
  • test_ghl_failures.py - Tests de manejo de fallos GHL

Tests Unitarios

  • test_ghl_tag_nomenclature.py - Tests de nomenclatura de tags
  • test_ghl_id_floutic.py - Tests del custom field ID Floutic
  • test_ghl_empresa_tags.py - Tests de tags de empresas
  • test_ghl_experto_tags.py - Tests de tags de expertos
  • test_ghl_tag_cleanup.py - Tests de limpieza de tags
  • test_ghl_triggers.py - Tests de triggers
  • test_ghl_pipelines.py - Tests de pipelines
  • test_ghl_timeout.py - Tests de timeouts

Ejecutar Tests

# Todos los tests de GHL
./scripts/test_backend.sh tests/endpoints/test_ghl_*.py tests/services/test_ghl_*.py tests/unit/test_ghl_*.py -v

# Solo health check
./scripts/test_backend.sh tests/unit/test_ghl_health_check.py -v

# Solo tests de registro/contacto
./scripts/test_backend.sh tests/services/test_ghl_registration_contact.py -v

Troubleshooting

Endpoint de Diagnóstico

Para diagnosticar problemas de sincronización:

GET /api/admin/users/{user_id}/ghl-diagnosis

Sincronización Manual

Si hay discrepancias entre Floutic y GHL:

POST /api/admin/users/{user_id}/ghl-sync-tags

Documentación Completa

Para documentación detallada, consulta:

Checklist de Activación

  • Obtener API Key de GoHighLevel
  • Configurar variables en backend/.env
  • Ejecutar migración de base de datos
  • Reiniciar backend
  • Configurar webhook en panel de GHL
  • Probar creación de contacto
  • Probar creación de oportunidad
  • Verificar logs de sincronización