Skip to content

DSW - Desarrollo web en entorno servidor

El backend como nucleo de la aplicacion

La capa servidor de SEO Growth Engine concentra la logica principal del proyecto. Aqui definimos el dominio, controlamos accesos, lanzamos procesos, construimos respuestas API y guardamos trazabilidad de las ejecuciones.

Hemos utilizado Django como framework principal y lo hemos llevado a un uso bastante completo: modelos, ORM, formularios, vistas web, admin, autenticacion, API JSON y tareas desacopladas.

Evidencias directas

  • dashboard/models.py
  • dashboard/admin.py
  • dashboard/web/forms.py
  • dashboard/web/views.py
  • dashboard/api/urls.py
  • dashboard/api/views.py
  • main/settings.py
  • main/urls.py
  • dashboard/tasks/queue.py
  • dashboard/tasks/services.py
  • dashboard/management/commands/runworker.py
  • engine/runner.py
  • engine/gsc.py
  • engine/ga4.py
  • engine/report_data.py
  • engine/ai_visibility.py

Cumplimiento de los requisitos de DSW

Requisito Como lo hemos resuelto Evidencia real
Django como backend Hemos construido la aplicacion principal sobre Django y la hemos organizado por apps, vistas y settings manage.py, main/, dashboard/
Modelos y ORM Hemos modelado sitios, accesos, runs y visibilidad IA con relaciones y consultas ORM dashboard/models.py
Interfaz administrativa Registramos modelos clave para administracion interna dashboard/admin.py
API La capa cliente consume una API JSON real construida dentro del proyecto dashboard/api/views.py, dashboard/api/urls.py
Autenticacion Usamos usuarios Django, cookies de sesion, CSRF y permisos por acceso a sitio main/settings.py, dashboard/api/views.py, dashboard/web/views.py
Tareas desacopladas Los procesos largos se mandan a Redis + RQ y se ejecutan en worker dashboard/tasks/queue.py, dashboard/tasks/services.py, runworker.py
Documentacion tecnica El backend esta documentado con rutas, evidencias y decisiones tecnicas docs/documentacion-del-proyecto.md, docs de despliegue y esta seccion

El dominio que hemos modelado

En dashboard/models.py se ve bien que no estamos ante una base de datos improvisada. Hemos creado un dominio coherente:

  • Site: representa el activo principal sobre el que trabaja la plataforma.
  • SiteAccess: relaciona usuarios con sitios y permisos operativos.
  • AnalysisRun: guarda cada ejecucion con estado, progreso, artefactos y tiempos.
  • AIVisibilityPrompt: define prompts configurables por sitio.
  • AIVisibilityRun: registra ejecuciones de visibilidad IA.
  • AIVisibilityObservation: persiste observaciones y resultados.

Ademas, los modelos incluyen helpers que convierten datos crudos en comportamiento util:

  • Site.save() genera el slug automaticamente.
  • Site.integration_cards() resume el estado de integraciones.
  • AnalysisRun.is_finished, is_active, is_cancellable ayudan a la interfaz y al flujo.
  • AnalysisRun.duration_display y date_range_label traducen datos a informacion operativa legible.

Arquitectura backend en detalle

API y serializacion

En dashboard/api/views.py hay una API JSON propia que alimenta la capa cliente y expone datos operativos del workspace:

  • _serialize_user() prepara la informacion del usuario para el cliente.
  • _serialize_run_summary() y _serialize_run_detail() convierten un AnalysisRun en un payload reutilizable.
  • _serialize_site() y _serialize_dashboard_site() construyen la vista resumida que necesita el dashboard.
  • api_bootstrap() resuelve el arranque de la sesion cliente.
  • api_session_login() y api_session_logout() conectan el login Vue con la autenticacion Django.
  • api_sites_list(), api_runs_list(), api_run_detail() y api_dashboard_summary() exponen los datos reales del workspace.

