Auditoría SEO Unificada — fibrolab.cl (v2 — 2026-04-27)

Re-auditoría integral con 8 subagentes especializados. Compara contra seo-audit-2026-04-27.md (v1, mismo día). Verifica fixes del commit 93bccd8 y detecta nuevos hallazgos en Technical, Content, Schema, Sitemap, Performance, GEO y Local SEO.


Puntaje de Salud SEO: 62 / 100

Categoría Peso Puntaje v1 Δ Ponderado
SEO Técnico 22% 68 71 −3 14.96
Contenido / E-E-A-T 23% 54 62 −8* 12.42
SEO On-Page (incl. Local) 20% 65 65 0 13.00
Datos Estructurados (Schema) 10% 68 64 +4 6.80
Rendimiento (CWV) 10% 60 60 0 6.00
Búsqueda con IA (GEO) 10% 67 41 +26 6.70
Imágenes 5% 45 45 0 2.25
Total 62.13

* La caída de Contenido refleja análisis E-E-A-T más profundo (no regresión real). El salto en GEO refleja que /llms.txt y allowlist de bots IA estaban infravalorados.

Tipo de negocio: Negocio local híbrido — fábrica + área de servicio nacional. Vertical: construcción (HomeAndConstructionBusiness + LocalBusiness).


Δ Verificado vs. v1 (commit 93bccd8)

✅ Confirmado resuelto en live

Issue v1 Estado actual
C1: Service schema NO se emite en /bombas-de-calor/ FIXED. Confirmado: la página emite 5 bloques JSON-LD incluyendo Service con @id #service.
C2: Doble <h1> en homepage FIXED. grep -c '<h1' = 1 en home y en las 8 páginas inspeccionadas.
C3: WebP del hero no existía en disco FIXED. otono.png.webp y otonom.png.webp retornan HTTP/2 200.
/gracias-por-cotizar* indexables FIXED. Las 3 variantes envían <meta name="robots" content="nofollow, noindex">.
Cabeceras de seguridad Confirmadas: HSTS preload, X-Frame, X-CTO, Referrer-Policy, Permissions-Policy, CSP enforced (no Report-Only).
CLS por imágenes sin dimensiones Imgs con width/height. CLS estimado ahora dentro de banda.
Single-hop redirects http→https y non-www→www, ambos en 1 salto.
TTFB ~391 ms con x-litespeed-cache: hit. PASS.

🔄 Aún abierto (verificado nuevamente)

Issue Estado Evidencia
/tienda2/ indexable OPEN Aparece en page-sitemap.xml Y como primera entrada de product-sitemap.xml; meta robots index, follow; canonical self.
/spas/ vs /spa-y-jacuzzi/ duplicado OPEN Ambos 200, ambos en sitemap, ambos index, follow con canonical self → señales en competencia.
GBP URL en sameAs OPEN Solo Facebook + Instagram en Organization.sameAs.
Inconsistencia "Fabrica de Piscinas FIBROLAB" vs "Fibrolab" OPEN Title tag de /piscinas-de-fibra/ y <title> del home usan long-form; schema usa "Fibrolab".
Imágenes ChatGPT en /piscinas-de-fibra/ OPEN 9 archivos ChatGPT-Image-Apr-*.png confirmados en /wp-content/uploads/2025/04/.
IndexNow OPEN Ningún key file en raíz (404 en /indexnow.txt y /indexnow).
3 familias Google Fonts OPEN <link rel="stylesheet"> síncrono.
Font Awesome desde cdnjs OPEN Render-blocking externo.
PoolService como @type REVISAR El audit v1 reportaba esto pero las páginas inspeccionadas usan Service con serviceType: "...". Confirmar en Rank Math si algún otro template lo emite.
Logo como string FIXED Ahora es ImageObject con url, width, height, contentUrl, caption.

🔴 CRÍTICO

C1. Render-blocking Swiper.js en <head> (LCP risk)

functions.php:207-210 imprime un <script src> síncrono (sin defer/async) en wp_head priority 5, antes del preload del LCP image. El navegador no puede pintar hasta descargar+parsear Swiper. La preload del hero queda neutralizada.

Cómo:

// functions.php línea 208 — actual:
echo '<script src="' . esc_url( $src ) . '" data-no-optimize="1" data-no-defer="1"></script>';
// Cambiar a:
echo '<script src="' . esc_url( $src ) . '" defer data-no-optimize="1"></script>';

Si Swiper debe estar listo antes de DOMContentLoaded para evitar FOUC del slider, mostrar el primer slide como <picture> estático y diferir Swiper.

