Case Study — Santifer iRepair

SEO Programático: 4.700+ Páginas desde un ERP

Cómo generé 4.730 landing pages únicas con datos reales de producción, un CMS de 14 tablas en Airtable, y DataForSEO como motor de decisiones. 2,26M impresiones, 19K+ clicks.

Santiago Fernández de Valderrama
25 feb 202637 min de lectura

En el sector de reparación de dispositivos en España, nadie estaba haciendo SEO programático. Cada combinación de dispositivo, marca, modelo, tipo de reparación y ciudad era una oportunidad long-tail sin explotar.

La idea era simple: si alguien busca "reparar iPhone batería Sevilla", debería existir una página específica para esa búsqueda, con el precio real, el tiempo estimado y fotos de reparaciones reales. Pero crear esas páginas a mano para miles de combinaciones no era viable. Necesitaba un sistema que generase las páginas automáticamente desde el ERP, y que fuera lo suficientemente inteligente para decidir cuáles indexar y cuáles no.

Santifer iRepair fue mi negocio de reparación de dispositivos en Sevilla desde 2009. 16 años, más de 30.000 reparaciones. En 2024 decidí que la web del negocio necesitaba dejar de ser un folleto en Squarespace y empezar a capturar la demanda que ya existía en Google. Construí este sistema de SEO programático como ventaja competitiva y vendí el negocio en septiembre 2025, en su punto más alto.

En 10 segundos

  • Construí 4.730 landing pages estáticas desde un ERP de producción (precios, fotos, reseñas reales)
  • Motor de decisiones con DataForSEO: solo se indexan las páginas con volumen de búsqueda real
  • Resultado: 2,26M impresiones, 19K+ clicks orgánicos, 80% del tráfico del sitio
  • 7 meses de desarrollo, una persona, vendido en su punto más alto

La Oportunidad#

El mercado de reparación de dispositivos en España es altamente local. Los usuarios buscan servicios por ciudad, marca y tipo de reparación. Pero la mayoría de negocios del sector tenían webs genéricas: una landing para toda España, si es que tenían web.

Miles de combinaciones long-tail sin competencia real en SERPs

Intención de búsqueda transaccional clara: el usuario quiere reparar, no informarse

Ningún competidor en el sector estaba usando SEO programático en España (2024)

El ERP ya tenía todos los datos necesarios: 867 modelos, precios, tiempos, fotos reales

La taxonomía natural del negocio (dispositivo, marca, modelo, reparación, ciudad) se mapea directamente a URLs

Queries reales de GSC

QueryClicksImp.CTRPos.
reparacion moviles sevilla421,9472,2%2,5
reparar iphone sevilla513,3141,5%12,9
reparacion iphone sevilla464,3151,1%5,2
cambiar bateria pixel 6a517556,8%6,4
servicio técnico garmin sevilla365346,7%6,5
cambiar bateria apple watch373,9670,9%11,7

Los Números#

2,26M

Impresiones

Total acumulado en Google Search Console

19K+

Clicks orgánicos

Tráfico real desde búsqueda orgánica

4.730

Páginas con tráfico

De miles generadas, 4.084 indexables en sitemap, 4.730 recibieron impresiones

10,8x

Crecimiento

De 202 a 2.193 clicks/mes en 11 meses

80%

Clicks desde pSEO

El tráfico orgánico del sitio viene de páginas programáticas

7

Meses

1 persona. CMS, pipelines, DataForSEO, 26K imágenes y deploy

Desarrollo: marzo → octubre 2024 (7 meses). Una persona. CMS, scripts de generación, pipeline de imágenes, integración con DataForSEO y deploy — todo en paralelo. Lanzamiento en producción en octubre 2024. Si lo construyera hoy con Claude Code, tardaría una semana.

Homepage de santiferirepair.es
santiferirepair.es: homepage generada con Astro SSG. Buscador de dispositivos, categorías y marcas.

Dos Estrategias, Un Sistema#

El proyecto empezó con ambición nacional, pero Google tiene criterio propio. Las búsquedas de reparación tienen intención local muy fuerte. Google prioriza resultados con proximidad geográfica, así que las páginas nacionales sin ciudad competían peor. La solución: una estrategia dual. Páginas locales para Sevilla (donde está la tienda física) y páginas nacionales de nicho para reparaciones específicas donde la localización importa menos.

Páginas Locales (Sevilla)

Combinaciones de dispositivo + marca + reparación con "/sevilla". Google las prioriza por proximidad al negocio físico. Son las que más tráfico generan.

/reparar-smartwatch/sevilla615 clicks · 3,7%
/reparar-iphone/bateria/sevilla581 clicks · 2,5%
/reparar-apple-watch/sevilla562 clicks · 2,7%
/reparar-iphone/sevilla466 clicks · 0,6%
/reparar-ipad/sevilla370 clicks · 1,2%

Páginas Nacionales (sin ciudad)

Reparaciones de nicho donde la localización importa menos. El formato "cambiar-{pieza}-{marca}-{modelo}" captura búsquedas informacionales que terminan en conversión.

/cambiar-bateria-google-pixel-6a372 clicks · 5,0%

La Arquitectura#

El sistema tiene cuatro capas. Airtable funciona como CMS headless con 14 tablas y ~60 campos por tabla. El ERP alimenta los datos reales de producción. DataForSEO decide qué se indexa. Astro genera HTML estático con mínimo JavaScript en el cliente — solo lo imprescindible para UX (buscador, carrusel), cargado de forma lazy.

Airtable (CMS Headless)

14 tablas, ~60 campos por tabla. Jerarquía de 6 niveles: Tipo de dispositivo, Marca, Familia, Modelo, Reparación + variantes locales. Precios duales (original y compatible), herencia de imágenes, social proof en cascada.

ERP (Datos de Producción)

Alimenta Airtable con datos reales: fotos de antes/después de reparaciones reales, reseñas verificadas de clientes, stock de piezas actualizado. 867 modelos, 20+ marcas, 15+ tipos de reparación.

DataForSEO (Motor de Decisiones)

Consulta volúmenes de búsqueda reales para cada combinación. El campo "indexable" en Airtable se alimenta directamente de estos datos. Sin volumen, la página no se indexa.

Astro (Generación Estática)

21 templates de página. Genera HTML estático con JS mínimo lazy-loaded. 6 tipos de JSON-LD por página. SEO de imágenes con inyección EXIF. Deploy en Cloudflare CDN.

Taxonomía de URLs#

La web usa 6 patrones de URL, cada uno correspondiente a un nivel de la taxonomía del negocio. Los patrones locales (con /sevilla) capturan intención local. Los patrones nacionales (sin ciudad) capturan búsquedas de nicho.

/reparar-{dispositivo}/{ciudad}

[object Object]

/reparar-{dispositivo}/{marca}/{ciudad}

[object Object]

/reparar-{dispositivo}/{reparación}/{ciudad}

[object Object]

/reparar-{dispositivo}/{marca}/{reparación}/{ciudad}

[object Object]

/reparar-{dispositivo}/{modelo}/{reparación}

[object Object]

/cambiar-{reparación}-{marca}-{modelo}

[object Object]

Rutas Premium para Apple

El negocio empezó en 2009 reparando exclusivamente dispositivos Apple — la gente nos conocía por ello. Apple tiene el mayor volumen de búsqueda y las rutas más cortas reflejan esa prioridad: /iphone/14-pro en vez de /reparar-movil/apple/iphone-14-pro. Más corto, más limpio, mejor CTR. Un solo booleano cambia todo:

// Apple: /iphone/14-pro (corto, limpio, mejor CTR)
const records = await getRecordsModelos(true);  // modoApple = true → vista CMSAstro(Apple)
return records.map(r => ({
  params: { paramMarcaApple: r.paramMarca, paramModeloApple: r.paramModelo },
}));

