Dev.to WebDev 🛠 Dev 👁 0 📖 4 min read

Auditoría técnica de SEO con Lighthouse CLI y Node.js (sin depender de PageSpeed Insights)

El problema Revisar manualmente PageSpeed Insights o Search Console página por página no escala. Si manejas 20, 50 o 200 URLs (un e-commerce, un blog grande, un sitio multi-idioma), necesitas automatizar la auditoría t

Auditoría técnica de SEO con Lighthouse CLI y Node.js (sin depender de PageSpeed Insights)

El problema

Revisar manualmente PageSpeed Insights o Search Console página por página no escala. Si manejas 20, 50 o 200 URLs (un e-commerce, un blog grande, un sitio multi-idioma), necesitas automatizar la auditoría técnica: performance, SEO score, accesibilidad y buenas prácticas, todo en un solo reporte.

Aquí vamos a montar un script en Node que:

  1. Corre Lighthouse por línea de comandos sobre una lista de URLs.
  2. Extrae las métricas clave (Core Web Vitals, score SEO, errores de indexación).
  3. Genera un CSV consolidado que puedes abrir en Sheets/Excel o pasar a un dashboard.

Requisitos

node -v   # v18 o superior recomendado
npm i -g lighthouse chrome-launcher

lighthouse trae su propio Chrome headless por debajo, así que no necesitas instalar Chrome aparte en la mayoría de entornos (aunque en CI a veces sí hay que apuntar a un binario existente).

Paso 1: correr Lighthouse desde la CLI

Lo más simple, para una sola URL:

lighthouse https://tusitio.com \
  --output json \
  --output-path ./reports/home.json \
  --chrome-flags="--headless" \
  --only-categories=performance,seo,accessibility,best-practices

Esto genera un JSON con todo el detalle. El campo que más nos interesa para SEO técnico es categories.seo.score y las auditorías individuales dentro de audits, como is-crawlable, robots-txt, hreflang, canonical y structured-data.

Paso 2: automatizar varias URLs con un script de Node

Creamos un archivo audit.js que recorre un array de URLs, llama a Lighthouse programáticamente (no como proceso hijo, sino usando su API de Node) y consolida los resultados.

// audit.js
import lighthouse from 'lighthouse';
import * as chromeLauncher from 'chrome-launcher';
import fs from 'fs';

const urls = [
  'https://tusitio.com',
  'https://tusitio.com/blog',
  'https://tusitio.com/servicios',
  'https://tusitio.com/contacto',
];

async function auditUrl(url, chrome) {
  const options = {
    logLevel: 'error',
    output: 'json',
    onlyCategories: ['performance', 'seo', 'accessibility', 'best-practices'],
    port: chrome.port,
  };

  const runnerResult = await lighthouse(url, options);
  const { categories, audits } = runnerResult.lhr;

  return {
    url,
    performance: Math.round(categories.performance.score * 100),
    seo: Math.round(categories.seo.score * 100),
    accessibility: Math.round(categories.accessibility.score * 100),
    bestPractices: Math.round(categories['best-practices'].score * 100),
    lcp: audits['largest-contentful-paint'].displayValue,
    cls: audits['cumulative-layout-shift'].displayValue,
    tbt: audits['total-blocking-time'].displayValue,
    isCrawlable: audits['is-crawlable'].score === 1,
    robotsTxtValid: audits['robots-txt'] ? audits['robots-txt'].score === 1 : null,
    hasCanonical: audits['canonical'] ? audits['canonical'].score === 1 : null,
    hasStructuredData: audits['structured-data']
      ? audits['structured-data'].score !== 0
      : null,
  };
}

async function run() {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const results = [];

  for (const url of urls) {
    console.log(`Auditando ${url}...`);
    try {
      const result = await auditUrl(url, chrome);
      results.push(result);
    } catch (err) {
      console.error(`Error auditando ${url}:`, err.message);
      results.push({ url, error: err.message });
    }
  }

  await chrome.kill();

  fs.writeFileSync('./reports/audit-results.json', JSON.stringify(results, null, 2));
  console.log('Auditoría completa. Ver ./reports/audit-results.json');

  return results;
}

run();

Puntos a notar:

  • Usamos chromeLauncher.launch() una sola vez y reusamos el mismo puerto para todas las URLs, en vez de abrir un Chrome nuevo por cada una — esto es mucho más rápido cuando auditas varias páginas.
  • audits['is-crawlable'] te dice directamente si Google puede indexar la página (detecta noindex, bloqueos por robots, etc.) — esto conecta directo con el error #1 de "sitio bloqueado para Google".
  • structured-data valida si hay schema markup presente, relevante para AEO además de SEO tradicional.

Paso 3: exportar a CSV para revisar rápido

Un JSON con 50 URLs es difícil de escanear a simple vista. Convertimos a CSV:

// to-csv.js
import fs from 'fs';

const data = JSON.parse(fs.readFileSync('./reports/audit-results.json', 'utf-8'));

const headers = [
  'url', 'performance', 'seo', 'accessibility', 'bestPractices',
  'lcp', 'cls', 'tbt', 'isCrawlable', 'robotsTxtValid',
  'hasCanonical', 'hasStructuredData',
];

const rows = data.map((row) =>
  headers.map((h) => JSON.stringify(row[h] ?? '')).join(',')
);

const csv = [headers.join(','), ...rows].join('\n');
fs.writeFileSync('./reports/audit-results.csv', csv);
console.log('CSV generado en ./reports/audit-results.csv');

Con esto ya tienes un archivo que puedes abrir en cualquier hoja de cálculo y ordenar por seo o performance para ver qué páginas necesitan atención primero.

Paso 4 (opcional): correrlo en CI

Si quieres que esto corra automáticamente en cada deploy, un job simple en GitHub Actions:

# .github/workflows/lighthouse-audit.yml
name: Lighthouse Audit
on:
  schedule:
    - cron: '0 6 * * 1' # cada lunes 6am
  workflow_dispatch:

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 18
      - run: npm install
      - run: node audit.js
      - run: node to-csv.js
      - uses: actions/upload-artifact@v4
        with:
          name: seo-audit-report
          path: reports/

Así tienes un historial de auditorías cada semana sin tocar nada manualmente, y puedes detectar regresiones (por ejemplo, si un deploy rompió el robots.txt o metió un noindex por error).

Qué mirar primero en los resultados

De las métricas que salen del script:

  • isCrawlable: false es la alarma más urgente — significa que esa página literalmente no puede ser indexada.
  • lcp por encima de 2.5s ya pone en desventaja competitiva según los umbrales de Core Web Vitals.
  • hasStructuredData: false en páginas clave (producto, servicio, artículo) es una oportunidad fácil de cerrar con JSON-LD.

Cierre

Automatizar esto no reemplaza una auditoría profesional completa (perfil de enlaces, intención de búsqueda, contenido duplicado entre dominios), pero sí te da visibilidad continua sobre los problemas técnicos que rompen el SEO silenciosamente — que suelen ser los que más impacto tienen y menos se detectan a tiempo.

Si prefieren que un equipo humano cruce estos datos con el resto de la estrategia (SEO, AEO, contenido, enlaces), la gente de Agencia Digital ECW hace auditorías de este tipo para negocios en Bogotá.

¿Ya usan Lighthouse en su pipeline de CI, o prefieren herramientas como Sitebulb o Screaming Frog para esto? Me interesa saber qué stack usan para auditorías recurrentes.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.