🌐 WebPulse Monitor
Backend MicroSaaS para monitoreo de sitios web: uptime, SEO, integraciones y predicciones.
📋 Contexto
Los equipos de marketing y desarrollo necesitan visibilidad continua del estado de sus sitios web: disponibilidad, rendimiento, SEO y herramientas de análisis instaladas.
🎯 Objetivo
Proporcionar una API REST que permita monitorear múltiples proyectos web, recolectar métricas periódicamente y generar recomendaciones basadas en ML.
📦 Alcance
Incluye:
- Monitoreo de uptime y latencia (cada 5 min)
- Auditoría SEO diaria (crawling + análisis)
- Detección de integraciones (GTM, GA4)
- Predicciones de SEO score (ML)
- Dashboard JSON para frontend
Excluye:
- Interfaz web (se consume por API)
- Notificaciones en tiempo real (SMS/Slack)
- Análisis de competencia
🏛️ Arquitectura
Stack Tecnológico
| Componente | Tecnología | Propósito |
|---|---|---|
| API | Flask | Endpoints REST |
| Base de datos | PostgreSQL + SQLAlchemy | Persistencia |
| Tareas | Celery + Redis | Procesamiento asíncrono |
| Crawling | BeautifulSoup + lxml | Análisis HTML |
| ML | scikit-learn + pandas | Predicciones |
| Migraciones | Alembic | Versionado schema |
Estructura
webpulse-monitor/
├── app/
│ ├── api/ # Blueprints (routes, projects, metrics, seo)
│ ├── models/ # SQLAlchemy models
│ ├── services/ # Lógica de negocio
│ ├── tasks/ # Celery tasks
│ └── utils/ # Helpers
├── tests/
├── docker-compose.yml
└── Pipfile
🗄️ Modelos
| Entidad | Campos Clave | Propósito |
|---|---|---|
| Project | name, domain | Sitio web a monitorear |
| Page | url, status_code, last_crawled | Páginas descubiertas |
| LatencyMetric | response_time_ms, is_online | Métricas de uptime |
| SEOMetric | seo_score, title, meta_description, h1_present | Auditoría SEO |
| IntegrationStatus | has_gtm, has_ga | Herramientas detectadas |
| Recommendation | priority, category, message, impact_score | Sugerencias ML |
Relaciones
Project 1:N Page
Project 1:N LatencyMetric
Page 1:N SEOMetric
Page 1:N IntegrationStatus
Project 1:N Recommendation
🔌 API Endpoints
Proyectos
| Método | Endpoint | Descripción |
|---|---|---|
GET | /projects/ | Listar proyectos |
POST | /projects/ | Crear proyecto |
Métricas
| Método | Endpoint | Descripción |
|---|---|---|
GET | /metrics/uptime/<id> | Último estado de uptime |
GET | /metrics/uptime/<id>/trends | Tendencias históricas |
SEO
| Método | Endpoint | Descripción |
|---|---|---|
GET | /seo/score/<id> | Score SEO global y por página |
GET | /seo/recommendations/<id> | Recomendaciones generadas |
GET | /seo/integrations/<id> | Estado de GTM/GA4 |
⚙️ Configuración
Variables de Entorno (.env)
FLASK_ENV=development
SECRET_KEY=super-secret-key
DATABASE_URL=postgresql+psycopg2://webpulse:webpulse@localhost:5432/webpulse
REDIS_URL=redis://localhost:6379/0
DEFAULT_TARGET_URL=https://example.com
Docker Compose
services:
postgres:
image: postgres:15
environment:
POSTGRES_USER: webpulse
POSTGRES_PASSWORD: webpulse
POSTGRES_DB: webpulse
ports:
- "5432:5432"
redis:
image: redis:7
ports:
- "6379:6379"
🔄 Tareas Celery
Schedule (celery_app.py)
beat_schedule = {
"ping-uptime-every-5-min": {
"task": "app.tasks.collectors.check_uptime_all_projects",
"schedule": 300, # 5 minutos
},
"crawl-seo-daily": {
"task": "app.tasks.collectors.crawl_and_audit",
"schedule": 86400, # 24 horas
},
"compute-predictions-daily": {
"task": "app.tasks.collectors.compute_predictions",
"schedule": 86400,
},
}
Tareas Principales
| Tarea | Frecuencia | Descripción |
|---|---|---|
check_uptime_all_projects | 5 min | Ping a todos los proyectos |
crawl_and_audit | Diaria | Crawling + análisis SEO |
compute_predictions | Diaria | Predicción SEO score (ML) |
🧠 Servicios Clave
SEO Analyzer
def analyze_seo(project, page, soup):
title = soup.title.string.strip() if soup.title else ""
meta = soup.find("meta", attrs={"name": "description"})
h1_present = bool(soup.find("h1"))
images_without_alt = len([img for img in soup.find_all("img") if not img.get("alt")])
# Score heurístico (0-100)
seo_score = sum([
20 if title else 0,
20 if meta else 0,
15 if h1_present else 0,
max(0, 20 - images_without_alt * 2),
])
return seo_score
Predicciones (ML)
def update_predictions():
# LinearRegression con datos históricos
# Predice SEO score a 90 días
model = LinearRegression()
model.fit(X_days, y_scores)
future_score = model.predict([[max_day + 90]])
🧪 Testing
@pytest.fixture
def client():
app = create_app("app.config.Config")
with app.test_client() as client:
with app.app_context():
db.create_all()
yield client
with app.app_context():
db.drop_all()
def test_health(client):
resp = client.get("/health/")
assert resp.status_code == 200
assert resp.json["status"] == "ok"
🚀 Comandos
# Instalación
pipenv --python 3.11
pipenv install
# Base de datos
docker compose up -d
pipenv run flask db upgrade
# Ejecución
pipenv run flask run
pipenv run celery -A app.celery_app worker -l info
pipenv run celery -A app.celery_app beat -l info
# CLI
pipenv run flask create-project "All Ritmo" allritmocancun.com
✅ Roadmap
| Prioridad | Feature |
|---|---|
| 1 | Migraciones Alembic |
| 2 | Alertas por email (SMTP) |
| 3 | Autenticación JWT |
| 4 | Lighthouse CI / Web Vitals |
| 5 | Observabilidad (Prometheus/Grafana) |