// Genérico: /reparar-movil/samsung/galaxy-s21
const records = await getRecordsModelos();  // modoApple = false → vista CMSAstro
return records.map(r => ({
  params: { paramTipo: r.paramTipo, paramMarca: r.paramMarca, paramModelo: r.paramModelo },
}));

modoApple = true

Un solo booleano cambia la vista de Airtable (CMSAstro vs CMSAstro(Apple)) y la estructura de URLs. Misma página, mismo layout, dos sistemas de routing.

Rutas más cortas

/iphone/14-pro vs /reparar-movil/apple/iphone-14-pro. Apple es la marca dominante en reparaciones; sus rutas merecen URLs premium.

El CMS por Dentro#

Airtable no es solo una hoja de cálculo con esteroides. En este proyecto funciona como un CMS relacional completo. La clave es la jerarquía de 6 niveles que refleja exactamente cómo funciona el negocio.

TablaPropósitoCampos clave
Tipos de DispositivoNivel raíz de la taxonomíaslug, nombre, descripción SEO, orden de menú
MarcasMarcas vinculadas a tipos de dispositivoslug, nombre, logo, tipos compatibles
FamiliasAgrupación de modelos (ej: iPhone 14 serie)slug, imagen principal (heredable), marca
ModelosDispositivos concretos con preciosslug, familia, imagen (hereda de familia si no tiene), año
ReparacionesTipos de reparación por modeloslug, precio original, precio compatible, tiempo, indexable
Variantes LocalesPáginas con ciudad para SEO localmodelo + reparación + ciudad, precio ajustado, disponibilidad
Jerarquía de tablas en Airtable — CMS del SEO programático
Las 14 tablas del CMS conectadas al Business OS de 12 bases. Jerarquía de 6 niveles desde tipo de dispositivo hasta variante local.

Este CMS de 14 tablas es parte de un Business OS más amplio de 12 bases de Airtable que gestionaba todo el negocio: inventario, CRM, contabilidad, RRHH y más. Lee el case study completo del Business OS →

Patrones clave del CMS

Precios duales

Cada reparación tiene precio con pieza original y precio con pieza compatible. El usuario elige en la landing.

Herencia de imágenes

Si un modelo no tiene imagen propia, hereda la de su familia. Reduce trabajo de mantenimiento sin dejar páginas sin visual.

Social proof en cascada

Las reseñas se vinculan a nivel de modelo, familia o marca. Una reseña de "iPhone 14 Pro" aparece en todas las reparaciones de ese modelo.

Bridge mode

Reparaciones descatalogadas no se eliminan: se marcan como "bridge" y redirigen a la alternativa más cercana. Cero 404s, cero pérdida de autoridad.

Página de categoría Samsung en santiferirepair.es
Página de categoría generada automáticamente. Cada marca tiene su landing con modelos, precios y reseñas.

Anatomía de una Página#

Cada una de las 4.700+ páginas se genera desde un template, pero el contenido es único porque viene del ERP. No es texto generado por IA ni contenido de relleno: son datos de producción.

Breadcrumb + Schema

Navegación jerárquica que refleja la taxonomía. Genera BreadcrumbList JSON-LD automáticamente.

Precios Reales

Precio original y compatible, actualizados desde el ERP. El usuario ve exactamente lo que va a pagar.

Tiempo Estimado

Basado en datos históricos reales del taller. No es una estimación genérica.

Fotos Antes/Después

Imágenes reales de reparaciones completadas. EXIF inyectado con geolocalización y metadata SEO.

Reseñas Verificadas

Reviews de clientes reales, vinculadas al modelo o familia. Con schema Review y AggregateRating.

6 Tipos de JSON-LD

LocalBusiness, Product, Service, BreadcrumbList, FAQPage, AggregateRating. Cada página tiene markup completo.

Campos de una reparación en Airtable
Cada reparación tiene ~60 campos: precios duales, flag indexable, specs del modelo que alimentan el copy dinámico.
Anatomía de una página programática de reparación
Ejemplo real: página de reparación generada desde el ERP. Precios duales, reseñas reales, JSON-LD completo.
Hero de una página de reparación en santiferirepair.es
Hero de página de reparación: precio dual (original/compatible), CTA de cita, y breadcrumb semántico.

Flujo de Conversión por Página

Cada página sigue una estructura de conversión diseñada para llevar al usuario del descubrimiento a la acción:

Hero con precio dual (original/compatible) + CTA de cita directa

Specs del modelo personalizadas: cámara, batería, tecnologías del dispositivo

Galería de fotos reales de reparaciones completadas (antes/después)

Reseñas verificadas de clientes vinculadas al modelo o familia

FAQ generada desde los datos del ERP (preguntas reales de clientes)

CTA final con mapa de la tienda y botón de reserva

Un usuario busca "reparar pantalla iPhone 14 Pro Sevilla". Llega a una página con precio (189€ original / 89€ compatible), tiempo estimado (45 min), 3 fotos de reparaciones reales de iPhone 14 Pro, y 12 reseñas verificadas. No necesita navegar a otra página — toda la información para decidir está ahí.

Copy Dinámico por Modelo

Cada modelo de dispositivo tiene un microcopy único generado a partir de sus specs de hardware reales. Un campo en Airtable almacena las características técnicas (cámara, batería, procesador, resistencia al agua) y un prompt genera una descripción que varía según el modelo. Un iPhone 14 Pro habla de su cámara de 48MP y su pantalla ProMotion. Un Pixel 7a destaca su chip Tensor y fotografía computacional. No es contenido genérico: es contenido que solo aplica a ESE modelo, basado en datos reales de hardware. Misma plantilla, contenido único en cada página.

Copy dinámico del iPhone 12: specs reales de hardware generan texto único por modelo
Página del iPhone 12: almacenamiento, RAM, pantalla Super Retina XDR OLED, batería Li-Ion 2815mAh. Todo extraído de las specs reales del modelo en Airtable.

Precios Sincronizados desde el ERP

El mismo CMS que genera el copy también sincroniza los precios de cada reparación en tiempo real. Airtable funciona como puente entre el ERP (donde se actualizan los costes de piezas y márgenes) y la web. Cada modelo muestra un rango de precios calculado desde el mínimo y máximo de sus reparaciones disponibles. Cuando un precio cambia en el ERP, la web se regenera con el precio actualizado — sin intervención manual.

Página de categoría iPhone con rangos de precios sincronizados desde el ERP
Página de categoría: cada tarjeta muestra "Desde X € hasta Y €", calculado automáticamente desde los precios de reparación del ERP.
let cadenaPrecio = '';
if (mostrarPrecio.startsWith('desde') && detail.precioMinCard) {
  cadenaPrecio = `Desde ${detail.precioMinCard}`;
}
if (mostrarPrecio === 'desdeHasta' && detail.precioMaxCard) {
  cadenaPrecio = `${cadenaPrecio} hasta ${detail.precioMaxCard}`;
}
if (mostrarPrecio === 'exacto' && detail.precioMinCard) {
  cadenaPrecio = detail.precioMaxCard
    ? `Desde ${detail.precioMinCard} hasta ${detail.precioMaxCard}`
    : `${detail.precioMinCard}`;
}

Tres modos de precio

"desde" (solo mínimo), "desdeHasta" (rango completo), "exacto" (precio fijo o rango con CTA). El modo se configura por tipo de página.

precioMinCard / precioMaxCard

Campos calculados en Airtable: agregan min y max de todas las reparaciones disponibles para ese modelo. Si el coste de una pieza cambia en el ERP, estos campos se recalculan automáticamente.