C2. /tienda2/ indexable y en dos sitemaps

WooCommerce shop archive duplicado. Title genérico ("Tienda | Fibrolab"), description auto-generada ("Productos Archive | Fibrolab"). Aparece como primera entrada en product-sitemap.xml (no debe — los archivos no van ahí) y también en page-sitemap.xml.

Cómo: En Rank Math → Title & Meta → Pages → /tienda2/: noindex. Excluir del sitemap. Si /tienda2/ debería redirigir a /tienda/ (canónico), añadir 301 vía .htaccess o plugin Redirection.

C3. /spas/ y /spa-y-jacuzzi/ compitiendo

Ambas 200, index, follow, canonical self, ambas en sitemap, ambas con FAQPage propio. Google ve dos páginas para el mismo cluster ("hot tub / spa"). El home (front-page.php:69) enlaza a /spas/; /spa-y-jacuzzi/ es la página más antigua (2024-07-03) y con slug más rico.

Cómo: Decidir canónica única. Recomendado: 301 /spas//spa-y-jacuzzi/. Actualizar enlace del home (front-page.php:69). Sacar /spas/ del sitemap. Consolidar los 4 modelos de hot-tub en una sola página.

C4. Imágenes generadas por ChatGPT en producción

9 archivos ChatGPT-Image-Apr-*.png confirmados en /wp-content/uploads/2025/04/. Si están adjuntas a galerías de productos WooCommerce, son señal E-E-A-T negativa directa — contradicen la propuesta "fábrica real, instalaciones reales". El audit v2 de contenido también detectó pasos de instalación con nombres paso-1-excavacion.png etc. que podrían ser estas mismas imágenes renombradas (verificar).

Cómo: 1. find /root/Proyecto_compartido/fibrolab.cl/wp-content/uploads/ -iname "ChatGPT-Image*" y eliminar. 2. Auditar galerías de productos en wp-admin → reemplazar por fotos reales de instalaciones. 3. Confirmar que los paso-1.png...paso-4.png no son ChatGPT renombradas.

C5. Conflicto factual +500 vs +1.000 instalaciones

page-nosotros.php:47 muestra "+500 Proyectos realizados"; front-page.php:331 afirma "más de 1.000 instalaciones". Es una contradicción factual entre dos páginas del mismo sitio — un quality rater la marcará como falla de Trustworthiness.

Cómo: Decidir el número correcto. Si la diferencia es real (500 piscinas vs. 1.000 trabajos totales incluyendo bordes/revestimientos/cobertores), explicitar la distinción en ambas páginas. Cambiar data-counter en page-nosotros.php:47.


🟠 ALTO

H1. CSS render-blocking externo (Google Fonts + Font Awesome)

Tres familias Google Fonts y font-awesome/6.5.1/all.min.css desde cdnjs (~56 KB) cargan síncronos. Existe <link rel="preload" as="style"> pero el <link rel="stylesheet"> real sigue bloqueando render.

Cómo: Patrón print/onload swap o self-host de FA con subset:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/.../font-awesome.../all.min.css"
      media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="..."></noscript>

O mejor: reemplazar Font Awesome por SVGs inline para los 4-6 íconos efectivamente usados.

H2. H1 enterrado en home

El único H1 ("Fábrica chilena de piscinas de fibra de vidrio desde 2020") está en front-page.php:328, dentro de la sección 8 (después de hero slider, categorías, 4 carouseles de productos, testimonios, garantías). El hero (sección 1) no tiene heading. Para un crawler que lee DOM-order, el primer texto-señal de tema aparece muy abajo.

Cómo: Mover el H1 al hero o convertir el primer H2 del hero ("Fabrica de Piscinas con Instalación incluida") en H1, y degradar fl-intro-title a H2.

H3. /spa-y-jacuzzi/ críticamente delgado

124 palabras visibles. Por debajo del piso de 300 para una página de producto. Sin definición de qué es un jacuzzi, sin proceso de instalación, sin specs de material.

Cómo: Expandir a 800+ palabras con: definición ("Un jacuzzi de fibra de vidrio es..."), comparación spa vs hot tub vs jacuzzi, proceso, hidroterapia y clima chileno, mantenimiento.

H4. /nosotros/ thin (289 palabras), sin fundador, sin RUT visible

Sin nombre del fundador en ningún template del sitio. RUT 77.424.952-4 sólo aparece en front-page.php:331 (un único lugar). Sin anécdota fundacional. Stat counter con error grammatical ("fabrica" sin acento) y duplicado verbatim entre home y /nosotros/.

