Resumen — qué abarca
Además de la consola que hay tras el inicio de sesión, InfraGuard tiene una superficie pública.
| Ruta | Pantalla | Acceso |
|---|---|---|
/ |
landing de marketing | invitados (una sesión autenticada redirige a /console) |
/demo |
formulario de solicitud de demo | invitados |
/manual |
manual de usuario | tanto invitados como usuarios autenticados |
/login · /lang/{locale} |
inicio de sesión · cambio de idioma | invitados |
El inicio de la consola vive en /console. Ese traslado cedió / a la superficie pública sin romper el nombre de ruta (overview) ni los marcadores existentes.
La landing se compila como un bundle aparte (front.*). Incluirla en el bundle de la consola obligaría a cada visitante a descargar Vue, ECharts, CodeMirror, Konva y xterm (medido: aproximadamente 1,283KB la consola frente a 24KB el front). Para una página de marketing, la primera impresión es la velocidad de carga. Solo la UI compartida mínima (botones de icono, selector de idioma) vive en
_shared-ui, de modo que ambos lados usan la misma definición: copiarla y pegarla dejaría que un lado se desviara.
El manual público
/manual se abre sin iniciar sesión. Quien esté evaluando el producto debería poder leer cómo se opera realmente, y la documentación pública es en sí misma un activo de marketing y de SEO. Los documentos no contienen secretos ni datos en vivo.
- Una URL, dos envolturas — los invitados reciben la envoltura pública (cabecera, pie, selector de idioma), los usuarios autenticados reciben la envoltura de la consola, y ambas renderizan el mismo cuerpo. La vista y el módulo de página son compartidos, así que las dos no pueden desviarse.
- Los invitados reciben además únicamente un subbundle específico del manual (
manual.*); el bundle de la consola nunca se les sirve. - Los artículos de funciones con privilegios superiores se marcan como bloqueados en lugar de ocultarse. A los invitados se los trata como nivel 1.
- Los puntos de entrada son la llamada a la acción [Manual de usuario] del hero de la landing y la navegación superior.
Solicitudes de demo
El formulario público (/demo)
Se trata de una recepción de solicitudes, no de una demo con un clic. Solo son obligatorios un nombre y un correo corporativo; el idioma, la fuente de referencia y la IP se registran junto a ellos.
Este formulario es la única vía de escritura para invitados de la aplicación, así que está defendido de cuatro maneras.
- Honeypot — si se rellena, no se almacena nada pero la respuesta sigue pareciendo un éxito (nunca anuncie la detección).
throttle:8,1— la novena solicitud dentro de un minuto obtiene un 429.- Token CSRF.
- Validación en servidor con lista blanca —
statusynoteson exclusivos de administración, así que el formulario público no puede fijarlos.
La pantalla de administración (Administración ▸ Solicitudes de demo)
/admin/demo-requests gestiona la bandeja de entrada: CRUD en modal más búsqueda, filtros de estado con recuentos y paginación.
| Estado | Significado |
|---|---|
new |
recibida, sin tocar |
contacted |
ya se ha contactado |
qualified |
oportunidad cualificada |
closed |
terminada |
- Cambie el estado en línea en una fila, o deje una nota interna en el modal.
- El contexto de recepción (IP, idioma, fuente, marca de tiempo) se muestra en solo lectura.
- Las facetas de estado cuentan toda la tabla con independencia del filtro activo: «cuántas quedan sin atender» no debe desaparecer porque se haya aplicado un filtro.
La búsqueda escapa los comodines de LIKE (
%,_,\). Sin eso, escribir un solo%coincidiría con todas las filas.
Etiquetas de analítica (GA4 · GTM · Search Console)
Ponga un ID de medición en .env y la etiqueta aparecerá solo en la superficie pública. Cuando el valor está vacío no se renderiza ningún <script>, de modo que un despliegue por defecto no realiza ninguna petición saliente.
| Clave | Valor | Propósito |
|---|---|---|
GA_MEASUREMENT_ID |
G-XXXXXXXXXX |
gtag.js (GA4) |
GTM_CONTAINER_ID |
GTM-XXXXXXX |
Google Tag Manager (puede convivir) |
GOOGLE_SITE_VERIFICATION |
token meta | propiedad verificada en Search Console |
GA_PRODUCTION_ONLY |
true (por defecto) |
disparar solo en producción |
No las añada nunca a la consola (
layouts/app). Las URL y los títulos de la consola llevan nombres de host, IP, alias de instancia y títulos de incidente. Enviar eso a una propiedad de analítica de terceros contradice la promesa de autoalojamiento y soberanía del dato que la propia landing hace, y filtra detalles de la infraestructura del cliente.
- Los ID solo se emiten tras validar su formato (
G-…/GTM-…). Una errata o un valor con comillas sueltas degrada a «sin analítica» en lugar de a una etiqueta rota. GA_PRODUCTION_ONLYvaletruepor defecto: el tráfico local y de staging que contamina una propiedad no se puede limpiar después, y es el motivo más frecuente de que las cifras de GA4 dejen de resultar fiables.- La conversión se dispara en la página de éxito, no al enviar. Dispararla al enviar cuenta como conversiones los fallos de validación y los aciertos del honeypot, e infla la cifra.
- Las llamadas a la acción se separan por posición (
hero,header,footer_cta,footer_nav,hero_manual) para poder atribuir la contribución. - Si
gtagno está presente el JS no hace absolutamente nada: una carga fallida de la analítica nunca bloquea la interfaz.
GA4 no le da las palabras clave de búsqueda. Informa del canal (búsqueda orgánica) y ahí se detiene; las consultas viven únicamente en Search Console. Por eso la etiqueta meta de verificación de propiedad se emite con independencia de GA4: puede verificar la propiedad sin habilitar GA4 en absoluto. Para los informes por sitio consulte Analítica de visitantes y búsquedas.
Política de textos
Las cifras de confianza de la landing usan solo lo que se puede contar en el código, y se cuentan en tiempo de renderizado en lugar de estar codificadas a mano (número de conjuntos de reglas, número de comprobaciones, número de adaptadores de correo/SMS, etcétera).
Esta política detectó un error real: el número de comprobaciones era 36, no 37. A la inversa, nunca se usan valores observados: el recuento de firmas distintas es 43 en 24h, 67 en 7d y 79 en total, así que cambiaría entre visitas y minaría la confianza en lugar de construirla. Al ser una página pública, tampoco toca nunca la base de datos: una consulta por visita es innecesaria, y la superficie de marketing debería sobrevivir a una base de datos inestable.
Fuentes de datos
| Destino | Ubicación | Función |
|---|---|---|
infr_demo_request |
por defecto (000770) | bandeja de solicitudes de demo (status, note, locale, source, ip) |
config/analytics.php ← .env |
config | fuente única de verdad de los ID de medición y su activación (App\Support\Analytics) |
public/brand/ |
archivos estáticos | logotipo e imágenes OG |
public/brand/debe estar en el repositorio. La mayor parte depublic/es salida generada (build,hot,storageestán en gitignore), así que es fácil pasarlo por alto, pero los recursos de marca no son salida de Vite: nada los construye, y sin ese commit el logotipo y la imagen OG dan 404 en producción. La imagen OG debe ser PNG: muchos rastreadores sociales no renderizan una vista previa en SVG.
Permisos
- Landing, formulario de demo, manual: público.
- Administración ▸ Solicitudes de demo: nivel ≥ 10 (autocontrol), con cada cambio registrado en
infr_audit_log.
Resolución de problemas · Preguntas frecuentes
/me sigue enviando a la consola — es correcto: una sesión autenticada se redirige a/console. Cierre la sesión o use una ventana privada para ver la landing.- La etiqueta no aparece nunca — el ID está vacío, no ha superado la validación de formato, o
GA_PRODUCTION_ONLY=truemientras esto no es producción. Busquegoogletagmanager.comen el código fuente de la página para confirmarlo. - GA4 no recoge nada — compruebe que el ID de medición del sitio pertenece a la propiedad que pretende consultar (Administración de GA4 ▸ Flujos de datos). Si los datos caen en otra propiedad, los informes leerán cero para siempre.
- No se guardó una solicitud de demo — un acierto del honeypot devuelve éxito sin almacenar (es lo previsto). Compruebe también los errores de validación y el límite de 8 por minuto (429).
- El selector lista ocho idiomas pero solo ko/en están traducidos — el resto recurre al inglés. La demanda real de los idiomas sin traducir se observa mediante el parámetro
languagede la analítica. - Un 500 justo después de un despliegue nuevo — hay que configurar nginx para que espere a que termine la compilación de Vite. Como la landing pública es
/, de lo contrario los rastreadores y los posibles clientes se encontrarían un 500 como primera impresión.
Relacionado
- Analítica de visitantes y búsquedas — leer por sitio los datos recogidos
- Servicio ▸ Web — supervisión de los sitios web registrados
- Idioma y localización — cambio de idioma y paquetes de traducción
- Administración ▸ Registro de auditoría — historial de la gestión de solicitudes de demo