El buscador no es un simple filtro de texto. Es un componente con un algoritmo de scoring propio — sin librerías externas como Fuse.js. El usuario escribe "iphone 12 pro" y el sistema puntúa los 867 modelos: +20 si contiene todas las palabras, +30 si es coincidencia exacta, +10 si el nombre empieza por la búsqueda, y penaliza palabras extra en el nombre del modelo. El resultado: los 6 modelos más relevantes, ordenados por puntuación.

Buscador en homepage: "12 pro" muestra resultados de todas las marcas
Home: "12 pro" → Xiaomi, Apple, Xiaomi...
Buscador en página iPhone: "13" solo muestra modelos iPhone
Página iPhone: "13" → solo iPhones

Lo interesante es que el buscador es sensible al contexto. En la homepage busca en los 867 modelos de todas las marcas y tipos de dispositivo. Pero en la página de una marca específica (ej: Samsung), solo busca entre modelos de esa marca. Y en la página de un tipo de dispositivo (ej: tablets), solo tablets. El mismo componente, con props de filtro (`filtroTipo`, `filtroMarca`), se comporta de forma diferente según dónde se embeba. Los modelos se cargan bajo demanda en el primer foco del input y se cachean en localStorage para que las búsquedas siguientes sean instantáneas.

El artículo describe el algoritmo. Este es el código real — 30 líneas sin dependencias externas:

function calcularPuntuacion(modelo, terminosBusqueda) {
  let puntuacion = 0;
  const nombreModelo = modelo.n.toLowerCase();

  const todasPresentes = terminosBusqueda.every(t => nombreModelo.includes(t));

  if (todasPresentes) {
    puntuacion += 20;
    const palabrasModelo = nombreModelo.split(/\s+/);
    const extras = palabrasModelo.filter(p => !terminosBusqueda.includes(p)).length;
    puntuacion -= extras * 2;

    if (nombreModelo === terminosBusqueda.join(' ')) puntuacion += 30;
    if (nombreModelo.startsWith(terminosBusqueda.join(' '))) puntuacion += 10;
  }
  return puntuacion;
}

+20 base

Todos los términos deben estar presentes. "iphone 12 pro" coincide con "Apple iPhone 12 Pro" pero no con "Apple iPhone 12".

-2 por palabra extra

Penaliza nombres largos. "Apple iPhone 12 Pro Max" puntúa menos que "Apple iPhone 12 Pro" para la query "iphone 12 pro".

+30 exacto, +10 starts-with

Coincidencias exactas dominan. 30 líneas, cero dependencias, superando a Fuse.js para este dominio concreto.

El Motor de Decisiones#

El sistema genera miles de páginas (muchas más de las 4.730 que recibieron tráfico), pero no todas merecen ser indexadas. Si nadie busca "reparar cámara delantera iPhone 11", esa página no debería competir en Google — pero sí debe existir para el usuario que navega desde la página del iPhone 11 y necesita esa reparación concreta. La clave es separar SEO de UX. El motor de decisiones consulta DataForSEO para obtener volumen de búsqueda real de cada combinación, y el resultado se almacena en el campo "indexable" de airtable.ts.

1

Volumen de búsqueda alto (DataForSEO) → Página indexable

Si la keyword tiene volumen significativo, la página se genera con meta robots "index, follow", se incluye en el sitemap, y recibe enlazado interno prioritario.

2

Volumen de búsqueda bajo o nulo → Página noindex (solo UX)

La página existe para la experiencia de usuario y navegación interna, pero lleva meta robots "noindex" y no aparece en el sitemap.

3

Sin datos de servicio en el ERP → No se genera página

Si no hay datos reales del servicio (precio, disponibilidad), la página no se genera. Cero contenido thin.

4

Reparación descatalogada → Bridge redirect

La página se marca como "bridge" y redirige 301 a la alternativa más cercana. Preserva la autoridad acumulada.

El sistema genera miles de páginas en total. De esas, 4.084 están en el sitemap como indexables. 4.730 recibieron alguna impresión de Google. El resto no se indexa, pero sigue existiendo para la experiencia del usuario que navega la web.

Campo indexable en Airtable alimentado por DataForSEO
Motor de decisiones: DataForSEO alimenta el campo indexable. Sin volumen → noindex.

Optimización del Crawl Budget#

Con 4.700+ páginas, gestionar el crawl budget es crítico. Google no debería perder tiempo rastreando páginas que no van a posicionar. Las 700+ reglas de robots.txt se suman a las 1.009 redirecciones heredadas de la migración.

Noindex selectivo con DataForSEO

El campo "indexable" en Airtable se alimenta directamente de los datos de volumen de DataForSEO. Las páginas sin volumen llevan noindex. No es una decisión arbitraria: es data-driven.

Sitemap filtrado (4.084 URLs)

El sitemap.xml solo incluye URLs indexables. De las 4.730 páginas con impresiones, solo 4.084 están en el sitemap. Google no descubre las demás a través de este canal.

Estructura de URLs con 6 patrones

Cada nivel de la taxonomía tiene un patrón de URL predecible. Google entiende la jerarquía sin necesidad de heurísticas complejas.

Enlazado interno contextual

Las páginas indexables reciben más enlaces internos. Las páginas de ciudad enlazan a reparaciones disponibles, los modelos enlazan a sus reparaciones, y las familias agregan sus modelos.

Bridge redirects para descatalogados

En lugar de devolver 404 cuando una reparación se descataloga, se redirige 301 a la alternativa más cercana. 700+ reglas de redirección en vercel.json. Cero pérdida de autoridad, cero enlaces rotos.

Patrón "Noindex Seguro"

El noindex accidental es uno de los errores más caros en SEO: una sola línea puede desindexar miles de páginas. Este es el patrón de seguridad que lo previene:

{NOINDEXCUIDADO &&
  NOINDEXCUIDADO === 'Estoy absolutamente seguro que no quiero hacer no index por eso pongo esta cadena' && (
    <meta name="robots" content="noindex" />
  )}

String, no boolean

Un booleano puede ser true por accidente (campo incorrecto, valor por defecto, error de migración). Un string de 80 caracteres en español requiere intención deliberada.

Doble guarda

El prop debe ser truthy Y coincidir con el string exacto. Incluso si se establece a "true" o 1, el tag noindex no se renderiza.

Un booleano puede ser truthy por accidente. Un string de 80 caracteres en español requiere intención deliberada. En 2 años de producción, cero noindex accidentales.

Pipeline de Build#

El pipeline transforma los datos del CMS en una web estática lista para desplegar. Todo está automatizado. schema.ts tiene 1.677 líneas que mapean la jerarquía de Airtable a tipos de Astro.

1

Airtable API

Extracción de registros con retry y backoff exponencial

2

Schema Mapping

1.677 líneas que transforman la jerarquía de 6 niveles en tipos TypeScript

3

Cache de Reviews

Las reseñas se cachean para no hacer llamadas redundantes a la API

4

getStaticPaths

Genera las rutas estáticas desde la taxonomía completa

5

ReparacionLayout

21 templates de página que renderizan según el nivel de la taxonomía

6

Astro SSG

Build estático con mínimo JavaScript lazy-loaded

7

Optimización

Imágenes comprimidas, EXIF inyectado, sitemap filtrado, internal linking

8

Cloudflare CDN

Deploy con invalidación de caché e edge caching global

Retry con Backoff Exponencial

El pipeline comienza con la extracción de datos de Airtable. Con 14 tablas y miles de registros, las llamadas a la API necesitan ser resilientes. Esta función genérica de retry sostiene todo el build:

