# Auditoría SEO — fibrolab.cl (re-audit v3) **Fecha:** 2026-04-29 (tercera corrida del día) **URL:** https://www.fibrolab.cl/ **Tipo de negocio:** Hybrid — Manufacturer + LocalBusiness + HomeAndConstructionBusiness + SAB nacional. Fábrica en La Pintana, instalación en todo Chile. **Stack:** WordPress + WooCommerce + Rank Math + LiteSpeed Cache + GTM-W6DGGKK + PixelYourSite Free 11.2.0.4 **Idioma:** es-CL (hreflang `es-CL` + `x-default` autorreferenciados) **NAP:** Fibrolab · Los Álamos 2538, La Pintana, Región Metropolitana · +56 9 8225 6792 · contacto@fibrolab.cl · RUT 77.424.952-4 **Metodología:** auditoría fresca independiente con 8 subagentes en paralelo (technical, content, schema, sitemap, performance, visual, geo, local) + verificación manual cruzada con curl/Python contra el HTML live. Algunos subagentes (performance, geo, local) no completaron entrega: sus áreas se cubrieron con verificación manual y consolidación con findings de v2. --- ## SEO Health Score — 64 / 100 *(↑ 1 vs v2 = 63)* | Categoría | Peso | Score | Ponderado | |---|---:|---:|---:| | Technical SEO | 22% | 74 | 16.28 | | Content Quality / E-E-A-T | 23% | 59 | 13.57 | | On-Page SEO | 20% | 62 | 12.40 | | Schema / Datos estructurados | 10% | 61 | 6.10 | | Performance (CWV proxy) | 10% | 70 | 7.00 | | AI Search Readiness (GEO) | 10% | 50 | 5.00 | | Imágenes | 5% | 75 | 3.75 | | **Total** | | | **~64** | **Local SEO (informativo, fuera de fórmula):** 49/100 (↓ 9 vs v2 informativo de 58) — el agente local detectó que `template-comuna.php` ya está construido completo (con `h1` dinámico, FAQ localizado, schema Service + FAQPage con `AdministrativeArea`, WhatsApp pre-filled, distancia desde fábrica) pero **0 páginas comunales publicadas** — el factor #1 de ranking en local pack según Whitespark 2026. Además: testimonios hardcoded sin importar como WC reviews (AggregateRating omitido), `hasMap` ausente en schema, sin SEC license number. > **Lectura:** el sitio mejoró marginalmente. Varios fixes de la v2 sí aterrizaron en código, pero los **9 issues críticos clave** que bloquean rich results y compliance regulatorio chileno **siguen abiertos**. Score plano refleja un avance en backend/seguridad sin progreso en compliance/Merchant Center/AI citation. --- ## Estado de fixes pendientes desde v2 (verificación live HTML) ### ❌ NO FIXEADOS (siguen igual que v2) 1. **Title sin tilde** — `Fabrica de Piscinas FIBROLAB...` aún sin "Fábrica". OG arrastra el error. 2. **Meta description "más de 6 años"** vs OG description "6 años" coherente entre sí pero contradice `foundingDate: 2020` (~6 años). Aceptable; pero si la lectura es "experiencia previa del equipo" hay que decirlo. 3. **`hasMerchantReturnPolicy` + `shippingDetails` ausentes en Product Offer** — confirmado en `/modelo/piscina-4-8-metros/`. Bloquea Google Merchant Center. 4. **`@type` LocalBusiness sin `Manufacturer`** — `functions.php:300` sigue `['HomeAndConstructionBusiness', 'LocalBusiness']`. 5. **`postalCode 8830000`** no verificado contra Correos de Chile. 6. **`sameAs` sin URL del Google Business Profile** — solo Facebook + Instagram. 7. **Embed Google Maps ausente** en todos los templates. 8. **`/contacto/` 301→home** — la página de contacto sigue sin existir. 9. **Páginas legales 404** — `/politica-de-privacidad/`, `/terminos-y-condiciones/`, `/privacidad/` siguen devolviendo 404. 10. **Sin mención Sernac / Ley 19.496 / CAE** en home, /financiamiento-salvum/ ni /nosotros/. Riesgo activo con Sernac. 11. **BreadcrumbList de producto incompleto** — `/modelo/piscina-4-8-metros/` aún emite solo "Inicio → Piscina 4.8 Metros". 12. **og:type "article" en /spas/, /jacuzzi/, /piscinas-de-fibra/** — debería ser "website" o "product". 13. **URL incorrecta en llms.txt** — sigue listando `/spa-y-jacuzzi/` en lugar de `/jacuzzi/`. La URL ahora hace 301 (mejora vs v2 que decía que estaba rota), pero llms.txt debe apuntar a la canónica. 14. **Speakable schema ausente en todas las páginas** — 0 ocurrencias en HTML live. 15. **Pasajes "first-40-words" definitorios faltan** en /piscinas-de-fibra/, /spas/, /jacuzzi/, /reparacion/. ### ✅ NUEVOS HALLAZGOS NO DETECTADOS EN V2 16. **Type-collision en JSON-LD del home (NEW)** — Block 1 (Rank Math) emite `"@type": "Organization"` con `"@id": "https://www.fibrolab.cl/#localbusiness"`. Block 2 (custom theme) emite `"@type": ["HomeAndConstructionBusiness", "LocalBusiness"]` con el mismo `@id`. El alias `@id` es intencional (v2 lo cita como fix correcto), pero los dos nodos publicados con el mismo `@id` deberían tener tipos compatibles. Solución: agregar `"Organization"` al array de tipos del block 2 → `["Organization", "Manufacturer", "HomeAndConstructionBusiness", "LocalBusiness"]`. Esto unifica la entidad, agrega `Manufacturer` y elimina la colisión. *(Severidad: HIGH)* 17. **`/paneles-solares/` devuelve 404 (NEW)** — la URL retorna 404 con `Página no encontrada | Fibrolab` y `meta robots="follow, noindex"`. El template `page-paneles-solares.php` aún existe en el tema (visible en git status), pero la página WP fue eliminada. El footer en v2 ya tenía el enlace comentado. Si el servicio sigue activo, recrear la página; si fue descontinuado, remover el archivo PHP. *(Severidad: HIGH — pérdida de tráfico orgánico potencial)* 18. **Font Awesome cargado externo desde cdnjs.cloudflare.com (NEW)** — verificado en HTML live: ``. Render-blocking + RTT DNS+TLS al critical path, pese a tener `preconnect`. Self-hostal junto a Swiper para que LiteSpeed lo combine. *(Severidad: HIGH — LCP -200/-300ms en mobile 3G/4G)* 19. **CSS principal 271KB sin defer aplicado en código (NEW)** — el comentario en `functions.php:142-150` describe la estrategia `media='print' onload`, pero el filtro `style_loader_tag` que la aplica no está implementado en el código actual. LiteSpeed Cache combina el CSS en un único archivo hasheado (`/wp-content/litespeed/css/8ba678a6be1fe2d796dc0afd41af5f98.css`), pero el atributo `media="print"` no aparece en el HTML live. Resultado: render-blocking efectivo. *(Severidad: HIGH — verificar y aplicar filtro)* 20. **OpenReplay tracker en `wp_head` priority 1 (NEW)** — `functions.php:1461`. El bootstrap inline ocupa el slot más alto del head, antes de los preloads del LCP hero. Mover a footer priority 20. *(Severidad: HIGH)* 21. **Hero de páginas de servicio como `background-image` CSS (NEW)** — `page-piscinas-de-fibra.php:28`, `page-nosotros.php:20`, `page-jacuzzi.php`. El preload scanner del navegador no detecta imágenes en `background-image`, retrasando LCP 400-800ms. La home sí usa ``. *(Severidad: HIGH)* 22. **Hero del home en mobile sin texto ni CTA (NEW)** — `` puro con `aspect-ratio: 768/900` (~117vw) y H1 en última sección. El usuario móvil ve solo una foto sin value prop ni CTA above-the-fold. *(Severidad: CRITICAL UX — bloquea conversión móvil directa)* 23. **`.fibrolab-product-card__title { font-size: 9px }` en mobile (NEW)** — viola mínimo de legibilidad Google (12px) y estándar UX (14-16px). Aplica a home, /piscinas-de-fibra/, /spas/. Una línea de CSS arregla. *(Severidad: CRITICAL)* 24. **30 imágenes con `loading="eager"` + `data-no-lazy="1"` en `#fl-cat-gallery` (NEW)** — `/piscinas-de-fibra/` carga 30 imágenes en paralelo al LCP, saturando bandwidth. Cambiar a `loading="lazy"`. *(Severidad: HIGH)* 25. **post-sitemap.xml con `lastmod 2024-11-17` (NEW)** — el sub-sitemap de blog está congelado hace 17 meses, sugiere que el blog no se actualiza. Crawl budget desperdiciado. *(Severidad: MEDIUM — más de UX/contenido que técnico)* 26. **Logs accesibles en uploads (NEW)** — `csp-violations.log` e `indexnow.log` en `/wp-content/uploads/` no bloqueados en robots.txt y potencialmente indexables. Fuente: agente technical. *(Severidad: MEDIUM)* 27. **Bots IA importantes faltantes en robots.txt (NEW)** — robots.txt declara reglas para GPTBot/OAI-SearchBot/ClaudeBot/PerplexityBot/Google-Extended/CCBot, pero falta `Google-CloudVertexBot` (Gemini), `anthropic-ai`, `Bytespider`. *(Severidad: LOW)* 28. **`template-comuna.php` completamente construido, 0 páginas comunales publicadas (NEW)** — el template tiene `h1` dinámico, FAQ localizado por comuna, schema Service + FAQPage con `AdministrativeArea`, WhatsApp pre-filled CTA, campo distancia desde fábrica. Listo para publicar. Cero usos en producción (verificado en `page-sitemap.xml` con 11 URLs, ninguna `/piscinas-en-*/`). El factor #1 de ranking en local pack es páginas dedicadas por área de servicio (Whitespark 2026). Comunas prioritarias por volumen de búsqueda: Maipú, Puente Alto, San Bernardo, Las Condes, Providencia, Ñuñoa, Peñalolén, Vitacura. *(Severidad: HIGH — máximo ROI local)* 29. **10 testimonios hardcoded en `front-page.php:208-268` no importados como WC reviews (NEW)** — la lógica `fibrolab_get_aggregate_rating()` (`functions.php:388-416`) emite `aggregateRating` solo si hay reviews aprobadas en WooCommerce. Los 10 clientes reales (Felipe Faundez, Katherine Meller, etc.) aparecen visualmente pero no en schema. Sin estrellas en SERP. Importarlos vía admin (`inc/fl-reviews.php`) los expone al schema sin escribir contenido nuevo. *(Severidad: HIGH)* 30. **`hasMap` ausente en LocalBusiness schema (NEW)** — agregar `'hasMap' => 'https://maps.app.goo.gl/[PLACE_ID]'` al schema. Combinado con A2 (sameAs GBP), refuerza la disambiguación de la entidad local. *(Severidad: HIGH)* 31. **SEC license number ausente / sin `hasCredential` (NEW)** — `/nosotros/` no muestra el N° SEC y el schema LocalBusiness no incluye `hasCredential`. Para una empresa que instala piscinas de fibra (sistema eléctrico de la bomba + iluminación), la inscripción SEC es regulatoria. *(Severidad: MEDIUM)* ### ✅ FIXES CONFIRMADOS DESDE V2 (siguen estables) - Critical CSS inline + main CSS combinado por LiteSpeed (`functions.php:154-163`). - Google Fonts self-hosted (Montserrat + Nunito WOFF2 variables, `:128-139`). - Rank Math `@id` alias a `#localbusiness` (`:842-854`) — efectivo, sin Organization huérfanos. - Schema dedup: WooCommerce `woocommerce_structured_data_product` + Rank Math Product/Article/BreadcrumbList suprimidos. - Headers de seguridad completos: HSTS preload, CSP enforced con report-uri, X-Frame-Options, etc. - Service schema completo en 5 páginas: `image`, `areaServed`, `provider @id`, `offers.priceCurrency: CLP`. - IndexNow: lógica correcta, key file servido vía PHP. - `/spa-y-jacuzzi/` ahora hace 301→`/jacuzzi/` (✓ corregido vs v2). - `/producto-categoria/spas/` y `/producto-categoria/piscinas-de-fibra/` hacen 301 limpio a páginas hub (✓). - `/cobertor-de-seguridad/` hace 301 a `/modelo/cobertor-de-seguridad-para-piscinas/` (decisión OK; pero pierde candidato para hub propio). - `/bordes/` ya devuelve 200 (vs v2 noindex). --- ## Plan de acción priorizado ### CRÍTICO (esta semana — bloqueadores de revenue / compliance) | # | Acción | Archivo:Línea | Esfuerzo | |---|---|---|---| | C1 | Agregar `hasMerchantReturnPolicy` + `shippingDetails` al `$offer` array en `fibrolab_schema_product()` | `functions.php:595-608` | 30 min — bloquea Google Shopping | | C2 | Crear `/contacto/` (eliminar el 301 a home) con NAP completo + iframe Maps + formulario + schema `ContactPage` + `Organization.contactPoint` | nueva página | 2-3h | | C3 | Crear `/politica-de-privacidad/` (Ley 19.628) y `/terminos-y-condiciones/` (Ley 19.496); enlazar en footer | nuevas páginas + `footer.php:73-88` | 3h (texto plantilla + revisión) | | C4 | Agregar CAE + ejemplo representativo + RUT/CMF de Forum Servicios Financieros en `/financiamiento-salvum/` (Art. 37 Ley 19.496) | `page-financiamiento-salvum.php` | 1h | | C5 | Hero del home mobile: añadir capa absoluta con H1 + value prop + botón "Cotizar" sobre `.fibrolab-hero__slide.is-active` | `front-page.php` + CSS | 1h | | C6 | Subir `font-size` de `.fibrolab-product-card__title` de 9px a 13px en mobile | `assets/css/fibrolab.css` (regla `@media (max-width: 768px)`) | 5 min | | C7 | Corregir title sin tilde + unificar copy "fundada 2020" / "experiencia 6 años": en Rank Math → Inicio → Título SEO + Descripción + Social | Rank Math admin | 15 min | | C8 | Corregir URL `/spa-y-jacuzzi/` → `/jacuzzi/` en `/llms.txt` | archivo en raíz | 2 min | | C9 | Resolver `/paneles-solares/` 404: recrear página WP o eliminar `page-paneles-solares.php` y `templates/sections/financiamiento-salvum.php` (?) | decisión de producto | 30 min-2h | | C10 | **Publicar 8 páginas comunales** usando `template-comuna.php` (Maipú, Puente Alto, San Bernardo, Las Condes, Providencia, Ñuñoa, Peñalolén, Vitacura). Llenar campos ACF: `fl_comuna_nombre`, `fl_comuna_region`, `fl_comuna_lat`, `fl_comuna_lng`, `fl_comuna_testimonio`, `fl_comuna_distancia_km` | template ya existe | 1-2 días — máximo ROI local pack | | C11 | **Importar los 10 testimonios** del home como reviews WooCommerce vía admin (`inc/fl-reviews.php` → "Importar reseñas"). Activa `aggregateRating` y estrellas en SERP sin escribir contenido nuevo | WP Admin | 1h | ### ALTO (próximas 2 semanas) | # | Acción | Archivo:Línea | Esfuerzo | |---|---|---|---| | A1 | `@type` LocalBusiness: agregar `Organization` + `Manufacturer` → `['Organization', 'Manufacturer', 'HomeAndConstructionBusiness', 'LocalBusiness']` (resuelve type-collision con Rank Math) | `functions.php:300` | 5 min | | A2 | `sameAs` agregar URL pública del Google Business Profile (formato `https://maps.app.goo.gl/...`). **Prerequisito:** reclamar/verificar GBP | `functions.php:348-351` | 30 min admin + 5 min código | | A3 | Verificar `postalCode` La Pintana en Correos de Chile y reemplazar `8830000` si es incorrecto | `functions.php:326` | 10 min | | A4 | BreadcrumbList producto: agregar nivel intermedio `Piscinas de Fibra → /piscinas-de-fibra/` (lógica de mapeo `product_cat` → página hub) | `functions.php:680-686` (snippet en sección "Schema fixes" abajo) | 1h | | A5 | Self-host Font Awesome 6.5.1 en `/assets/vendor/fontawesome/` (eliminar dependencia cdnjs) | `functions.php:182-188` | 30 min | | A6 | Implementar filtro `style_loader_tag` para defer real de `fibrolab.css` (`media='print' onload`) | `functions.php` (snippet abajo) | 15 min | | A7 | Mover OpenReplay tracker de `wp_head` priority 1 → `wp_footer` priority 20 | `functions.php:1461` | 5 min | | A8 | Convertir hero `background-image` en /piscinas-de-fibra/ y /nosotros/ a `` con preload | `page-piscinas-de-fibra.php:28`, `page-nosotros.php:20` | 2h | | A9 | `loading="lazy"` en las 30 imágenes de `#fl-cat-gallery` (eliminar `data-no-lazy="1"`) | `page-piscinas-de-fibra.php` (galería) | 15 min | | A10 | og:type "article" → "website" en /spas/, /jacuzzi/, /piscinas-de-fibra/ | Rank Math por página → Social → OG Type | 10 min | | A11 | Agregar `Speakable` schema en home (cssSelector apuntando a H1 + hero subtitle) | `functions.php` (snippet abajo) | 20 min | | A12 | Agregar `WebSite` + `SearchAction` para Sitelinks Searchbox (verificar si Rank Math ya lo emite) | Rank Math o `functions.php` | 30 min | | A13 | Agregar `AboutPage` schema en `/nosotros/` | `functions.php` (snippet abajo) | 15 min | | A14 | Agregar `CollectionPage` schema en archives `/producto-categoria/*/` | `functions.php` (snippet abajo) | 30 min | | A15 | Pasajes "first-40-words" definitorios en /piscinas-de-fibra/, /spas/, /jacuzzi/, /reparacion/ — abrir cada página con definición técnica citable, no banner promocional | templates page-*.php | 3-4h (4 páginas × 45 min) | | A16 | Tabla comparativa fibra vs hormigón vs proyectado en `/piscinas-de-fibra/` + replicar en llms.txt | `page-piscinas-de-fibra.php` + llms.txt | 2h | | A17 | Definición spa vs jacuzzi + tabla diferencial en `/spas/` o `/jacuzzi/` | template | 1.5h | | A18 | Specs técnicas (jets, capacidad, kW, voltaje, dimensiones) en `/spas/` y `/jacuzzi/`; mover modal JS de equipamiento `/piscinas-de-fibra/` a tabla HTML estática | templates | 3h | | A19 | Equipo nombrado + bio fundador + foto + certificaciones en `/nosotros/` (target 600 palabras vs 310 actuales) | `page-nosotros.php` | 4h (texto + foto) | | A20 | Reescribir FAQs `/piscinas-de-fibra/` (eliminar "muchos años en el mercado", reescribir con datos: 1.000+ instalaciones, ISO-NPG, etc.) | `page-piscinas-de-fibra.php:765-790` | 2h | | A21 | Testimonios: agregar campo `location` (comuna) al array de `front-page.php:208-268` | `front-page.php` | 30 min | | A22 | IndexNow: agregar hook `woocommerce_update_product` para cubrir cambios de precio sin transición de status | `functions.php:1583` | 15 min | | A23 | Agregar `hasMap` a LocalBusiness: `'hasMap' => 'https://maps.app.goo.gl/[PLACE_ID]'` | `functions.php:297` | 5 min | | A24 | Embed Google Maps en `footer.php` (CSP ya tiene `frame-src https://www.google.com`) + link "Cómo llegar" | `footer.php` | 30 min | | A25 | Agregar `hasCredential` con N° SEC a LocalBusiness schema | `functions.php:297` | 30 min | | A26 | FAQPage schema en `page-piscinas-de-fibra.php`, `page-bombas-de-calor.php`, `page-jacuzzi.php` (ya está en `/reparacion/` y `/financiamiento-salvum/`) — beneficio GEO/AI, no rich result Google | templates | 2h | ### MEDIO (siguiente mes) | # | Acción | Detalle | |---|---|---| | M1 | Bloquear `csp-violations.log` e `indexnow.log` en robots.txt o moverlos a `wp-content/logs/` con `.htaccess Deny from all` | 15 min | | M2 | Agregar `Google-CloudVertexBot`, `anthropic-ai` (Allow), `Bytespider` (Disallow) a robots.txt | 5 min | | M3 | Refrescar blog (post-sitemap.xml lastmod 2024-11-17 — 17 meses sin update). Mínimo: 1 post mensual con datos técnicos chilenos | continuo | | M4 | `priceValidUntil` con timezone explícita: cambiar `date('Y-12-31')` por `date('Y-12-31\TH:i:sP')` ISO 8601 con offset | `functions.php:602` | | M5 | `Product` agregar `manufacturer` apuntando a `#localbusiness` | `functions.php:572` | | M6 | Agregar `LoanOrCredit` schema en `/financiamiento-salvum/` (beneficio GEO, no rich result Google) | `page-financiamiento-salvum.php` | | M7 | Mejorar tap targets a 48px+ (`.fl-mobile-cta__btn`, `.fibrolab-menu-toggle`) | CSS | | M8 | `min-height` en `.fl-cat-hero--visual` para prevenir CLS si imagen tarda | CSS | | M9 | Single product mobile: `order: 1` en `.fl-single__summary` para que H1+precio+CTA aparezcan antes que galería | CSS | | M10 | Fallback CSS para elementos `[data-animate]`: `html:not(.js-animate-ready) [data-animate] { opacity: 1 !important; }` | CSS | | M11 | Body `padding-bottom: 56px` incondicional en mobile (eliminar dependencia de JS para sticky CTA, evita CLS) | CSS | | M12 | URL en shortcode `[cotizar]` con `rawurlencode()` | `functions.php:1146` | ### BAJO (backlog) | # | Acción | |---|---| | L1 | Header `X-XSS-Protection` deprecado — remover (LiteSpeed config) | | L2 | Directivas residuales `fonts.googleapis.com` en CSP — remover (`functions.php:1031`) | | L3 | `og:locale` `es_CL` no en lista oficial Facebook — usar `es_LA` o sin locale | | L4 | Anuncios bar `font-size:11px` mobile → 12px | | L5 | `/tienda2/` configurar redirect 301 explícito o noindex | --- ## Snippets de fix listos para copy-paste ### A1 — `@type` LocalBusiness con Organization + Manufacturer ```php // functions.php:300 — cambiar de: '@type' => array( 'HomeAndConstructionBusiness', 'LocalBusiness' ), // a: '@type' => array( 'Organization', 'Manufacturer', 'HomeAndConstructionBusiness', 'LocalBusiness' ), ``` ### C1 — `hasMerchantReturnPolicy` + `shippingDetails` en Product Offer ```php // functions.php — dentro del array $offer en fibrolab_schema_product(), después de 'seller': 'hasMerchantReturnPolicy' => array( '@type' => 'MerchantReturnPolicy', '@id' => 'https://www.fibrolab.cl/#return-policy', 'applicableCountry' => 'CL', 'returnPolicyCategory' => 'https://schema.org/MerchantReturnNotPermitted', 'merchantReturnDays' => 0, ), 'shippingDetails' => array( '@type' => 'OfferShippingDetails', 'shippingRate' => array( '@type' => 'MonetaryAmount', 'value' => '0', 'currency' => 'CLP', ), 'shippingDestination' => array( '@type' => 'DefinedRegion', 'addressCountry' => 'CL', ), 'deliveryTime' => array( '@type' => 'ShippingDeliveryTime', 'handlingTime' => array( '@type' => 'QuantitativeValue', 'minValue' => 1, 'maxValue' => 3, 'unitCode' => 'DAY', ), 'transitTime' => array( '@type' => 'QuantitativeValue', 'minValue' => 1, 'maxValue' => 2, 'unitCode' => 'DAY', ), ), ), ``` > **Nota legal:** Ley 19.496 (Chile) Art. 3 lit. e) garantiza derecho de retracto en compras online por 10 días. Para piscinas instaladas (servicio prestado y bienes personalizados Art. 3 ter), la categoría correcta puede ser `MerchantReturnFiniteReturnWindow` con `merchantReturnDays: 10` y aclaración. Confirmar con asesor legal antes de subir. ### A6 — Defer real de fibrolab.css ```php // functions.php — agregar después del enqueue de fibrolab-style: add_filter( 'style_loader_tag', function ( $tag, $handle ) { if ( in_array( $handle, array( 'fibrolab-style', 'swiper' ), true ) ) { $tag = str_replace( "media='all'", "media='print' onload=\"this.media='all'\"", $tag ); $tag .= ''; } return $tag; }, 10, 2 ); ``` ### A11 — Speakable schema en home ```php // functions.php — nuevo hook (o dentro de fibrolab_schema_local_business cuando is_front_page()): add_action( 'wp_head', function () { if ( ! is_front_page() ) return; $speakable = array( '@context' => 'https://schema.org', '@type' => 'WebPage', '@id' => 'https://www.fibrolab.cl/#webpage', 'speakable' => array( '@type' => 'SpeakableSpecification', 'cssSelector' => array( 'h1', '.fl-ns-hero__subtitle', '.fibrolab-intro p:first-of-type' ), ), ); echo '' . "\n"; }, 25 ); ``` ### A4 — BreadcrumbList con categoría intermedia ```php // functions.php — reemplazar el bloque is_singular('product') en fibrolab_schema_breadcrumbs() (~L680): if ( is_singular( 'product' ) ) { global $product; if ( ! $product ) $product = wc_get_product( get_the_ID() ); $cat_map = array( 'piscinas-de-fibra' => array( 'name' => 'Piscinas de Fibra', 'url' => '/piscinas-de-fibra/' ), 'jacuzzi' => array( 'name' => 'Jacuzzis', 'url' => '/jacuzzi/' ), 'spa' => array( 'name' => 'Spas', 'url' => '/spas/' ), 'bombas-de-calor' => array( 'name' => 'Bombas de Calor', 'url' => '/bombas-de-calor/' ), ); $terms = get_the_terms( get_the_ID(), 'product_cat' ); if ( $terms && ! is_wp_error( $terms ) ) { $primary = $terms[0]; if ( isset( $cat_map[ $primary->slug ] ) ) { $items[] = array( '@type' => 'ListItem', 'position' => $pos++, 'name' => $cat_map[ $primary->slug ]['name'], 'item' => 'https://www.fibrolab.cl' . $cat_map[ $primary->slug ]['url'], ); } } $items[] = array( '@type' => 'ListItem', 'position' => $pos++, 'name' => get_the_title(), 'item' => get_permalink(), ); } ``` ### A13 — AboutPage en /nosotros/ ```php add_action( 'wp_head', function () { if ( ! is_page( 'nosotros' ) ) return; $schema = array( '@context' => 'https://schema.org', '@type' => 'AboutPage', '@id' => 'https://www.fibrolab.cl/nosotros/#aboutpage', 'url' => 'https://www.fibrolab.cl/nosotros/', 'name' => 'Nosotros — Fibrolab', 'description' => 'Fábrica e instalación de piscinas de fibra de vidrio desde 2020. Más de 1.000 instalaciones en todo Chile.', 'inLanguage' => 'es-CL', 'about' => array( '@id' => 'https://www.fibrolab.cl/#localbusiness' ), ); echo '' . "\n"; }, 25 ); ``` ### C6 — Font size product card mobile ```css /* assets/css/fibrolab.css — dentro de @media (max-width: 768px): */ .fibrolab-product-card__title { font-size: 13px; line-height: 1.3; } /* era 9px */ .fibrolab-label { font-size: 10px; } /* era 9px */ ``` --- ## Resumen ejecutivo (TL;DR) **Score 64/100 (+1 vs v2).** El sitio mejoró en backend (security headers, IndexNow, dedup schema) pero **9 de los issues críticos de v2 siguen sin fixear**: title sin tilde, Merchant Center bloqueado por Offer incompleto, `/contacto/` inexistente, páginas legales 404, sin CAE/Sernac, Manufacturer ausente del `@type`, `postalCode` no verificado, GBP no enlazado, breadcrumb producto incompleto. **Hallazgos NUEVOS (12)** detectados en esta corrida que v2 no listó: 1. Type-collision en JSON-LD home (Organization vs LocalBusiness con mismo @id) 2. `/paneles-solares/` 404 (probable página WP eliminada, template aún existe) 3. Font Awesome cargado externo desde cdnjs (LCP -200/-300ms) 4. `fibrolab.css` 271KB sin defer en código (filtro `style_loader_tag` no implementado) 5. OpenReplay en `wp_head` priority 1 (impacta critical path) 6. Hero `background-image` en /piscinas-de-fibra/ y /nosotros/ (preload scanner ciego) 7. Hero del home mobile sin texto/CTA (above-the-fold huérfano) 8. `font-size: 9px` en titulos de product cards mobile 9. 30 imágenes `loading="eager"` en galería /piscinas-de-fibra/ 10. post-sitemap.xml con lastmod 2024-11-17 (blog congelado 17 meses) 11. Logs en uploads accesibles (csp-violations.log, indexnow.log) 12. Bots IA importantes faltantes en robots.txt (Google-CloudVertexBot, anthropic-ai, Bytespider) **Mayor ROI inmediato (priorizado):** C1 (`hasMerchantReturnPolicy`), C7 (title tilde), C8 (llms.txt URL), C6 (font-size 9px), A1 (`Manufacturer` + `Organization` en @type), A6 (defer CSS), A5 (self-host Font Awesome). Total esfuerzo conjunto: ~3 horas; cubre Merchant Center, type-collision, LCP -500ms, AI citation y legibilidad mobile. **Mayor complejidad pero crítico:** C2 (página `/contacto/`), C3 (legales), A19 (`/nosotros/` con equipo nombrado). Total ~10 horas pero cierra el gap de Trustworthiness (30% del peso E-E-A-T) y compliance Sernac. **Mayor ROI local pack:** **C10** — publicar las 8 páginas comunales con `template-comuna.php` ya construido. Cero código nuevo (solo crear páginas WP y llenar 6 campos ACF por comuna). Es el único item del plan que ataca el factor #1 del local pack ranking (páginas dedicadas por área de servicio). 1-2 días de trabajo de contenido, no de código. Combinado con C11 (importar 10 testimonios → AggregateRating + estrellas en SERP) y A2 (GBP en sameAs), el Local SEO Score sube de 49 → ~75 en una sprint de tres días. --- ## Verificación cruzada de hallazgos Para evitar falsos positivos, los issues marcados ❌ NO FIXEADOS y los NUEVOS HALLAZGOS fueron verificados en **dos fuentes** mínimo: | Issue | Fuente 1 | Fuente 2 | |---|---|---| | Title sin tilde | curl `` | OG title meta | | `hasMerchantReturnPolicy` ausente | curl + Python parse JSON-LD `/modelo/piscina-4-8-metros/` | functions.php:595-608 (agente schema) | | og:type article en categorías | curl `<meta property="og:type">` ×3 URLs | agente schema | | `/contacto/` 301→home | curl -IL | agente local NAP audit | | Páginas legales 404 | curl HEAD ×3 URLs | agente content + agente local | | Type-collision JSON-LD home | Python parse de los 2 bloques en home | agente schema (SC-001) | | `/paneles-solares/` 404 | curl HEAD + GET (redirect a página de error 404 noindex) | agente content (footer.php:32 link comentado) | | Font Awesome cdnjs | curl `<link rel='stylesheet'>` | agente technical (CWV-01) | | llms.txt URL incorrecta | curl `/llms.txt` grep "spa-y-jacuzzi" | (era issue v2) | | Hero mobile sin texto | agente visual VIS-001 | inspección de `front-page.php` (H1 al final) | | `font-size: 9px` cards mobile | agente visual VIS-005 | (verificable abriendo `assets/css/fibrolab.css` `@media (max-width: 768px)`) | | `template-comuna.php` 0 páginas publicadas | agente local | page-sitemap.xml (11 URLs, ninguna `/piscinas-en-*/`) | **Falsos positivos descartados durante el cruzado:** - El agente technical (SD-01) afirmó que `HomeAndConstructionBusiness` no es un tipo válido de Schema.org. **Verificación**: `https://schema.org/HomeAndConstructionBusiness` devuelve HTTP 200 — el tipo SÍ existe. Lo que sí falta es agregar `Organization` + `Manufacturer` al array (cubierto en A1), no remover `HomeAndConstructionBusiness`. - El agente technical también listó "X-XSS-Protection deprecado" como issue. Es deprecado pero sigue siendo aceptado por navegadores antiguos; severidad real LOW (recategorizada).