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_flouticcomo 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_iden 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,usernamecompany_name,company_website,contact_person
Campos Personalizados - Comunes (3)
id_floutic- Master Key para actualizacionestipo_de_usuario- "Empresa", "Experto" o "Empresa y Experto"estado_del_contacto- Calculado dinámicamente
Campos Personalizados - Empresas (14)
company_type,industry,company_size,preferred_languagecif,company_email,tax_idfiscal_name,fiscal_address,fiscal_postal_codefiscal_city,fiscal_province,fiscal_country,fiscal_data_complete
Campos Personalizados - Expertos (17)
main_area,work_language,experience_years,expert_levelavailability,internal_rating,portfolio_url,linkedin_urlhourly_rate,tax_id,fiscal_name,fiscal_addressfiscal_postal_code,fiscal_city,fiscal_provincefiscal_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 perfilexperto-pendiente- Usuario con rol experto que aún no completó su perfilmarketing-opt-in- Usuario aceptó recibir comunicaciones comerciales
Etiquetas de Empresa (15)
emp-early- Registro desde whitelist/early adoptersemp-nuevo-registro- Al registrar empresa (registro normal)emp-activo- Empresa verificada con proyectosemp-inactivo,emp-reactivado- Cambios de estadoemp-recontacto,emp-baja,emp-baja-confirmada- Gestión de contactosemp-eliminado- Usuario eliminado definitivamenteemp-borrador-creado,emp-proyecto-en-validación- Estados de proyectoemp-proyecto-publicado,emp-proyecto-en-ejecución,emp-proyecto-completado- Ciclo de proyectoemp-cliente-recurrente- Múltiples proyectos completados
Etiquetas de Experto (14)
exp-early- Registro desde whitelist/early adoptersexp-solicitud- Al crear perfil de expertoexp-activo- Experto verificado con actividadexp-pre-evaluación,exp-verificado- Estados de verificaciónexp-inactivo,exp-eliminado- Gestión de estadoexp-nivel-global,exp-nivel-pro,exp-nivel-enterprise- Nivelesexp-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-pendientesegún el rol, ymarketing-opt-insi 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-registrooexp-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_usuarioa "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-bajayemp-baja-confirmada, añadeemp-eliminado - Expertos: Añade
exp-eliminado - Registra evento
user_deletedenghl_sync_log - Si GHL falla, no bloquea la eliminación (solo registra warning)
- Empresas: Remueve
- 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):
- Usuario se registra con uno o ambos roles → Se crea contacto mínimo en GHL inmediatamente con tags
registro-incompleto+empresa-pendientey/oexperto-pendiente - Al crear el primer perfil → Se enriquece el contacto GHL existente con datos completos del perfil. Se remueven
registro-incompletoy el tag pendiente del rol creado, se agregan tags definitivos (emp-nuevo-registrooexp-solicitud). - Al crear el segundo perfil → Se actualiza el contacto existente:
- Se añade la etiqueta del nuevo rol (
emp-nuevo-registrooexp-solicitud) - Se actualiza el campo personalizado
tipo_de_usuarioa "Empresa y Experto"
- Se añade la etiqueta del nuevo rol (
Detección de escenarios:
- El sistema usa
event_type="registration_minimal"enghl_sync_logpara 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-registroyexp-solicitud - Las etiquetas se acumulan, no se reemplazan
- El campo
tipo_de_usuariorefleja 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-solicitudañ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
| # | Check | Descripción | Modo |
|---|---|---|---|
| 1 | Config | Verifica que todas las variables de entorno GHL estén configuradas | quick |
| 2 | Sync Logs | Analiza últimos 100 sync logs buscando errores recientes | quick |
| 3 | Last Sync | Verifica cuándo fue la última sincronización exitosa | quick |
| 4 | API Ping | Hace una llamada real a la API de GHL para verificar conectividad | full |
| 5 | Tag Drift | Compara tags en GHL vs las que debería tener según Floutic | full |
| 6 | Custom Fields | Verifica que los custom fields necesarios existan en GHL | full |
| 7 | Webhook Coverage | Verifica cobertura de eventos de webhook | full |
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
- Al registrar un usuario y crear el contacto en GHL → se guarda el
ghl_iden el User - Al buscar el contacto GHL de un usuario → primero se consulta
user.ghl_id(fast path) - Si
ghl_idesNone→ fallback a búsqueda enGHLSyncLog
Ventajas
- Performance: Elimina query a
GHLSyncLogpara la mayoría de operaciones - Simplicidad: Un solo campo en User, no requiere joins
- Resiliencia: Fallback a
GHLSyncLogsi 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
| Variable | Default | Descripción |
|---|---|---|
GHL_RETRY_ENABLED | true | Habilita/deshabilita el scheduler |
GHL_RETRY_INTERVAL_MINUTES | 30 | Minutos 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_countque 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ía | Eventos | Handler |
|---|---|---|
| Contact | registration_minimal, profile_enriched, contact_update | Sync de contacto |
| Tag | tag_add, tag_remove, user_deleted | Gestión de tags |
| Opportunity | opportunity_create, opportunity_update | Gestió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_contactes 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.budgetesDecimalde PostgreSQL → siempre se convierte afloat()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
- Ir a Settings → Integrations → Webhooks en GHL
- 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
- URL:
API Endpoints
Administración (Solo Admin)
Sincronización Manual
POST /api/integrations/ghl/contact- Sincronizar contacto manualmentePOST /api/integrations/ghl/opportunity- Crear oportunidadPOST /api/integrations/ghl/tag- Añadir tags
Diagnóstico
GET /api/admin/users/{user_id}/ghl-diagnosis- Diagnóstico completo de sincronización GHLPOST /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 generaltest_ghl_sync.py- Tests de sincronización en endpoints admintest_ghl_project_tags.py- Tests de etiquetas de proyectotest_ghl_contact_status.py- Tests de estado de contactotest_ghl_lead_score.py- Tests de lead scoretest_ghl_lead_score_integration.py- Tests de integración de lead scoretest_ghl_sync_complete_fields.py- Tests de sincronización de campos completostest_ghl_failures.py- Tests de manejo de fallos GHL
Tests Unitarios
test_ghl_tag_nomenclature.py- Tests de nomenclatura de tagstest_ghl_id_floutic.py- Tests del custom field ID Floutictest_ghl_empresa_tags.py- Tests de tags de empresastest_ghl_experto_tags.py- Tests de tags de expertostest_ghl_tag_cleanup.py- Tests de limpieza de tagstest_ghl_triggers.py- Tests de triggerstest_ghl_pipelines.py- Tests de pipelinestest_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:
- Listado de Etiquetas - Todas las etiquetas disponibles
- Configuración de GoHighLevel - Guía de setup
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