function delay(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function retryWithBackoff<T>(
  operation: () => Promise<T>,
  retries: number = 5,
  delayTime: number = 500
): Promise<T> {
  try {
    return await operation();
  } catch (error: any) {
    if (retries > 0 && (error.statusCode === 502 || error.statusCode === 503)) {
      await delay(delayTime);
      return retryWithBackoff(operation, retries - 1, delayTime * 2);
    }
    throw error;
  }
}

Generic <T>

Una sola función para todos los tipos de registro (ITipos, IMarcas, IModelos, IReparaciones...).

Solo 502/503

Solo reintenta errores de servidor (Bad Gateway, Service Unavailable). Errores de cliente (400, 401) fallan inmediatamente.

delayTime * 2

Backoff exponencial: 500ms → 1s → 2s → 4s → 8s. 5 reintentos = 15,5s máximo antes de fallar.

Sistema de Cache de Reseñas

Las reseñas son las llamadas más caras del build: 4.700+ páginas podrían necesitarlas, pero solo hay 607 en total. La solución: cargar todas una vez al inicio del build y que cada página consulte desde memoria.

let caches: { [key: string]: Reseña[] | undefined } = {};

async function loadReseñas(baseName: string, cacheKey: string): Promise<void> {
  if (caches[cacheKey]) return;

  const fetchOperation = () => new Promise<Reseña[]>((resolve, reject) => {
    const allRecords: Reseña[] = [];
    base(baseName)
      .select({ view: 'CMSAstro', fields: ReseñaFields })
      .eachPage(
        (records, fetchNextPage) => {
          records.forEach(record => allRecords.push(mapReseñaFields(record.fields)));
          fetchNextPage();
        },
        (err) => err ? reject(err) : resolve(allRecords)
      );
  });

  caches[cacheKey] = await retryWithBackoff(fetchOperation);
}

export async function ensureCachesLoaded(): Promise<void> {
  await Promise.all([
    loadReseñas('Reseñas sincronizar Astro', 'cachedReseñas'),
    loadReseñas('Reseñas Internas', 'cachedReseñasInternas')
  ]);
}

// Se ejecuta al importar el módulo
ensureCachesLoaded().catch(console.error);

Module-level call

ensureCachesLoaded() se ejecuta cuando se importa el módulo. En Astro SSG, todas las reseñas se cargan en memoria antes de que comience la generación de páginas.

Promise.all

Ambas fuentes (Google My Business + encuestas internas) se cargan en paralelo.

Trade-off: O(n) find

Las páginas buscan por ID con .find(). Escaneo lineal, pero con 607 reseñas elimina cientos de llamadas API. El trade-off correcto para un build pipeline.

Pipeline de Contenido Automatizado#

Generar miles de páginas es solo la mitad. Cada página necesita imágenes, metadata y copy únicos. Un conjunto de 8 scripts Node.js (1.411 líneas) automatiza toda la producción de contenido visual y textual sin intervención manual. Todo conectado a las 12 bases del Business OS en Airtable. Resultado: más de 26.000 imágenes generadas automáticamente.

Generación Paramétrica de Imágenes

De 1 foto de dispositivo se generan 18 variantes automáticas: una por tipo de reparación (pantalla, batería, cámara, puerto de carga...) + una imagen genérica. La foto del dispositivo se extrae de GSM Arena y se compone con overlays PNG de cada reparación. 867 modelos × 18 variantes = 15.500+ imágenes únicas, sin tocar Photoshop.

Inyección EXIF para SEO Local

Cada imagen recibe coordenadas GPS de Sevilla y una descripción SEO inyectada en los metadatos EXIF. Google Images lee estos datos para posicionar en búsquedas locales. Automatizado con piexifjs y codificación UCS-2.

Pipeline de Fotos Antes/Después

10.000+ fotos de reparaciones reales procesadas automáticamente. Se descargan de Airtable, se redimensionan, se aplica blur para fondos, se componen en WebP, y las URLs resultantes se escriben de vuelta en Airtable. Pipeline ETL bidireccional: Airtable → procesamiento → Airtable.

Copy Dinámico por Modelo

Cada modelo tiene un campo con sus specs de hardware (cámara, batería, procesador). Un prompt convierte esas specs en microcopy único para cada página. No es IA generando contenido: es IA describiendo datos reales de hardware. Cada página es diferente porque cada dispositivo es diferente.

Cada imagen recibe las coordenadas GPS de la tienda inyectadas en los metadatos EXIF. Google Images usa estos datos para posicionar imágenes en búsquedas locales:

// Coordenadas de la tienda en Sevilla
gps[piexif.GPSIFD.GPSLatitude] = convertToDMS(37.38606);
gps[piexif.GPSIFD.GPSLatitudeRef] = 'N';
gps[piexif.GPSIFD.GPSLongitude] = convertToDMS(-5.98585);
gps[piexif.GPSIFD.GPSLongitudeRef] = 'W';

// Descripción SEO en ambos campos EXIF
exifObj['0th'][piexif.ImageIFD.ImageDescription] = description;

// UCS-2 para soporte Unicode (tildes, ñ)
const userComment = Buffer.concat([
  Buffer.from('UNICODE\0\0\0', 'ascii'),
  encodeUCS2(description),
]);
exifObj['Exif'][piexif.ExifIFD.UserComment] = userComment.toString('binary');

GPS fijas

Cada imagen de reparación recibe las coordenadas exactas de la tienda en Sevilla. Google Images usa EXIF GPS para resultados locales.

Descripción dual

El texto SEO va en ImageDescription (EXIF estándar) y UserComment (EXIF extendido). Diferentes parsers leen diferentes campos.

UCS-2 encoding

Los caracteres españoles (tildes, ñ) requieren codificación Unicode. El spec EXIF exige UCS-2 con prefijo UNICODE\0\0\0.

Pipeline de imágenes en Airtable
Pipeline de imágenes: 1 foto de GSM Arena → 18 composiciones automáticas con overlays de reparación. Todo sincronizado con el Business OS.

Cascada de Contenido: Una Reseña, Seis Páginas

El sistema hereda contenido automáticamente a través de la taxonomía. Una reseña de "reparación de pantalla de iPhone 12" no solo aparece en esa página — aparece en todas las páginas donde es relevante:

PáginaNivel
/reparar-movil/apple/iphone-12/pantalla/sevillaModelo + reparación + ciudad
/reparar-iphone/pantalla/sevillaDispositivo + reparación + ciudad
/reparar-movil/apple/sevillaDispositivo + marca + ciudad
/reparar-iphone/sevillaDispositivo + ciudad
/reparar-movil/pantalla/sevillaDispositivo + reparación + ciudad
/reparar-movil/sevillaDispositivo + ciudad

La misma lógica aplica a las fotos antes/después: una foto de reparación de pantalla de iPhone 12 aparece en todas las páginas de esa rama de la taxonomía. Esto multiplica el contenido único sin duplicar ni generar nada artificialmente. Cada página acumula más social proof y contenido visual a medida que el negocio crece.

26.000+ imágenes generadas automáticamente. 867 modelos con 18 variantes cada uno. 10.000+ fotos de reparaciones reales. Cero intervención manual. Las 12 bases del Business OS alimentan el pipeline completo.

Explora los scripts del pipeline en GitHub →

Dentro del Pipeline de Imágenes#

La sección anterior describe el pipeline a alto nivel. Aquí se ve exactamente cómo funciona: las plantillas reales, el código de composición, y el resultado de aplicarlo a 867 modelos distintos.

Las Plantillas de Overlay

Cada tipo de reparación tiene un overlay PNG de 384×256 píxeles. El overlay muestra visualmente qué pieza se repara: una pantalla rota, una batería, una cámara... Son 17 plantillas en total, cada una diseñada para superponerse sobre la foto de cualquier dispositivo.

Overlay de reparación de pantallaOverlay de reparación de pantalla — iPhone 14 Pro
Overlay de reparación de pantalla
Overlay de cambio de bateríaOverlay de cambio de batería — iPad Air 5
Overlay de cambio de batería
Overlay de cámara traseraOverlay de cámara trasera — Pixel 7a
Overlay de cámara trasera
Overlay de puerto de cargaOverlay de puerto de carga — Huawei P30 Pro
Overlay de puerto de carga
Overlay de tapa traseraOverlay de tapa trasera — OnePlus 11
Overlay de tapa trasera
Overlay de cambio de cristalOverlay de cambio de cristal — Apple Watch Series 7
Overlay de cambio de cristal

El Proceso de Composición

Cada imagen de reparación se genera en 6 pasos, completamente automatizado con un script Node.js y Sharp.js:

1

Descargar foto del dispositivo

Se extrae la foto oficial del dispositivo desde GSM Arena y se almacena temporalmente.

2

Crear canvas blanco 384×256

Sharp.js crea una imagen base en blanco de 384×256 píxeles con canal alpha.

3

Superponer el overlay PNG

La plantilla de reparación (pantalla, batería, etc.) se compone como primera capa sobre el canvas.

4

Centrar el dispositivo en x=96

La foto del dispositivo se redimensiona proporcionalmente y se centra en la posición x=96, dejando espacio para el overlay a la derecha.

5

Exportar a WebP

El resultado se exporta como WebP optimizado. Cada imagen pesa ~5-8 KB.

6

Repetir ×17 reparaciones + hero

El proceso se repite para los 17 tipos de reparación más una imagen genérica (hero) de 256×256. Total: 18 imágenes por modelo.

El Código Real

Este es el fragmento real del script generarImagenesReparacionesModelos.mjs que genera cada imagen de reparación:

await sharp({
  create: {
    width: 384, height: 256,
    channels: 4,
    background: { r: 255, g: 255, b: 255, alpha: 1 }
  }
})
  .png()
  .composite([
    { input: overlayPath },
    { input: devicePhoto,
      top: Math.round(top),
      left: Math.round(left) }
  ])
  .webp()
  .toFile(outputPath)

Canvas

Crea una imagen en blanco de 384×256 con fondo blanco y canal alpha. Este es el lienzo sobre el que se compone todo.

Orden de composición

Primero el overlay (plantilla de reparación), después la foto del dispositivo. El orden importa: el overlay queda detrás del dispositivo.

Posicionamiento

La foto del dispositivo se centra verticalmente y se posiciona en x≈96. Esto deja espacio visual para que el overlay de reparación sea visible a la derecha.

1 Foto → 18 Variantes

A partir de una sola foto del iPhone 14 Pro, el pipeline genera automáticamente 18 imágenes únicas: una imagen hero genérica y 17 variantes de reparación. Cada variante combina la foto del dispositivo con un overlay específico.

iPhone 14 Pro — imagen hero genérica generada automáticamente
Imagen hero: la foto del iPhone 14 Pro centrada en un canvas de 256×256, sin overlay.
Cambiar pantalla iPhone 14 Pro
Cambiar batería iPhone 14 Pro
Cambiar cámara trasera iPhone 14 Pro
Cambiar puerto de carga iPhone 14 Pro
Cambiar tapa trasera iPhone 14 Pro
Cambiar cristal iPhone 14 Pro
Cambiar altavoz iPhone 14 Pro
Cambiar micrófono iPhone 14 Pro
Cambiar auricular iPhone 14 Pro

9 de las 17 variantes generadas automáticamente para el iPhone 14 Pro. Cada imagen combina la foto real del dispositivo con un overlay de reparación específico.

Mismo Pipeline, Diferente Dispositivo

El mismo proceso se aplica a cualquier dispositivo. La foto cambia, los overlays son los mismos. Esto es lo que permite escalar a 867 modelos sin trabajo manual.

iPhone 14 Pro — hero
Samsung Galaxy S23 Ultra — hero
Xiaomi 12 — hero
Cambiar pantalla iPhone 14 Pro
Cambiar pantalla Samsung Galaxy S23 Ultra
Mismo overlay de "cambiar pantalla", diferente dispositivo. La plantilla es idéntica — lo que cambia es la foto del modelo.

La Escala

867

Modelos

Dispositivos únicos con imágenes generadas

17

Overlays

Plantillas de reparación (pantalla, batería, cámara...)

18

Imgs/modelo

17 reparaciones + 1 hero por dispositivo

15.606

Composites

Total de imágenes generadas automáticamente

Pipeline de Reseñas#

Las reseñas son el social proof más potente de cada página. Pero gestionar cientos de perfiles de clientes, sincronizar dos fuentes y cascadear la prueba social por toda la taxonomía requiere su propio pipeline.

Fuente y Sincronización

Las reseñas llegan de dos fuentes: Google My Business (verificadas públicamente) y encuestas internas post-reparación. Ambas se sincronizan a Airtable y se normalizan en un formato único.

TablaFuenteCampos clave
Reseñas sincronizar AstroGoogle My Businessquote, name, puntuacion, imageUrl, respuesta
Reseñas InternasEncuestas post-reparaciónquote, name, puntuacion, imageUrl, modelo vinculado

Procesamiento de Fotos de Perfil

Cada reseña con foto de perfil pasa por un pipeline de procesamiento automatizado:

1

Descargar foto desde Airtable

La URL de la foto de perfil se descarga desde el campo de attachments de Airtable.

2

Convertir a WebP quality 95

Sharp.js convierte la imagen a WebP con calidad 95 para preservar el detalle del rostro.

3

Guardar en /bg/res/

El archivo se guarda con nombre semántico: reparacion-{tipo}-{modelo}-{nombre}-{fecha}.webp

4

Escribir URL de vuelta en Airtable

La URL resultante se escribe de vuelta en el campo correspondiente. ETL bidireccional.

El Código Real

Este es el fragmento real de `generarImagenesReseñas.mjs` que procesa cada foto de perfil:

const imageBuffer = await fetch(attachmentUrl)
  .then(r => r.arrayBuffer())

await sharp(Buffer.from(imageBuffer))
  .webp({ quality: 95 })
  .toFile(outputPath)

// Write processed URL back to Airtable
await base('Reseñas sincronizar Astro')
  .update(record.id, {
    'imagen_procesada': outputUrl
  })

Preservación de dimensiones

No se redimensiona — la foto de perfil se mantiene en su tamaño original para máxima calidad en el carrusel.

WebP quality 95

Quality más alto que las fotos de reparación (85) porque las fotos de perfil son más pequeñas y el detalle importa más.

ETL bidireccional

Airtable es fuente Y destino: la foto se descarga, se procesa, y la URL resultante se escribe de vuelta en el registro.

Cascada de Social Proof

Las reseñas no solo aparecen en una página — se heredan por toda la taxonomía. Una reseña vinculada a un modelo se propaga a todas las páginas donde ese modelo es relevante.

Reseña de "iPhone 14 Pro" → aparece en todas las reparaciones de ese modelo, en todas las ciudades

Reseña de familia "iPhone 14" → aparece en todos los modelos de la familia (14, 14 Plus, 14 Pro, 14 Pro Max)

Reseña de marca "Apple" → aparece en páginas de marca agregadas como /reparar-movil/apple/sevilla

La cascada es automática: al vincular la reseña al nivel correcto, el build la distribuye

Cientos de Perfiles Procesados

Perfiles reales de clientes procesados por el pipeline. Cada foto fue descargada, convertida a WebP y vinculada de vuelta a Airtable.

Víctor — reparación de pantalla Samsung Galaxy A70
Sarah — reparación de auricular iPhone 11
Cristina — reparación de auricular iPhone 12
Ricardo — cambio de batería Google Pixel 4
Manolo — reparación de batería iPhone 11 Pro Max
Fernando — reparación de táctil iPad 5
Susana — reparación de pantalla iPhone XS
Teresa — reparación de pantalla iPhone 8 Plus
Luisa — reparación de batería iPhone 6 Plus

Perfiles reales de clientes. Cada foto se descarga, convierte a WebP y vincula de vuelta a Airtable.

En producción, las reseñas se renderizan en un carrusel con auto-rotación de 9 segundos, barra de progreso visual y navegación por puntos. Las top 20 reseñas son visibles directamente; el resto se expanden bajo un botón "Ver más". Todo renderizado en servidor — cero JavaScript para el carrusel base.

Carrusel CRO de reseñas reales 1/5

1 / 5

Filtro automático: solo reseñas ≥5★ con comentario van primero. Las reseñas sin texto o con menos de 5 estrellas quedan después del fold.

La Escala

600+

Perfiles procesados

Fotos de perfil convertidas a WebP

2

Fuentes

Google My Business + encuestas internas

9s

Rotación

Auto-rotación del carrusel CRO

≥5★

Prioridad

Reseñas con 5 estrellas y comentario van primero

Pipeline Antes/Después#

Cada reparación completada genera evidencia fotográfica: 4 fotos que documentan el estado del dispositivo antes y después. Este pipeline procesa esas fotos automáticamente y las distribuye por la web.

Protocolo de Captura

Cada reparación completada en el taller sigue un protocolo de 4 fotos:

1

Frontal antes

Foto del frontal del dispositivo antes de la reparación. Muestra el daño visible (pantalla rota, marcas, etc.).

2

Frontal después

Foto del frontal tras la reparación. Mismo ángulo para comparación directa.

3

Trasera antes

Foto de la parte trasera antes. Documenta el estado general del dispositivo.

4

Trasera después

Foto de la parte trasera tras la reparación. Completa la documentación visual.

El flag `difuminar` en Airtable marca las fotos que necesitan blur: pantallas encendidas con notificaciones visibles, datos personales, etc. El blur se aplica automáticamente en el pipeline.

Procesamiento Automatizado

Cada foto pasa por 6 pasos de procesamiento con Sharp.js:

1

Descargar desde Airtable

La foto original se descarga desde el campo de attachments del registro de reparación.

2

Resize a 1/4 de resolución

La imagen se redimensiona al 25% de su tamaño original. Suficiente para web, reduce el peso drásticamente.

3

Blur condicional (sigma 8)

Si el flag `difuminar` está activo, se aplica un blur gaussiano con sigma 8. Protege datos personales en pantalla.

4

Overlay blanco semi-transparente

Se compone una capa blanca al 30% sobre el fondo para mejorar contraste y darle un look consistente.

5

Exportar a WebP quality 85

Calidad 85 — más bajo que las fotos de perfil (95) porque a 1/4 de resolución el detalle extra no se nota.

6

Escribir slug de vuelta

El nombre del archivo procesado se escribe de vuelta en Airtable para que el build de Astro lo encuentre.

El Código Real

Este es el fragmento real de CasosExito.mjs que procesa cada foto de reparación:

let pipeline = sharp(inputBuffer)
  .resize({
    width: Math.round(metadata.width / 4),
    height: Math.round(metadata.height / 4)
  })

if (record.fields.difuminar) {
  pipeline = pipeline.blur(8)
}

await pipeline
  .composite([{
    input: whiteOverlay,
    blend: 'over'
  }])
  .webp({ quality: 85 })
  .toFile(outputPath)

Resize 1/4

Reduce a la cuarta parte. Una foto de 4032×3024 queda en 1008×756 — perfecto para web, reduce el peso de ~3MB a ~30KB.

Blur condicional

Solo se aplica si el campo `difuminar` está activo en Airtable. Sigma 8 difumina notificaciones y datos personales visibles en pantalla.

Quality 85 vs 95

Menor calidad que las fotos de perfil porque a 1/4 de resolución el detalle extra no aporta. Ahorra ~40% de peso por imagen.

Resultado Real: iPhone 14 Pro

Estas son fotos reales procesadas por el pipeline. Frontal y trasera, antes y después de la reparación.

iPhone 14 Pro frontal — antes de reparación
iPhone 14 Pro frontal — después de reparación
iPhone 14 Pro — frontal antes y después
iPhone 14 Pro trasera — antes de reparación
iPhone 14 Pro trasera — después de reparación
iPhone 14 Pro — trasera antes y después

Mismo Pipeline, Diferentes Marcas

El pipeline funciona igual para cualquier marca y modelo. Aquí se ve aplicado a un Samsung Galaxy A51 y un Xiaomi Redmi Note 9S.

Samsung Galaxy A51 — antes de reparación
Samsung Galaxy A51 — después de reparación
Samsung Galaxy A51 — antes y después
Xiaomi Redmi Note 9S — antes de reparación
Xiaomi Redmi Note 9S — después de reparación
Xiaomi Redmi Note 9S — antes y después

Mismo pipeline de procesamiento para cualquier marca. Las fotos se descargan, redimensionan, difuminan si es necesario y exportan a WebP automáticamente.

La Escala

10.342

Fotos procesadas

Fotos de reparaciones reales convertidas a WebP

4

Ángulos

Frontal antes/después + trasera antes/después

1/4

Resolución

Resize al 25% del original para web

Q85

WebP quality

Calidad optimizada para fotos de reparación

Curva de Crecimiento#

El proyecto se lanzó en octubre 2024. Los primeros meses fueron de indexación progresiva. Tras un pico inicial en enero, el tráfico se estancó entre febrero y junio — y no fue estacionalidad. Fue una reestructuración: la versión inicial generaba páginas nacionales y locales para cada combinación, pero eran demasiadas y Google priorizaba claramente la intención local. Redirigí las páginas nacionales a sus equivalentes locales con /sevilla, manteniendo solo las reparaciones de nicho en formato nacional (como /cambiar-bateria-iphone-11) donde la especificidad compensa la falta de localización. Mientras Google reindexaba la nueva estructura, el tráfico se mantuvo plano. Una vez consolidado, el crecimiento se disparó hasta el pico de septiembre 2025.

Curva de crecimiento en Google Search Console — clicks e impresiones
Google Search Console: clicks (azul) e impresiones (violeta) desde noviembre 2024 hasta septiembre 2025.
MesClicksImpresiones
Oct 202420216,420Lanzamiento
Nov 202474869,054
Dic 202494977,387
Ene 20251,277110,836
Feb 2025935100,558Reestructuración nacional → local
Mar 20251,191118,826
Abr 20251,027106,744
May 202593697,137
Jun 2025996121,088
Jul 20251,611150,927Post-reestructuración
Ago 20251,789164,791
Sep 20252,193164,440Pico · Venta del negocio

De 202 a 2.193 clicks/mes en 11 meses. La meseta de febrero a junio coincide con la reestructuración de URLs nacionales a locales — Google necesitó tiempo para reindexar la nueva arquitectura. Una vez consolidada, el tráfico creció un 62% en un solo mes (jun → jul). El sistema sigue en producción bajo el nuevo propietario.

Hitos de Google Search Console

Google celebra los hitos de tráfico con badges. En 3 meses pasamos de 1.2K a 2K clicks mensuales — el último badge llegó junto a la venta del negocio.

1.2K clicks
1.2K clicks18 jul 2025
1.5K clicks
1.5K clicks3 ago 2025
1.8K clicks
1.8K clicks11 sep 2025
2K clicks
2K clicks22 sep 2025

Resultados#

Métricas acumuladas desde el lanzamiento (octubre 2024 a febrero 2026), directamente de Google Search Console:

19.388

Clicks orgánicos

17 meses de operación, oct 2024 → feb 2026

1,17%

CTR medio

Sobre 2,26M de impresiones totales

4.084

URLs en sitemap

Solo las que pasan el motor de decisiones de DataForSEO

<1s

Tiempo de carga

Astro SSG con JS mínimo lazy + Cloudflare CDN

Pero estos resultados no surgieron de la nada. El punto de partida fue una web en Squarespace con problemas técnicos que había que resolver antes de construir el sistema programático.

El Punto de Partida#

La web del negocio llevaba años en Squarespace. Sin control de URLs, sin canonical tags, sin redirects custom. Lo que venía no era solo un cambio de plataforma — era una triple migración: plataforma (Squarespace → Astro), dominio (santifer.me → santiferirepair.es) y hosting (Squarespace → Vercel/Cloudflare). El primer paso fue documentar exactamente qué había que arreglar: una auditoría técnica completa de 144 páginas, realizada como Trabajo Fin de Máster del programa Big SEO.

santifer.me en Squarespace: homepage móvil
santifer.me en Squarespace: página de precios con iconos genéricos
santifer.me en Squarespace. Homepage y página de precios: iconos genéricos, sin fotos reales, sin datos del ERP.

Squarespace servía la misma página en 4 URLs diferentes (www, non-www, trailing slash, .html). Google veía 4 copias de cada página.

La Auditoría Técnica

El primer paso fue una auditoría técnica completa, realizada como Trabajo Fin de Máster del programa Big SEO. 144 páginas documentando cada aspecto técnico de la web: desde la situación del tráfico hasta la última meta description.

23,1

Posición media

↓ Declive

Visibilidad SISTRIX

21/100

Lighthouse (móvil)

33/40

Items con errores

SISTRIX: visibilidad orgánica de santifer.me en declive constante desde 2019 hasta 2024
Índice de visibilidad SISTRIX (2019-2024). Tendencia decreciente durante 5 años, de 0.036 a 0.003.
Google Search Console: clics orgánicos reduciéndose a la mitad en 12 meses
SISTRIX: comparativa de visibilidad del sector en España — santifer.me invisible frente a competidores
Izquierda: GSC muestra los clics reduciéndose a la mitad (17,3K clics, posición media 23,1). Derecha: comparativa del sector — santifer.me es la línea roja pegada al eje X.

838 H1s duplicados

El template de Squarespace inyectaba un H1 oculto en cada página, duplicando el encabezado principal. Google veía dos títulos compitiendo por relevancia.

1.015 canibalizaciones

Páginas compitiendo entre sí por las mismas keywords. Home, categorías y modelos se pisaban mutuamente en los resultados de búsqueda.

869 errores en datos estructurados

El LocalBusiness schema no seguía las recomendaciones de schema.org. Google no podía interpretar correctamente la información del negocio.

831 páginas no canónicas

Squarespace servía 4 URLs por página sin redirigir a la canónica. GSC las reportaba como duplicadas sin canonical.

33 de 40 aspectos técnicos auditados tenían errores. Solo 7 pasaban. La auditoría no solo diagnosticó los problemas — se convirtió en el roadmap de todo el proyecto.

Screaming Frog: 838 páginas con H1s múltiples, 118 duplicados, 255 sin H2
Screaming Frog: 838 páginas con H1s múltiples
Screaming Frog: 8.000+ imágenes sin atributos de tamaño, 497 demasiado pesadas, 164 sin alt text
Screaming Frog: 8.000+ imágenes sin dimensiones

Los Problemas Técnicos

Sin canonical tags

www vs non-www, con/sin trailing slash, con/sin .html. Misma página, 4 URLs. 831 páginas no canónicas en GSC. Squarespace indicaba canonical pero no redirigía.

Sin redirects custom

Squarespace no permite crear redirecciones 301 personalizadas. 266 URLs históricas dando 404 en GSC. Imposible mapear URLs antiguas a la nueva estructura.

Sin control de slugs de URL

La taxonomía del negocio ya existía, pero Squarespace generaba URLs redundantes como /reparar-iphone/reparar-iphone-x. 15 URLs de más de 115 caracteres, 10 con mayúsculas, keyword repetida 3 veces.

Riesgo de contenido duplicado

1.015 canibalizaciones detectadas. 79 páginas con thin content. Las variantes de URL sin canonical generaban señales confusas para Google, diluyendo la autoridad del dominio.

Página de reparación en Squarespace: iconos genéricos y precios sin estructura
Página de reparación típica en Squarespace. Iconos genéricos, sin fotos reales, sin JSON-LD, sin datos del ERP.
PageSpeed Insights: Lighthouse 21 en móvil, 51 en escritorio. Core Web Vitals: No superada en todas las tipologías
Antes: Squarespace. Lighthouse 21/100 móvil. CWV no superada.
PageSpeed Insights: Lighthouse 97 en móvil, Accesibilidad 100, SEO 100. Core Web Vitals: Superada
Después: Astro + Cloudflare. Lighthouse 97/100 móvil. CWV superada. Compruébalo tú mismo →

La Migración

1

Crawl completo con Screaming Frog

El crawl identificó 838 páginas con H1s múltiples, 266 URLs 404, y 1.015 canibalizaciones. El mapeo resultó en 1.009 reglas de redirección.

2

Nueva estructura de URLs en Astro

De ~80 páginas a una arquitectura de 480+ páginas optimizadas para 156.000 búsquedas mensuales transaccionales. URLs limpias: /reparar-{dispositivo}/, /reparar-{marca}/{modelo}/.

3

301 redirects en vercel.json

Proyecto dedicado (servidor-redirecciones) desplegado en Vercel solo para servir 301s. 190KB de configuración en un solo archivo.

4

Redirects inteligentes por intención

Redirigir páginas nacionales a versiones locales. Ejemplo: /reparar-movil/reparar-samsung → /reparar-movil/samsung/sevilla.

El Servidor de Redirecciones

La triple migración (plataforma, dominio, hosting) requería un plan para no perder la autoridad acumulada en el dominio antiguo. La solución fue un proyecto dedicado en Vercel cuya única función era servir redirecciones 301. Un gotcha del cambio de dominio: Squarespace no permitía redirigir la homepage, lo que bloqueaba el GSC change of address. El doble salto HTTP→308→301 impedía la validación. Se resolvió en una tarde con Vercel Redirect Domain + Cloudflare Redirect Rules para un único 301 directo.

1.009

Reglas de redirección

190 KB

vercel.json

4

Niveles de redirect

46

Commits en 7 meses

Modelo → modelo

/reparar-movil/reparar-samsung/reparar-samsung-galaxy-a12 → /reparar-movil/samsung/galaxy-a12. URL limpia, misma intención.

Marca → marca + ciudad

/reparar-movil/reparar-realme → /reparar-movil/realme/sevilla. La nueva estructura añadía la ciudad como señal local.

Wildcard + catch-all

Cualquier URL no mapeada en los tiers anteriores redirige a la homepage. Zero 404s para el usuario y para Google.

Un proyecto entero de Vercel cuya única función era redirigir. 1.009 reglas mapeadas a mano porque la estructura de URLs de Squarespace no seguía un patrón uniforme.

Implementa las redirecciones antes de solicitar el cambio en Google Search Console. No después. El orden importa.

El Coste de Migrar

Toda migración tiene un coste de transición. 800+ páginas tardaron en reindexarse y keywords clave cayeron temporalmente — "reparar iphone sevilla" pasó del top 2 al puesto 6. Era esperable: Google necesita tiempo para reevaluar un dominio tras un cambio de dirección. La recuperación llegó.

100

Performance

92

Accessibility

96

Best Practices

100

SEO

Comparativa AHREFs del sector: santifer.me con DR 0.1 y 23 backlinks vs competidores con miles
Comparativa de fuerza de dominio (AHREFs). santifer.me: DR 0.1, 23 backlinks. El líder (iriparo.com): DR 44, 21.430 backlinks.

De un Lighthouse de 21 en Squarespace a 100 en Astro. De DA 8 a competir en un mercado donde los líderes tienen 100x más tráfico. La auditoría técnica documentó 33 problemas; la migración los resolvió todos de una vez.

Stack y Herramientas#

El stack se eligió para una necesidad concreta: generar miles de páginas estáticas con datos de un CMS relacional, con el mínimo JavaScript posible en el cliente. Astro era la opción obvia para SSG puro. Airtable funcionaba como CMS porque ya era el Business OS del negocio — no tenía sentido migrar a Supabase para una web estática. DataForSEO se eligió por precio y cobertura de keywords en español.

Astro

SSG, 21 templates, JS mínimo lazy

Airtable

CMS headless, 14 tablas, ~60 campos/tabla

DataForSEO

DataForSEO

Volúmenes de búsqueda, campo "indexable"

ERP propio

867 modelos, precios, stock, fotos, reseñas

Cloudflare

CDN, edge caching, deploy

TypeScript

schema.ts de 1.677 líneas para el mapping

JSON-LD

6 tipos de structured data por página

Lecciones Aprendidas#

1

Google decide la intención del usuario, no tú.

Empecé queriendo posicionar en toda España. Google tenía otros planes: interpretó que las búsquedas de reparación tienen intención local fortísima. Las páginas sin ciudad competían peor que las locales de Sevilla. La lección: construye la infraestructura completa, pero deja que los datos de GSC te digan dónde poner el foco.

2

El motor de decisiones es más importante que el generador.

Generar 10.000 páginas es trivial. Decidir cuáles indexar basándote en datos reales de DataForSEO es lo que marca la diferencia entre pSEO con resultados y una granja de contenido thin. De las miles de combinaciones posibles, solo 4.084 están en el sitemap.

3

El ERP es el diferenciador competitivo, no el template.

Cualquiera puede generar páginas con IA. Nadie puede generar fotos reales de antes/después, reseñas verificadas, precios duales (original y compatible), y tiempos basados en datos históricos sin un ERP integrado. El contenido único no viene del copy, viene de los datos.

4

Airtable escala mejor de lo que esperaba.

14 tablas, ~60 campos por tabla, jerarquía de 6 niveles. Con retry y backoff exponencial en la API, el build es estable. El truco: cachear las reseñas y no hacer llamadas redundantes. Para un equipo de una persona, Airtable como CMS headless funciona.

5

Las URLs de nicho nacional dan el mejor CTR.

El formato /cambiar-bateria-google-pixel-6a tiene un CTR del 5,0% con posición media 7,8. Estas búsquedas son tan específicas que casi no tienen competencia. El volumen individual es bajo, pero multiplicado por cientos de modelos, suma.

6

El contenido generado sin datos de producción es thin content con mejor redacción.

La diferencia entre SEO programático que funciona y una granja de contenido no es el template ni la IA — es que los datos sean reales. Precios del ERP, fotos de reparaciones reales, reseñas verificadas. Este patrón aplica a cualquier empresa con datos operacionales: e-commerce, marketplaces, SaaS con catálogo.

7

La taxonomía del negocio ES la arquitectura de información — no la inventes, mapéala.

No diseñé la estructura de URLs desde cero. Mapée la jerarquía que ya existía en el negocio: tipo → marca → modelo → reparación → ciudad. El Business OS ya tenía esa taxonomía en Airtable. La web programática simplemente la expuso al mundo. Si tu empresa ya tiene una ontología interna, úsala.

Lo Que Esto Demuestra

Diseño de sistemas end-to-end

Desde datos del ERP hasta páginas en producción — CMS relacional, pipeline de build, motor de decisiones, optimización de crawl budget.

Automatización que escala sin intervención

Una persona, 4.730 páginas, 26.000+ imágenes. El sistema sigue funcionando tras la venta del negocio.

Decisiones basadas en datos, no en intuición

DataForSEO como motor de indexación. Google Search Console como feedback loop. Cada decisión respaldada por métricas reales.

Ejecución completa en contexto real

No es un proyecto de portfolio ni un tutorial. Es un sistema de producción que generó tráfico real para un negocio real — y contribuyó a su venta.

Diseño sistemas que convierten datos operacionales en ventajas competitivas.

Este case study demuestra un patrón que he aplicado repetidamente: mapear la ontología del negocio, construir un pipeline data-to-deploy, y medir todo con métricas reales. Actualmente exploro roles de AI Product Manager y Solutions Architect — si tu equipo necesita a alguien que piense en sistemas y ejecute hasta producción, hablemos.

Preguntas Frecuentes#

¿El SEO programático no es spam?

Solo si las páginas no aportan valor. En este caso, cada página tiene datos reales del servicio: precio actual (original y compatible), tiempo estimado basado en históricos, fotos de antes/después de reparaciones reales, y reseñas verificadas de clientes. No es contenido generado por IA ni texto de relleno. Son datos de producción del ERP.

¿Solo funciona en Sevilla?

Las páginas locales se centran en Sevilla porque es donde está la tienda física, y Google prioriza resultados con proximidad geográfica para búsquedas de reparación. Las páginas nacionales (formato /cambiar-{pieza}-{marca}-{modelo}) funcionan sin restricción geográfica y capturan búsquedas de nicho en toda España.

¿Por qué no usaste IA para generar el contenido?

Porque el diferenciador competitivo es que los datos son reales. Los precios salen del ERP, las fotos son de reparaciones reales, las reseñas son de clientes verificados. Una página generada por IA puede sonar bien, pero no tiene datos de producción. El blog sí se apoyó en IA para la redacción, combinado con NotebookLM para el podcast de cada artículo.

¿Airtable escala con 4.700+ páginas?

Sí, con matices. Las 14 tablas y ~60 campos por tabla funcionan bien con un pipeline de build (no consultas en tiempo real). La clave es retry con backoff exponencial en la API y cacheo de datos frecuentes como reseñas. Para consultas en vivo a escala mayor, habría que evaluar alternativas como Supabase.

¿Cómo se mantienen actualizadas las páginas?

Cuando cambia un precio o se añade un modelo en el ERP, el dato se actualiza en Airtable. El siguiente build regenera las páginas afectadas. Las reseñas nuevas se propagan automáticamente por la cascada familia-modelo. No hay intervención manual para el contenido.

¿Por qué Astro y no Next.js?

Para un sitio 100% estático donde el contenido cambia con baja frecuencia, Astro genera HTML puro con mínimo JavaScript — solo componentes interactivos como el buscador y el carrusel, cargados de forma lazy. Las páginas cargan en menos de 1 segundo, los Core Web Vitals son excelentes de forma nativa, y el deploy en Cloudflare CDN es trivial.

¿Qué hace DataForSEO exactamente?

DataForSEO proporciona el volumen de búsqueda real de cada keyword. El resultado se almacena en el campo "indexable" de Airtable. Si una combinación de dispositivo + reparación + ciudad no tiene volumen de búsqueda, la página se genera pero lleva noindex. Es el motor de decisiones que evita diluir la autoridad del dominio con páginas que Google ignoraría.

Recursos#

Santiago Fernández de Valderrama

Santiago Fernández de Valderrama

AI Product Manager · Solutions Architect · AI FDE · Teaching Fellow en AI Product Academy

Construyó y vendió un negocio de 16 años en 2025. Ahora aplica el mismo pensamiento de sistemas a AI enterprise.

© 2026 Santiago Fernández de Valderrama. Todos los derechos reservados.