Con esta API alimentamos la interfaz con datos de sesion, sitios, runs, detalle de ejecucion y resumen del dashboard.

Logica web y flujos operativos

En dashboard/web/views.py se concentran varios flujos operativos del backend:

  • _build_site_summary() resume el estado operativo de un sitio para listados y paneles.
  • _build_run_setup_warnings() detecta carencias de configuracion antes de lanzar una ejecucion.
  • launch_run() crea y arranca analisis tecnicos.
  • cancel_run() y retry_run() controlan el ciclo de vida de una ejecucion.
  • launch_ai_visibility_run(), cancel_ai_visibility_run() y retry_ai_visibility_run() hacen lo mismo con la parte de IA.
  • run_status(), run_report() y run_artifact() exponen seguimiento, informe y archivos generados.

Con estas funciones mostramos que nuestra aplicacion no solo presenta datos: tambien orquesta procesos reales.

Formularios con validacion de negocio

En dashboard/web/forms.py no hay formularios planos. Hemos anadido validaciones que protegen nuestra operativa:

  • AnalysisRunForm.clean() obliga a seleccionar al menos un modulo, valida rangos de fechas y comprueba si GSC, GA4 o AI Visibility estan realmente preparados.
  • ClientAccountForm.clean() y save() gestionan alta de clientes, asignacion de sitios y permisos finos de run y IA.
  • PublicContactForm prepara entradas de contacto con una estructura valida para revision interna.

Aqui se ve que usamos Django Forms no solo para pintar campos, sino para reforzar las reglas de nuestro sistema.

Crawler tecnico

El crawler vive en engine/crawler.py y se ejecuta desde engine/runner.py. Su responsabilidad es transformar una URL inicial en datos tecnicos medibles: paginas HTML, assets, enlaces internos, metadatos, contenido, canonicals, hreflang y redirecciones.

URL inicial Se normaliza la URL del sitio y se crea la primera entrada de cola.
Cola async `asyncio.Queue` reparte URLs entre workers concurrentes.
Fetch HTTP `httpx.AsyncClient` descarga la URL, controla timeout y sigue redirecciones de forma manual.
Parse HTML `BeautifulSoup` extrae title, H1, H2, H3, texto, links, canonical y hreflang.
Nuevos enlaces Solo se encolan enlaces normalizados del mismo dominio y no visitados.
Auditoria El resultado pasa a analisis de issues, enlazado interno, redirects, canonicals y estructura URL.

El control de alcance se hace con CrawlConfig:

  • max_pages limita cuantas URLs se visitan.
  • delay introduce pausa entre peticiones para no saturar el sitio.
  • timeout evita que una URL lenta bloquee todo el proceso.
  • concurrency define cuantos workers rastrean a la vez.

El crawler separa dos tipos de salida:

  • pages: documentos HTML con contenido, metadatos y enlaces internos.
  • assets: recursos no HTML o respuestas que parecen assets.

Despues, engine/analysis.py convierte ese material en informacion SEO:

  • audit_pages() detecta errores HTTP, titulos ausentes, H1 ausentes, contenido fino y duplicados.
  • internal_link_graph() calcula inlinks, outlinks, paginas huerfanas, hubs y autoridad interna.
  • audit_redirects() identifica redirecciones simples, cadenas y paginas rotas.
  • audit_canonical() revisa canonicals ausentes, self-canonical, cross-canonical y conflictos.
  • audit_url_structure() analiza profundidad y patrones de URL.

Con este flujo el crawler no se queda en "visitar paginas". Produce una base de datos tecnica que luego alimenta CSVs, plan de accion, informe HTML e historico de ejecuciones.

Tareas desacopladas, workers y ejecucion en segundo plano

Con esta capa resolvemos un problema real: un crawl, una consulta a GSC, una consulta a GA4 o un analisis de AI Visibility pueden tardar bastante. Si todo eso se ejecutara dentro de la peticion HTTP, el usuario esperaria con la pantalla bloqueada y el servidor podria agotar timeouts.