Cómo: Expandir a 600+ palabras añadiendo fundador, RUT inline, anécdota 2020, foto de equipo. Añadir AboutPage + Organization.founder schema condicional al template.

H5. Falta Service schema en 4 páginas de servicio

Página Service schema
/piscinas-de-fibra/ ✅ presente
/bombas-de-calor/ ✅ presente (FIXED)
/spa-y-jacuzzi/ ✅ presente
/spas/ ❌ ausente
/bordes-de-piscina/ ❌ ausente
/cobertor-de-seguridad/ ❌ ausente
/paneles-solares/ ❌ ausente

Cómo: En fibrolab_schema_service() (functions.php:413+) añadir entradas al array $services para page-bordes-de-piscina, page-cobertor-de-seguridad, page-paneles-solares. Para /spas/ la decisión depende de C3 (si se redirige, irrelevante).

H6. Falta FAQPage en /bordes-de-piscina/

La página tiene 2 bloques FAQ (líneas 226-278 y 288-319 según audit de contenido) pero no emite FAQPage JSON-LD. Pierde elegibilidad para AI Overviews / SGE.

H7. Article schema en páginas comerciales

Rank Math está emitiendo @type: Article en /spas/, /spa-y-jacuzzi/, /bombas-de-calor/, /bordes-de-piscina/. Misrepresenta el propósito (son landing comerciales, no artículos editoriales).

Cómo: En cada página, Rank Math → tab Schema → cambiar a WebPage con ItemList o CollectionPage.

H8. Testimonios reciclados sin fechas ni ciudades

Los 10 testimonios del home y los de /spa-y-jacuzzi/ + /bombas-de-calor/ reciclan los mismos nombres (Ernesto González, Gabriela López, Marco Soto, Felipe Faúndez) entre páginas no relacionadas. Sin fechas, sin comuna, sin link a plataforma externa. Patrón típico de "boilerplate repetitivo" — flag de AI-content / low-quality.

H9. Sistema de captación de reviews de Google ausente

fl-reviews.php envía emails post-compra para reviews WooCommerce on-site (alimentan aggregateRating schema), pero no hay flujo paralelo para reviews de Google Business Profile. La regla 18-day de Sterling Sky implica que >3 semanas sin nueva review de GBP genera caída en local pack. Sin mecanismo proactivo, la velocidad será insuficiente.

