{"id":"cs-1782776672041-iqipjw19","status":"done","createdAt":1782776672041,"finishedAt":1782776910003,"meta":{"projectName":"xzonassite","projectPath":"C:\\xampp\\htdocs\\xzonassite","messagePreview":"MODO REVISIÓN — xzonas lab :9080\nAgente: code · Refactor PHP acotado\n\nPropón mejoras SEO filter pages","missionId":null,"phaseId":null},"events":[{"event":"status","data":{"text":"Modo IDE / sesión — completo (80 herramientas, uso selectivo)"},"at":1782776672051},{"event":"status","data":{"text":"Agente"},"at":1782776674853},{"event":"status","data":{"text":"Modo revisión: snapshot local por archivo"},"at":1782776674853},{"event":"agent","data":{"agentId":"agent-4f769eff-09ef-4346-9fec-10cec042ee5b","projectPath":"C:\\xampp\\htdocs\\xzonassite"},"at":1782776674853},{"event":"changes","data":{"sessionId":"cs-1782776672051-6xexnb","pending":0},"at":1782776674853},{"event":"status","data":{"text":"Procesando…"},"at":1782776677071},{"event":"tool_activity","data":{"activity":{"id":"tool_1b1799e7-5e1a-4cb7-b46e-72972b7f21d","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-29T23:45:07.087Z"}},"at":1782776707087},{"event":"tool_activity","data":{"activity":{"id":"tool_bb6166b1-5f2b-4568-bcd6-b8f08abb7c9","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:45:07.093Z"}},"at":1782776707093},{"event":"text","data":{"chunk":"Revisando el transcript previo y el código de páginas de filtro SEO para proponer mejoras concretas.\n"},"at":1782776910003},{"event":"tool_activity","data":{"activity":{"id":"tool_1b1799e7-5e1a-4cb7-b46e-72972b7f21d","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-29T23:45:07.450Z"}},"at":1782776707450},{"event":"tool_activity","data":{"activity":{"id":"tool_bb6166b1-5f2b-4568-bcd6-b8f08abb7c9","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:45:11.314Z"}},"at":1782776711314},{"event":"tool_activity","data":{"activity":{"id":"tool_c9f63fc3-9df3-48c1-b4c6-cd24cedc2b6","name":"read","status":"running","summary":"read: …9b1dd7-7869-4e0c-9c39-a9a3a107120d\\b89b1dd7-7869-4e0c-9c39-a9a3a107120d.jsonl","detail":"","at":"2026-06-29T23:45:49.234Z"}},"at":1782776749234},{"event":"tool_activity","data":{"activity":{"id":"tool_eb312894-b83c-4d4b-9c5a-ba828a8cf52","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:45:49.240Z"}},"at":1782776749240},{"event":"tool_activity","data":{"activity":{"id":"tool_c9f63fc3-9df3-48c1-b4c6-cd24cedc2b6","name":"read","status":"completed","summary":"read: …9b1dd7-7869-4e0c-9c39-a9a3a107120d\\b89b1dd7-7869-4e0c-9c39-a9a3a107120d.jsonl","detail":"","at":"2026-06-29T23:45:54.255Z"}},"at":1782776754255},{"event":"tool_activity","data":{"activity":{"id":"tool_eb312894-b83c-4d4b-9c5a-ba828a8cf52","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:45:54.330Z"}},"at":1782776754330},{"event":"tool_activity","data":{"activity":{"id":"tool_536c4ffe-bf32-41bf-8dd2-7c4e2427989","name":"grep","status":"running","summary":"grep: …ampp-htdocs-xzonassite\\agent-transcripts\\b89b1dd7-7869-4e0c-9c39-a9a3a107120d","detail":"","at":"2026-06-29T23:46:04.582Z"}},"at":1782776764582},{"event":"tool_activity","data":{"activity":{"id":"tool_4b275e1d-fe9a-4772-92ee-ee2f9c1c0ea","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-29T23:46:04.584Z"}},"at":1782776764584},{"event":"tool_activity","data":{"activity":{"id":"tool_162f761d-fbdd-474b-8ce6-9ee667a0052","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-29T23:46:04.585Z"}},"at":1782776764585},{"event":"tool_activity","data":{"activity":{"id":"tool_536c4ffe-bf32-41bf-8dd2-7c4e2427989","name":"grep","status":"completed","summary":"grep: …ampp-htdocs-xzonassite\\agent-transcripts\\b89b1dd7-7869-4e0c-9c39-a9a3a107120d","detail":"","at":"2026-06-29T23:46:04.962Z"}},"at":1782776764962},{"event":"tool_activity","data":{"activity":{"id":"tool_4b275e1d-fe9a-4772-92ee-ee2f9c1c0ea","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-29T23:46:04.965Z"}},"at":1782776764965},{"event":"tool_activity","data":{"activity":{"id":"tool_162f761d-fbdd-474b-8ce6-9ee667a0052","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-29T23:46:05.084Z"}},"at":1782776765084},{"event":"tool_activity","data":{"activity":{"id":"tool_d9b300bd-ebb5-403a-84a4-a1b125e04de","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\xzonassite\\filter-page.php","detail":"","at":"2026-06-29T23:46:25.322Z"}},"at":1782776785322},{"event":"tool_activity","data":{"activity":{"id":"tool_db0d1c0f-e16c-4d3e-afea-b9d286e3736","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\xzonassite\\includes\\filter_page_engine.php","detail":"","at":"2026-06-29T23:46:25.324Z"}},"at":1782776785324},{"event":"tool_activity","data":{"activity":{"id":"tool_d9b300bd-ebb5-403a-84a4-a1b125e04de","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\xzonassite\\filter-page.php","detail":"","at":"2026-06-29T23:46:25.451Z"}},"at":1782776785451},{"event":"tool_activity","data":{"activity":{"id":"tool_db0d1c0f-e16c-4d3e-afea-b9d286e3736","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\xzonassite\\includes\\filter_page_engine.php","detail":"","at":"2026-06-29T23:46:25.456Z"}},"at":1782776785456},{"event":"tool_activity","data":{"activity":{"id":"tool_47d1f209-2282-4893-b2ee-c2543ca6ca5","name":"grep","status":"completed","summary":"grep: …9b1dd7-7869-4e0c-9c39-a9a3a107120d\\b89b1dd7-7869-4e0c-9c39-a9a3a107120d.jsonl","detail":"","at":"2026-06-29T23:46:26.172Z"}},"at":1782776786172},{"event":"tool_activity","data":{"activity":{"id":"tool_954ac994-9c67-43d9-802f-12f90c33c7d","name":"read","status":"running","summary":"read: …ssite\\gestion-anuncios-anunciantes\\migrations\\2026-05-09_seo_filter_pages.sql","detail":"","at":"2026-06-29T23:46:41.154Z"}},"at":1782776801154},{"event":"tool_activity","data":{"activity":{"id":"tool_29d793c8-c1ae-4ab0-895c-ca8f4d18307","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\xzonassite\\cron_filter_pages_refresh.php","detail":"","at":"2026-06-29T23:46:41.155Z"}},"at":1782776801155},{"event":"tool_activity","data":{"activity":{"id":"tool_72a56246-bc78-4c60-bf43-d3dec0998bb","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:46:41.166Z"}},"at":1782776801166},{"event":"tool_activity","data":{"activity":{"id":"tool_954ac994-9c67-43d9-802f-12f90c33c7d","name":"read","status":"completed","summary":"read: …ssite\\gestion-anuncios-anunciantes\\migrations\\2026-05-09_seo_filter_pages.sql","detail":"","at":"2026-06-29T23:46:41.257Z"}},"at":1782776801257},{"event":"tool_activity","data":{"activity":{"id":"tool_29d793c8-c1ae-4ab0-895c-ca8f4d18307","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\xzonassite\\cron_filter_pages_refresh.php","detail":"","at":"2026-06-29T23:46:41.268Z"}},"at":1782776801268},{"event":"tool_activity","data":{"activity":{"id":"tool_58b9c4ad-4142-4610-8788-3bb5a71f4c1","name":"shell","status":"running","summary":"shell","detail":"Get-Content \"C:\\xampp\\htdocs\\xzonassite\\xzonas_cron_filter_pages.log\" -Tail 60","at":"2026-06-29T23:46:41.286Z"}},"at":1782776801286},{"event":"tool_activity","data":{"activity":{"id":"tool_72a56246-bc78-4c60-bf43-d3dec0998bb","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:46:52.221Z"}},"at":1782776812221},{"event":"tool_activity","data":{"activity":{"id":"tool_58b9c4ad-4142-4610-8788-3bb5a71f4c1","name":"shell","status":"completed","summary":"shell","detail":"Get-Content \"C:\\xampp\\htdocs\\xzonassite\\xzonas_cron_filter_pages.log\" -Tail 60","at":"2026-06-29T23:46:53.101Z"}},"at":1782776813101},{"event":"tool_activity","data":{"activity":{"id":"tool_71bbd45c-5e12-416d-8891-13b24a097f0","name":"glob","status":"running","summary":"glob: ","detail":"","at":"2026-06-29T23:47:19.302Z"}},"at":1782776839302},{"event":"tool_activity","data":{"activity":{"id":"tool_5e5c1f4c-94da-41c5-9d04-f8fc8c26202","name":"read","status":"running","summary":"read: …xzonassite\\gestion-anuncios-anunciantes\\herramientas\\filter-pages-manager.php","detail":"","at":"2026-06-29T23:47:19.303Z"}},"at":1782776839303},{"event":"tool_activity","data":{"activity":{"id":"tool_35650f56-37a1-41ce-bc32-68b0016e5f6","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\xzonassite\\js\\grid-location-url-sync.js","detail":"","at":"2026-06-29T23:47:19.374Z"}},"at":1782776839374},{"event":"tool_activity","data":{"activity":{"id":"tool_5e5c1f4c-94da-41c5-9d04-f8fc8c26202","name":"read","status":"completed","summary":"read: …xzonassite\\gestion-anuncios-anunciantes\\herramientas\\filter-pages-manager.php","detail":"","at":"2026-06-29T23:47:19.488Z"}},"at":1782776839488},{"event":"tool_activity","data":{"activity":{"id":"tool_35650f56-37a1-41ce-bc32-68b0016e5f6","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\xzonassite\\js\\grid-location-url-sync.js","detail":"","at":"2026-06-29T23:47:19.492Z"}},"at":1782776839492},{"event":"tool_activity","data":{"activity":{"id":"tool_71bbd45c-5e12-416d-8891-13b24a097f0","name":"glob","status":"completed","summary":"glob: ","detail":"","at":"2026-06-29T23:47:19.620Z"}},"at":1782776839620},{"event":"tool_activity","data":{"activity":{"id":"tool_dbbc5b72-1133-4f67-bd3f-508dc92143d","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\xzonassite\\sitemap-filtros.php","detail":"","at":"2026-06-29T23:47:35.183Z"}},"at":1782776855183},{"event":"tool_activity","data":{"activity":{"id":"tool_496bf8a4-8798-499d-aebe-82c1cecbfd5","name":"read","status":"running","summary":"read: …\\gestion-anuncios-anunciantes\\migrations\\2026-05-09_seo_filter_pages_seed.sql","detail":"","at":"2026-06-29T23:47:35.192Z"}},"at":1782776855192},{"event":"tool_activity","data":{"activity":{"id":"tool_c47fc74b-4314-497a-b325-22613d5a2e2","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:47:35.263Z"}},"at":1782776855263},{"event":"tool_activity","data":{"activity":{"id":"tool_dbbc5b72-1133-4f67-bd3f-508dc92143d","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\xzonassite\\sitemap-filtros.php","detail":"","at":"2026-06-29T23:47:35.336Z"}},"at":1782776855336},{"event":"tool_activity","data":{"activity":{"id":"tool_496bf8a4-8798-499d-aebe-82c1cecbfd5","name":"read","status":"completed","summary":"read: …\\gestion-anuncios-anunciantes\\migrations\\2026-05-09_seo_filter_pages_seed.sql","detail":"","at":"2026-06-29T23:47:35.338Z"}},"at":1782776855338},{"event":"tool_activity","data":{"activity":{"id":"tool_c47fc74b-4314-497a-b325-22613d5a2e2","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:47:35.653Z"}},"at":1782776855653},{"event":"tool_activity","data":{"activity":{"id":"tool_697aaba8-00d7-41ed-9d5d-d547f7ed237","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:47:45.432Z"}},"at":1782776865432},{"event":"tool_activity","data":{"activity":{"id":"tool_e6838010-ce93-44a0-b606-341732b2a1c","name":"read","status":"running","summary":"read: C:\\xampp\\htdocs\\xzonassite\\includes\\anuncio_url_helper.php","detail":"","at":"2026-06-29T23:47:45.433Z"}},"at":1782776865433},{"event":"tool_activity","data":{"activity":{"id":"tool_5b875dd3-ef03-465d-a925-50cb589ad2a","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:47:45.434Z"}},"at":1782776865434},{"event":"tool_activity","data":{"activity":{"id":"tool_e6838010-ce93-44a0-b606-341732b2a1c","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\xzonassite\\includes\\anuncio_url_helper.php","detail":"","at":"2026-06-29T23:47:45.680Z"}},"at":1782776865680},{"event":"tool_activity","data":{"activity":{"id":"tool_697aaba8-00d7-41ed-9d5d-d547f7ed237","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:47:45.695Z"}},"at":1782776865695},{"event":"tool_activity","data":{"activity":{"id":"tool_5b875dd3-ef03-465d-a925-50cb589ad2a","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:47:45.811Z"}},"at":1782776865811},{"event":"tool_activity","data":{"activity":{"id":"tool_514229c3-272c-4021-a2eb-a0be0e0032b","name":"grep","status":"running","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:47:58.216Z"}},"at":1782776878216},{"event":"tool_activity","data":{"activity":{"id":"tool_04eb3793-76df-4031-a8e7-3a87b5d2a42","name":"read","status":"completed","summary":"read: C:\\xampp\\htdocs\\xzonassite\\js\\grid-location-url-sync.js","detail":"","at":"2026-06-29T23:47:58.382Z"}},"at":1782776878382},{"event":"tool_activity","data":{"activity":{"id":"tool_514229c3-272c-4021-a2eb-a0be0e0032b","name":"grep","status":"completed","summary":"grep: C:\\xampp\\htdocs\\xzonassite","detail":"","at":"2026-06-29T23:48:01.011Z"}},"at":1782776881011},{"event":"text","data":{"chunk":"## Propuesta SEO — filter pages (`/filtro/{slug}`)\n\nEstado operativo: **36 páginas seed**, cron estable, **solo ~10 indexables** (72% en `noindex` por `<3` anuncios o vacías). El esqueleto técnico (canonical, paginación, sitemap, JSON-LD base) está bien; el gap principal es **calidad de datos + contenido + coherencia con el resto del sitio**.\n\n---\n\n### P0 — Inventario y thin content (impacto alto, PHP acotado)\n\n| Problema | Acción concreta | Archivo |\n|----------|-----------------|---------|\n| 24 slugs con 0 anuncios (`color_piel`, `nacionalidad`, `idiomas_hablados`…) | Auditar columnas reales vs seed; muchos anuncios tienen `color_piel` NULL aunque lo declaran en `filtros_txt` | `gestion-anuncios-anunciantes/migrations/2026-05-09_seo_filter_pages_seed.sql` + `fpe_build_where()` |\n| Filtros “fantasma” activos en sitemap/crawl budget | Auto-`activo=0` si `total=0` durante N refreshes, o fallback `like` en `filtros_txt` | `includes/filter_page_engine.php` → `fpe_refresh_page()` |\n| `intro_html` / `outro_html` vacíos en casi todas | Generar bloques mínimos (300–400 palabras + FAQ) solo para las 10 indexables vía panel IA | `filter-pages-manager.php` |\n| Contradicción doc vs código | Comentario dice “vacío pero indexable”; código fuerza `noindex` si `$total===0` | `filter-page.php` L77 — alinear intención |\n\n**Refactor sugerido en `fpe_build_where()`** — fallback híbrido cuando el filtro numérico devuelve pocos resultados:\n\n```php\n// Tras COUNT primario: si total < 3 y filtro_key tiene alias textual, reintentar con filtros_txt LIKE\n```\n\n---\n\n### P1 — Bugs SEO técnicos (rápidos, bajo riesgo)\n\n**1. URLs incorrectas en ItemList schema**\n\n```316:316:includes/filter_page_engine.php\n        $url = sprintf('%s/detalle-anuncio/%d', $base, (int) $a['id']);\n```\n\nLas cards ya usan `xz_build_detalle_url()`; el JSON-LD no. Google ve URLs distintas a las canónicas del HTML.\n\n→ Reutilizar `xz_build_detalle_url($a, '')` dentro de `fpe_jsonld_itemlist()`.\n\n**2. Dominio hardcodeado**\n\n```281:281:includes/filter_page_engine.php\n    $base = 'https://xzonasvalencia.com';\n```\n\n→ Usar `BASE_URL` (lab `:9080` vs prod).\n\n**3. Paginación `?page=2+`**\n\nHoy: `index,follow` en todas las páginas con resultados. Para listados filtrados conviene:\n\n- `page > 1` → `noindex,follow` + canonical a `/filtro/{slug}` (página 1), o\n- mantener `index` solo si hay intro única por página (no es el caso).\n\n→ Cambio acotado en `filter-page.php` L77–78.\n\n**4. FAQPage prometido pero ausente**\n\nEl header de `filter-page.php` menciona FAQPage; `outro_html` está pensado para ello pero no se parsea a schema.\n\n→ Añadir `fpe_jsonld_faq(array $page): ?string` que lea FAQ estructurado (JSON en `keywords_secundarias` o campo nuevo `faq_json`).\n\n---\n\n### P2 — Enlazado interno (CTR + descubrimiento)\n\nHoy el grid enlaza landings de zona (`grid-location-url-sync.js`) pero **no** filter pages.\n\n| Mejora | Dónde |\n|--------|-------|\n| API `api_seo_filter_lookup.php?filtro_key=X&value=Y` → devuelve `/filtro/{slug}` si indexable | Nuevo endpoint pequeño |\n| Banner “Ver página SEO: Escorts con WhatsApp” al activar filtro equivalente en grid | `js/grid-location-url-sync.js` (patrón de `upsertLandingSeoBanner`) |\n| Bloque “Búsquedas relacionadas” (3–6 slugs del mismo `filtro_key` o prioridad alta) | `filter-page.php` footer |\n| Breadcrumb intermedio por categoría (`/escorts-valencia`) si `categoria_id` está definido | `fpe_breadcrumb()` |\n\n---\n\n###"},"at":1782776910003},{"event":"status","data":{"text":"Procesando…"},"at":1782776909991},{"event":"text","data":{"chunk":" P3 — Rich results y UX en SERP\n\n| Gap actual | Mejora |\n|------------|--------|\n| Sin `og:image` | Primera foto del listado o imagen genérica del filtro |\n| Cards sin thumbnail | Añadir `foto`/`thumb` al SELECT en `fpe_fetch_anuncios()` + `<img loading=\"lazy\">` |\n| `@graph` incompleto | Enlazar WebPage → ItemList con `@id` / `mainEntity` |\n| Sitemap `lastmod` = `updated_at` | Usar `last_refresh` (refleja inventario real) | `sitemap-filtros.php` L130–132 |\n\n---\n\n### P4 — Operativa GSC / lab :9080\n\n1. Tras fixes P0–P1, reenviar las ~10 URLs indexables a la cola GSC (`ops/submit_gsc_priority_urls.php`).\n2. Verificar en lab que `sitemap-filtros.xml` devuelve las 10 URLs (no urlset vacío).\n3. Panel admin: columna “último crawl GSC” en `filter-pages-manager.php` (ya hay infra SEO en admin).\n\n---\n\n### Sprint recomendado (orden de implementación)\n\n```mermaid\nflowchart LR\n  A[P0: re-mapear filtros + desactivar vacíos] --> B[P1: JSON-LD + BASE_URL + paginación]\n  B --> C[P2: lookup API + banner grid]\n  C --> D[P3: thumbs + og:image + FAQ schema]\n  D --> E[GSC: submit 10 URLs]\n```\n\n**Quick win de hoy (1 archivo, ~15 líneas):** corregir `fpe_jsonld_itemlist()` + `BASE_URL` en `filter_page_engine.php` — alinea schema con URLs reales sin tocar plantilla.\n\n¿Quieres que implemente el sprint P1 (JSON-LD + canonical paginación) o prefieres empezar por P0 (auditoría de mapeo `filtro_key`/`filtro_value` contra datos reales en MySQL)?"},"at":1782776910003},{"event":"done","data":{"ok":true,"bridgeSessionId":"bs-1782527498115-0s4zbk","agentId":"agent-4f769eff-09ef-4346-9fec-10cec042ee5b","runId":"run-376c8094-a860-454f-a26e-33ddd17ecbf6","status":"finished","result":"## Propuesta SEO — filter pages (`/filtro/{slug}`)\n\nEstado operativo: **36 páginas seed**, cron estable, **solo ~10 indexables** (72% en `noindex` por `<3` anuncios o vacías). El esqueleto técnico (canonical, paginación, sitemap, JSON-LD base) está bien; el gap principal es **calidad de datos + contenido + coherencia con el resto del sitio**.\n\n---\n\n### P0 — Inventario y thin content (impacto alto, PHP acotado)\n\n| Problema | Acción concreta | Archivo |\n|----------|-----------------|---------|\n| 24 slugs con 0 anuncios (`color_piel`, `nacionalidad`, `idiomas_hablados`…) | Auditar columnas reales vs seed; muchos anuncios tienen `color_piel` NULL aunque lo declaran en `filtros_txt` | `gestion-anuncios-anunciantes/migrations/2026-05-09_seo_filter_pages_seed.sql` + `fpe_build_where()` |\n| Filtros “fantasma” activos en sitemap/crawl budget | Auto-`activo=0` si `total=0` durante N refreshes, o fallback `like` en `filtros_txt` | `includes/filter_page_engine.php` → `fpe_refresh_page()` |\n| `intro_html` / `outro_html` vacíos en casi todas | Generar bloques mínimos (300–400 palabras + FAQ) solo para las 10 indexables vía panel IA | `filter-pages-manager.php` |\n| Contradicción doc vs código | Comentario dice “vacío pero indexable”; código fuerza `noindex` si `$total===0` | `filter-page.php` L77 — alinear intención |\n\n**Refactor sugerido en `fpe_build_where()`** — fallback híbrido cuando el filtro numérico devuelve pocos resultados:\n\n```php\n// Tras COUNT primario: si total < 3 y filtro_key tiene alias textual, reintentar con filtros_txt LIKE\n```\n\n---\n\n### P1 — Bugs SEO técnicos (rápidos, bajo riesgo)\n\n**1. URLs incorrectas en ItemList schema**\n\n```316:316:includes/filter_page_engine.php\n        $url = sprintf('%s/detalle-anuncio/%d', $base, (int) $a['id']);\n```\n\nLas cards ya usan `xz_build_detalle_url()`; el JSON-LD no. Google ve URLs distintas a las canónicas del HTML.\n\n→ Reutilizar `xz_build_detalle_url($a, '')` dentro de `fpe_jsonld_itemlist()`.\n\n**2. Dominio hardcodeado**\n\n```281:281:includes/filter_page_engine.php\n    $base = 'https://xzonasvalencia.com';\n```\n\n→ Usar `BASE_URL` (lab `:9080` vs prod).\n\n**3. Paginación `?page=2+`**\n\nHoy: `index,follow` en todas las páginas con resultados. Para listados filtrados conviene:\n\n- `page > 1` → `noindex,follow` + canonical a `/filtro/{slug}` (página 1), o\n- mantener `index` solo si hay intro única por página (no es el caso).\n\n→ Cambio acotado en `filter-page.php` L77–78.\n\n**4. FAQPage prometido pero ausente**\n\nEl header de `filter-page.php` menciona FAQPage; `outro_html` está pensado para ello pero no se parsea a schema.\n\n→ Añadir `fpe_jsonld_faq(array $page): ?string` que lea FAQ estructurado (JSON en `keywords_secundarias` o campo nuevo `faq_json`).\n\n---\n\n### P2 — Enlazado interno (CTR + descubrimiento)\n\nHoy el grid enlaza landings de zona (`grid-location-url-sync.js`) pero **no** filter pages.\n\n| Mejora | Dónde |\n|--------|-------|\n| API `api_seo_filter_lookup.php?filtro_key=X&value=Y` → devuelve `/filtro/{slug}` si indexable | Nuevo endpoint pequeño |\n| Banner “Ver página SEO: Escorts con WhatsApp” al activar filtro equivalente en grid | `js/grid-location-url-sync.js` (patrón de `upsertLandingSeoBanner`) |\n| Bloque “Búsquedas relacionadas” (3–6 slugs del mismo `filtro_key` o prioridad alta) | `filter-page.php` footer |\n| Breadcrumb intermedio por categoría (`/escorts-valencia`) si `categoria_id` está definido | `fpe_breadcrumb()` |\n\n---\n\n### P3 — Rich results y UX en SERP\n\n| Gap actual | Mejora |\n|------------|--------|\n| Sin `og:image` | Primera foto del listado o imagen genérica del filtro |\n| Cards sin thumbnail | Añadir `foto`/`thumb` al SELECT en `fpe_fetch_anuncios()` + `<img loading=\"lazy\">` |\n| `@graph` incompleto | Enlazar WebPage → ItemList con `@id` / `mainEntity` |\n| Sitemap `lastmod` = `updated_at` | Usar `last_refresh` (refleja inventario real) | `sitemap-filtros.php` L130–132 |\n\n---\n\n### P4 — Operativa GSC / lab :9080\n\n1. Tras fixes P0–P1, reenviar las ~10 URLs indexables a la cola GSC (`ops/submit_gsc_priority_urls.php`).\n2. Verificar en lab que `sitemap-filtros.xml` devuelve las 10 URLs (no urlset vacío).\n3. Panel admin: columna “último crawl GSC” en `filter-pages-manager.php` (ya hay infra SEO en admin).\n\n---\n\n### Sprint recomendado (orden de implementación)\n\n```mermaid\nflowchart LR\n  A[P0: re-mapear filtros + desactivar vacíos] --> B[P1: JSON-LD + BASE_URL + paginación]\n  B --> C[P2: lookup API + banner grid]\n  C --> D[P3: thumbs + og:image + FAQ schema]\n  D --> E[GSC: submit 10 URLs]\n```\n\n**Quick win de hoy (1 archivo, ~15 líneas):** corregir `fpe_jsonld_itemlist()` + `BASE_URL` en `filter_page_engine.php` — alinea schema con URLs reales sin tocar plantilla.\n\n¿Quieres que implemente el sprint P1 (JSON-LD + canonical paginación) o prefieres empezar por P0 (auditoría de mapeo `filtro_key`/`filtro_value` contra datos reales en MySQL)?","changeSessionId":"cs-1782776672051-6xexnb","pendingChanges":0,"changes":[],"transcriptPath":null,"notifyTitle":"Agente terminado","notifyBody":"Revisando el transcript previo y el código de páginas de filtro SEO para proponer mejoras concretas.\n## Propuesta SEO — "},"at":1782776909997}]}