Por eso en nuestro proyecto separamos dos responsabilidades:

  • la web recibe la accion del usuario, valida permisos y crea el AnalysisRun o el AIVisibilityRun;
  • el worker ejecuta el trabajo pesado fuera del ciclo de peticion/respuesta.
Vista Django Valida formulario, permisos y crea el run
Redis + RQ Guarda el trabajo en cola
Worker Ejecuta crawl, GSC, GA4 o IA
Base de datos Actualiza estado, progreso, logs y artefactos

En dashboard/tasks/queue.py se decide si se usa Redis + RQ o un fallback por thread:

  • get_active_queue_backend() elige rq si hay REDIS_URL o thread si no hay cola disponible.
  • enqueue_analysis_run() envia dashboard.tasks.jobs.run_analysis_job a la cola de analisis.
  • enqueue_ai_visibility_run() envia dashboard.tasks.jobs.run_ai_visibility_job a la cola de IA.
  • get_worker_queues() prepara las colas que escuchara el worker.

En dashboard/tasks/services.py se coordina la ejecucion real:

  • start_analysis_in_background() conecta la accion web con la cola.
  • start_ai_visibility_in_background() hace lo mismo para IA.
  • _execute_run() marca el run como RUNNING, llama a engine.runner.run_full(), actualiza progreso y guarda artefactos.
  • _execute_ai_visibility_run() procesa prompts, llama a run_visibility_analysis() y guarda observaciones.
  • _set_run_progress() actualiza porcentaje, paso actual y mensaje visible.
  • _append_log() deja rastro cronologico en log_output.
  • request_analysis_cancellation() y request_ai_visibility_cancellation() permiten cancelar de forma controlada.

La interfaz no se bloquea porque la peticion HTTP solo dispara el trabajo. Nuestro worker trabaja aparte y la UI consulta o muestra el estado guardado en base de datos.

Con esta separacion conseguimos varios resultados practicos:

  • la peticion HTTP no queda bloqueada por procesos largos;
  • menos riesgo de timeouts;
  • posibilidad de cancelar o reintentar;
  • logs visibles para diagnostico;
  • arquitectura preparada para crecer con mas workers si hubiera mas carga;
  • separacion limpia entre capa web y procesamiento pesado.

Motor y funciones analiticas relevantes

Nuestro backend no termina en dashboard/. El motor tecnico vive en engine/:

  • engine/gsc.py incluye funciones como fetch(), quick_wins(), ctr_leaks(), cannibalization() y bigram_clusters().
  • engine/ga4.py incluye fetch() y la construccion de metricas derivadas.
  • engine/report_data.py concentra build_report_data() y la comparativa entre ejecuciones.
  • engine/ai_visibility.py culmina en run_visibility_analysis().

El backend no es solo CRUD: tambien incorpora analitica, tratamiento de datos y generacion de resultados SEO.

Autenticacion y seguridad basica

La autenticacion se apoya en usuarios Django, sesion y CSRF. En main/settings.py quedan configurados:

  • LOGIN_URL, LOGIN_REDIRECT_URL y LOGOUT_REDIRECT_URL;
  • CSRF_TRUSTED_ORIGINS;
  • cookies de sesion con opciones de seguridad;
  • separacion de secretos mediante variables de entorno.

Con esto dejamos una base coherente para una aplicacion con usuarios autenticados, sesiones y variables de entorno.

Resultado del bloque servidor

Nuestro backend no se limita a responder peticiones. Es la capa que modela el dominio, protege el acceso, organiza procesos, genera resultados y alimenta las vistas y la API.

Evolucion natural

La API del proyecto esta hecha con vistas JSON propias y no con Django REST Framework. Esta decision es suficiente para el alcance actual, aunque una evolucion posterior podria usar DRF si quisieramos ampliar integraciones externas o estandarizar mas la capa API.