Cómo: Tras cierre de instalación (WC order completed + fl-submissions), enviar WhatsApp/email a 7 días con shortlink directo a GBP review form (https://g.page/r/XXXXX/review). Meta: 2+ reviews/mes.

H10. 0 service-area pages publicadas

template-comuna.php existe, está bien construido (FAQ, Service schema, Whatsapp pre-rellenado por ciudad). Cero páginas publicadas con esta plantilla. Es la mayor brecha local — y sin riesgo del quality gate (umbral de WARNING en 30 páginas, no aplica).

Cómo: Lanzar 6-8 páginas iniciales: Maipú, Puente Alto, San Bernardo, La Florida, Las Condes/Ñuñoa, Viña del Mar, Quilpué, Rancagua. Cada una con testimonio real y fl_comuna_distancia_km. NO superar 15 páginas sin instalación local citable por ciudad.


🟡 MEDIO

M1. CSP usa unsafe-inline y unsafe-eval

Necesario por GTM/PixelYourSite/WC inline. No es bloqueante SEO pero degrada señal de seguridad. Tracking para sprint futuro de hardening con nonce-based CSP.

M2. Author enumeration via /?author= 301

robots.txt bloquea crawl pero el 301 sigue revelando username. Añadir a functions.php:

add_action( 'init', function() {
    if ( isset( $_GET['author'] ) ) { wp_safe_redirect( home_url(), 301 ); exit; }
});

M3. IndexNow ausente

Sin key file ni señal Rank Math Pro. Recomendado: instalar Bing URL Submissions Plugin o implementar manual con hook transition_post_status.

M4. LocalBusiness schema incompleto en sameAs

Organization.sameAs solo tiene Facebook + Instagram. Añadir GBP Place URL (https://maps.google.com/?cid=XXXXX), YouTube (alta correlación con citaciones IA, ~0.737), LinkedIn empresa, y eventualmente Wikidata.

M5. /bombas-de-calor/ sin FAQPage schema en su guía editorial

Tiene la mejor sección editorial del sitio (5 Q-A en accordion sobre bombas de calor) pero solo emite el FAQPage del bloque más corto. Las 5 preguntas más profundas no son machine-readable. Ver Priority 2 del informe GEO con el JSON-LD listo para pegar.

M6. llms.txt con URLs inválidas y datos desactualizados

Cómo: Reemplazar la sección "Key URLs" con el bloque corregido del informe GEO.

M7. Falta FAQPage en /bordes-de-piscina/, falta AboutPage en /nosotros/

Ver H6 + ampliación: /nosotros/ no emite AboutPage ni Organization.founder/taxID (RUT). Añadir condicional en fibrolab_schema_local_business() cuando is_page('nosotros').

M8. /paneles-solares/ jerarquía de headings incorrecta

Después del H1 "Paneles Solares" (línea 27), la plantilla emite 4 <h2> separados como labels visuales de feature ("Tecnología On Grid / Off Grid", etc.). Deben ser <h3> o spans. El crawler no distingue H2s estructurales de decorativos.

M9. Sin "última actualización" / dateModified

Ningún template muestra fecha de actualización visible ni dateModified en schema. Bajo expectativas de freshness Dec 2025, las páginas con precios (bombas, paneles) lucen estáticas.

M10. Tono coloquial en FAQ de /piscinas-de-fibra/

"es pan comido", "Fibrolab tiene una gran trayectoria... De esta forma surge Fibrolab... De manera que..." — patrón circular tipo IA en page-piscinas-de-fibra.php:761-786. La palabra "manera/forma" aparece 7 veces en 150 palabras. Reescribir con métricas verificables (años, instalaciones por modelo, casos por comuna).

M11. Boilerplate duplicado entre home y /nosotros/

Las 3 cards de garantía (Garantía 5 años, Fabricación Propia, Precio Conveniente) son idénticas verbatim entre front-page.php:302-318 y page-nosotros.php:167-191. Reduce distintividad de /nosotros/ y dispara flag de AI-content.

M12. Cero cross-linking entre páginas de servicio

Estructura hub-and-spoke pura. /piscinas-de-fibra/ no enlaza a /bombas-de-calor/ (upsell natural). /bombas-de-calor/ no enlaza a /paneles-solares/. /spa-y-jacuzzi/ no enlaza a /bordes-de-piscina/. Añadir enlaces contextuales en cuerpo (no sólo nav).

M13. Sin embed de Google Maps

grep confirma cero iframes de maps en plantillas PHP. CSP frame-src ya permite google.com, no hay bloqueador técnico. Añadir embed en footer//contacto/ para señal directa GBP↔web.

M14. Geo-coordinates con 5 decimales (~1m precisión)

Schema usa -33.58301 / -70.63280 — al borde mínimo. Verificar que el pin esté sobre la entrada real de la fábrica.

M15. priceRange "$$" poco informativo

"$$" no aporta información útil. Considerar rango específico ("Desde CLP 1.500.000 hasta CLP 8.000.000" o similar) o eliminar.


🟢 BAJO

L1. <noscript> opacity hack de WooCommerce — comportamiento default, no SEO issue.

L2. X-XSS-Protection: 1; mode=block — header obsoleto pero inofensivo. Eliminar opcional.

L3. RSS feed en <head> con post-sitemap lastmod 2024-11-17 (stale). 6 posts en sitemap. Decidir si seguir publicando blog o bajar señal feed_links con remove_action('wp_head', 'feed_links', 2).

L5. Inconsistencia formato teléfono: +56 9 8225 6792 (texto), +56982256792 (schema, tel:). Estandarizar.

L6. data-counter="6" (años de experiencia) en page-nosotros.php:63 está hardcoded. En 2027 estará desactualizado. Reemplazar por <?php echo date('Y') - 2020; ?>.

L7. paneles-solares-familia-1024x683.png con apariencia stock-photo. Confirmar si es real o reemplazar por instalación verificada.

L8. local-sitemap.xml apunta a locations.kml — verificar que el KML se mantenga al día (Rank Math Local).

L9. Solo 1 entrada en product_cat-sitemap.xml (/producto/minipiscina/). Inusual — verificar configuración de Rank Math (probablemente la ruta es categoría de producto pero solo hay un cat indexable).


Inventario de Schema (pages auditadas en live)

Página JSON-LD blocks Tipos detectados
/ (home) 2 @graph(Organization,WebSite,WebPage,...) + LocalBusiness+HomeAndConstructionBusiness
/bombas-de-calor/ 5 + Service ✅ + BreadcrumbList + FAQPage
/piscinas-de-fibra/ 5 + Service + BreadcrumbList + FAQPage
/spa-y-jacuzzi/ 5 + Service + BreadcrumbList + FAQPage
/spas/ 4 + BreadcrumbList + FAQPage (sin Service ❌)
/paneles-solares/ 4 + BreadcrumbList + FAQPage (sin Service ❌)
/bordes-de-piscina/ 3 + BreadcrumbList (sin Service ❌, sin FAQPage ❌)
/nosotros/ 3 + BreadcrumbList (sin AboutPage)
/tienda2/ 3 + BreadcrumbList (no debería ser indexable)

Inventario de Sitemap

Sub-sitemap URLs Notas
page-sitemap.xml 13 Incluye /tienda2/ ❌ y /spas/ + /spa-y-jacuzzi/ (duplicado).
product-sitemap.xml 30 Primera entrada es /tienda2/ ❌ (un archive en sitemap de productos).
product_cat-sitemap.xml 1 Solo /producto/minipiscina/. Inusual. Verificar config.
post-sitemap.xml 6 Lastmod 2024-11-17 — blog estancado.
local-sitemap.xml 1 Apunta a locations.kml.

Hallazgos GEO (resumen ejecutivo)


Hallazgos Local SEO (resumen ejecutivo)


Quick-Win Action List (orden de impacto)

# Acción Archivo / lugar Tiempo Impacto
1 defer en Swiper script functions.php:208 5 min CRÍT (LCP)
2 301 /spas//spa-y-jacuzzi/ + sacar de sitemap + actualizar front-page.php:69 Multiple 30 min CRÍT (consolidación)
3 Noindex /tienda2/ + sacar de ambos sitemaps Rank Math 10 min CRÍT
4 Eliminar/renombrar archivos ChatGPT-Image-*.png wp-uploads + galerías productos 1 h CRÍT (E-E-A-T)
5 Resolver +500 vs +1.000 page-nosotros.php:47 o front-page.php:331 5 min CRÍT (Trust)
6 Mover H1 al hero del home front-page.php 10 min ALTO
7 Añadir Service schema a /bordes/, /cobertor/, /paneles-solares/, /spas/ (si no se redirige) functions.php:413 array $services 30 min ALTO
8 Añadir FAQPage JSON-LD a /bombas-de-calor/ (guía editorial) y /bordes/ page-bombas-de-calor.php, page-bordes-de-piscina.php 1 h ALTO (GEO)
9 Font Awesome async (print/onload swap) o swap a SVG header.php o functions.php enqueue 30 min ALTO (CWV)
10 Cambiar ArticleWebPage/CollectionPage en landings comerciales Rank Math per-page 30 min ALTO
11 Verificar GBP, añadir Place URL a sameAs + hasMap + alternateName functions.php:333 30 min + verif manual ALTO
12 Embed Google Maps en footer footer.php 15 min ALTO
13 Lanzar 4 service-area pages (Maipú, Puente Alto, Viña, Rancagua) WP admin con template-comuna.php 4 h ALTO
14 Pasaje definicional "¿Qué es una piscina de fibra?" en /piscinas-de-fibra/ page-piscinas-de-fibra.php 30 min ALTO (GEO)
15 Reescribir /nosotros/ con "Fibrolab" como sujeto + fundador + RUT inline page-nosotros.php 1.5 h ALTO (E-E-A-T + GEO)
16 Corregir llms.txt (URLs rotas, rango productos, blog) /llms.txt 30 min MEDIO (GEO)
17 Sistema reviews GBP post-instalación (WhatsApp 7 días) Workflow externo 2 h MEDIO (Local)
18 IndexNow (Rank Math Pro o plugin Bing) Plugin 30 min MEDIO
19 Cross-linking contextual entre service pages Multiple 1 h MEDIO
20 dateModified schema + "última actualización" visible Templates 1 h MEDIO

Roadmap 30/60/90 días

Días 1-7 (sprint crítico): items 1-5 del Quick-Win → puntaje técnico +6, contenido +4.

Días 8-30: items 6-15 → cierre de gaps schema/CWV/GEO/Local on-page.

Días 31-60: lanzar service-area pages (#13), sistema reviews GBP (#17), refactor /spa-y-jacuzzi/ con contenido editorial (H3), corregir conflicto coloquial en FAQs (M10).

Días 61-90: crear /galeria/ con 20+ instalaciones tagged por comuna, embedding YouTube videos (cuando exista canal), 4 nuevas city pages, primer ciclo de auditoría de citations T1 chilenas (Páginas Amarillas, Hoy.cl, Cybo, Empresite, Kompass).


Limitaciones de la auditoría

Para cubrir las brechas: instalar extensión DataForSEO MCP y correr /seo dataforseo, /seo backlinks, /seo maps. Con credenciales Google API: /seo google.