Commit Graph

60 Commits

Author SHA1 Message Date
FrankZamora
ce0179a134 feat: implement is_critical CSS injection via CriticalCSSService
- Created CriticalCSSService (singleton) that queries BD directly in wp_head
- Service generates CSS BEFORE components render (priority 1)
- Renderers check is_critical flag and skip inline CSS if true
- Made generateCSS() public in Renderers for CriticalCSSService to use
- Removed CriticalCSSCollector pattern (timing issue with WordPress)

Flow:
1. wp_head (priority 1) → CriticalCSSService::render()
2. Service queries BD for components with visibility.is_critical=true
3. Generates CSS using Renderer->generateCSS() methods
4. Outputs: <style id="roi-critical-css">...</style>
5. When Renderers execute, they detect is_critical and omit CSS inline

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 10:06:38 -06:00
FrankZamora
38d7099bcd fix(renderers): corregir timing issue en CSS crítico
PROBLEMA:
- wp_head() se ejecuta ANTES de que los componentes rendericen
- CriticalCSSCollector estaba vacío al momento de inyectar en <head>
- Componentes retornaban solo HTML sin CSS → sitio sin estilos

SOLUCIÓN:
- Eliminar lógica condicional de is_critical en render()
- Siempre incluir CSS inline con el componente (comportamiento anterior)
- Campo is_critical reservado para futura implementación con output buffering

Archivos modificados:
- NavbarRenderer.php
- TopNotificationBarRenderer.php
- HeroRenderer.php

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 09:42:18 -06:00
FrankZamora
4f25297f14 feat(pagespeed): implementar campo is_critical para CSS crítico dinámico (Phase 4.2)
Implementación completa del sistema de Critical CSS dinámico según plan 13.01:

Domain Layer:
- Crear CriticalCSSCollectorInterface para DIP compliance

Infrastructure Layer:
- Implementar CriticalCSSCollector (singleton via DIContainer)
- Crear CriticalCSSHooksRegistrar para inyección en wp_head
- Actualizar DIContainer con getCriticalCSSCollector()

Schemas:
- Agregar campo is_critical a navbar, top-notification-bar, hero
- Sincronizar con BD (18+39+31 campos)

Renderers (navbar, top-notification-bar, hero):
- Inyectar CriticalCSSCollectorInterface via constructor
- Lógica condicional: si is_critical=true → CSS a <head>

Admin (FormBuilders + FieldMappers):
- Toggle "CSS Crítico" en sección visibility
- Mapeo AJAX para persistencia

Beneficios:
- LCP optimizado: CSS crítico inline en <head>
- Above-the-fold rendering sin FOUC
- Componentes configurables desde admin panel

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 09:29:45 -06:00
FrankZamora
956819cf14 fix(anchor): Agregar width 100% a .roi-anchor-content
El ins.adsbygoogle tenia width 0 porque el contenedor padre
no tenia ancho definido. Esto causaba el error
"No slot size for availableWidth=0" de AdSense.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:53:28 -06:00
FrankZamora
46ad8340c3 fix(adsense): Anchor/Vignette solo visibles cuando AdSense llena slot
- Anchor Ads: Cambiar de visibility:hidden a transform:translateY()
  para que AdSense pueda medir dimensiones del slot
- Vignette Ads: Solo mostrar overlay cuando data-ad-status="filled"
- Mover card Exclusiones a columna izquierda en admin

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:44:05 -06:00
FrankZamora
4294a7c07b fix(rail): Add 15px margin to prevent hero overlap 2025-11-28 21:34:31 -06:00
FrankZamora
8aba07fdbf fix(vignette): Tamaños 16:9 para video + sin botón cerrar
- Agregados tamaños video: 1280x720, 960x540, 854x480, 800x450, 640x360, 560x315
- Eliminado botón de cerrar (usuario cierra haciendo clic fuera)
- Default cambiado a 960x540 (qHD)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:29:41 -06:00
FrankZamora
13beaf7b06 fix(adsense): Anchor ocultos por defecto + más tamaños Vignette
Anchor Ads:
- Ocultos por defecto via CSS (opacity: 0, visibility: hidden)
- Solo se muestran cuando AdSense llena el slot (clase .ad-loaded)
- Ya no aparece espacio en blanco si no hay anuncio

Vignette Ads:
- Agregados tamaños: 728x90, 970x250, 970x90, 468x60, 320x100
- Nueva opción "auto" (recomendado) para formato automático
- Renderer actualizado para manejar todos los tamaños

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:25:54 -06:00
FrankZamora
7edddada89 fix(adsense): ocultar anchor ads cuando AdSense no llena el slot
- Agregar watchUnfilledAds() con MutationObserver
- Detectar data-ad-status="unfilled" de AdSense
- Timeout de 5s como respaldo si no hay contenido
- Evitar mostrar espacio en blanco cuando no hay anuncio

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:10:40 -06:00
FrankZamora
b96a13427e feat(adsense): implementar Anchor Ads y Vignette Ads
- Anchor Ads: anuncios fijos top/bottom con botones minimizar/cerrar
- Vignette Ads: modal fullscreen con triggers configurables
- Schema v1.3.0 con grupos anchor_ads y vignette_ads (18 campos)
- FieldMapper actualizado para persistir settings en BD
- JavaScript para interacción (colapso, cierre, localStorage)
- Soporte para responsive y tamaños fijos en vignette

IMPORTANTE: Ejecutar en servidor remoto:
wp roi-theme sync-component adsense-placement

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 21:00:00 -06:00
FrankZamora
cec8b8dccd fix(rail-ads): rail derecho right:0px 2025-11-27 22:36:25 -06:00
FrankZamora
e8ead33311 fix(rail-ads): rail izquierdo left:0px para evitar corte 2025-11-27 22:34:47 -06:00
FrankZamora
9e8ffdb26f fix(rail-ads): agregar padding y max-width para evitar desbordamiento 2025-11-27 22:24:56 -06:00
FrankZamora
ec64ea38ea fix(rail-ads): alinear ads hacia el contenido - izq flex-end, der flex-start 2025-11-27 22:20:59 -06:00
FrankZamora
e7fc0f1408 fix(rail-ads): agregar overflow:hidden para forzar ancho calculado 2025-11-27 22:18:47 -06:00
FrankZamora
f4e3a61df8 fix(rail-ads): quitar min-width que causaba ancho incorrecto 2025-11-27 22:14:22 -06:00
FrankZamora
961f663107 fix(rail-ads): corregir rail izq cortado y ocultar rails cerca del footer
- Agregar min-width: 170px para evitar corte
- Quitar overflow:hidden que cortaba contenido
- Detectar footer y ocultar rails cuando se acercan
- Transicion suave de opacity para ocultar/mostrar
2025-11-27 22:11:02 -06:00
FrankZamora
21ac98c969 fix(rail-ads): revertir a anuncio 160px fijo centrado en container responsive 2025-11-27 22:07:04 -06:00
FrankZamora
c9c6a5ac7b fix(rail-ads): bajar umbral media query de 1620px a 1400px 2025-11-27 21:59:50 -06:00
FrankZamora
6b6ebd3c6d feat(rail-ads): rails responsive que llenan el espacio disponible
- Ancho calculado automaticamente: (viewport - container) / 2 - 20px
- 10px margen del viewport + 10px gap al container
- Selector simplificado: solo altura (250-1050px)
- AdSense usa data-full-width-responsive para adaptarse
- Media query actualizada: oculta en pantallas < 1620px
2025-11-27 21:55:04 -06:00
FrankZamora
070ee7398c fix(rail-ads): cambiar posicionamiento de 15px a 5px del borde del viewport 2025-11-27 21:48:01 -06:00
FrankZamora
ce19345f78 feat(rail-ads): Add more format options with multiple widths
- Added width options: 130px, 140px, 150px, 160px, 300px, 400px, 500px, 600px
- Each width has multiple height options (300, 400, 500, 600, etc.)
- Total of 31 format combinations available
- Updated Schema, Renderer and FormBuilder

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:44:18 -06:00
FrankZamora
1b9910165b fix(rail-ads): Position rails fixed at viewport edges
- Changed Rail Ads positioning from container-width-based formula to fixed 15px from viewport edges
- Rails no longer move inward when container width is reduced
- Fixes overlap issue when layout width setting changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:38:04 -06:00
FrankZamora
72ef7580fc fix: Container width setting now applies correctly + Rail Ads improvements
- Fix container width not applying: css-global-responsive.css now uses
  CSS variable --roi-container-width instead of hardcoded values
- Add 8 Rail format options: slim-small (160x300), slim-medium (160x400),
  slim-large (160x500), skyscraper (160x600), slim-xlarge (160x700),
  wide-skyscraper (160x800), half-page (300x600), large-skyscraper (300x1050)
- Change rail_top_offset from text input to select with preset values
- Fix Rail Ads JavaScript positioning (moved after HTML, added retries)
- ThemeSettingsRenderer now always outputs CSS variables for layout

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:30:06 -06:00
FrankZamora
122bcd4750 feat(adsense): agregar mas opciones de formato y altura para Rail Ads
- Formatos: skyscraper (160x600), wide-skyscraper (160x800), half-page (300x600), large-skyscraper (300x1050)
- Distancia desde arriba: 150, 200, 300 (default), 400, 500, 700px
- Cambiar rail_top_offset de text a select con opciones predefinidas

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:05:49 -06:00
FrankZamora
0dfe3fcd2c feat(theme-settings): agregar configuracion de ancho del contenedor
- Nuevo grupo 'Layout y Contenedor' en theme-settings
- Opciones: 1140px, 1200px, 1320px (default), 1400px, 100%
- CSS dinamico aplicado via ThemeSettingsRenderer
- Corregir selectores de hero en Rail Ads (.hero-section, .featured-image-container)
- Agregar setTimeout para esperar carga de DOM
- Aumentar gap de separacion a 30px
- Subir maxTop al 40% del viewport

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:03:43 -06:00
FrankZamora
2fa112ab7f fix(adsense): corregir posicionamiento de Rail Ads
- Usar CSS max() para evitar rail izquierdo cortado fuera del viewport
- Agregar JavaScript inteligente para detectar navbar/hero dinámicamente
- Rail ads se posicionan debajo del hero cuando es visible
- Usar requestAnimationFrame para throttle de scroll
- Eliminar dependencia de valores fijos en pixels

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:55:18 -06:00
FrankZamora
55f061df67 feat(adsense): reorganizar panel con UX mejorada y soporte 1-8 ads random
Panel AdSense reorganizado:
- Diagrama visual mostrando ubicaciones de anuncios (POST-TOP, IN-CONTENT, POST-BOTTOM, RAIL)
- Secciones colapsables por ubicación con badges de color
- Slots con descripciones claras indicando uso (Auto, In-Article, Display, etc.)

In-Content Ads mejorado:
- Soporte para 1-8 anuncios dentro del contenido
- Modo aleatorio (random) que varía posiciones en cada visita
- Configuración de mínimo/máximo de ads
- Párrafos mínimos entre anuncios configurable (2-6)
- Primer ad siempre en posición fija configurada

Archivos modificados:
- Schema v1.2.0 con 4 nuevos campos (random_mode, min_ads, max_ads, min_paragraphs_between)
- FormBuilder con diagrama visual y mejor organización
- ContentAdInjector con lógica de posicionamiento random
- Renderer con soporte para post-content-1 hasta post-content-8
- FieldMapper actualizado con nuevos campos

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:45:40 -06:00
FrankZamora
b70e11be62 refactor: move Analytics from ThemeSettings to AdsensePlacement
- Remove Analytics and AdSense tabs from theme-settings component
- Add Analytics group to adsense-placement component
- Add roi_enqueue_analytics_script() for GA4/UA support
- Clean up ThemeSettings to only handle custom code (CSS/JS)
- Update FormBuilders and FieldMappers accordingly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 18:43:39 -06:00
FrankZamora
371995d151 fix(accessibility): Add main landmark and fix cta-box-title heading
Phase 4.4 Accessibility fixes:
- single.php: Add <main id="main-content" role="main"> landmark
- CtaBoxSidebarRenderer: h5 cta-box-title changed to span

Fixes: "No main landmark" and "Headings skip levels"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:03:22 -06:00
FrankZamora
1c901ecdf9 fix(accessibility): Fix cta-post contrast and heading hierarchy
Phase 4.4 Accessibility fixes:
- cta-post: button_text_color from #ffffff to #0E2337 (WCAG AA 4.8:1)
- TableOfContentsRenderer: h4 toc-title changed to span (semantic)
- FooterRenderer: h5 widget-title changed to span (5 instances)

Fixes: "Low contrast on cta-button" and "Headings skip levels"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:59:06 -06:00
FrankZamora
281c05fa33 fix(accessibility): Correct heading hierarchy and identical links
Phase 4.4 Accessibility fixes:
- ContactFormRenderer: Change h6 info-labels to span (WhatsApp, Email, Location)
- RelatedPostRenderer: Change h5 card-title to span (semantic hierarchy)
- top-notification-bar schema: Change link_url default from # to /suscripcion-vip
  (identical links must have same destination)

Fixes: "Headings not in sequential order" and "Identical links have different purposes"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:45:38 -06:00
FrankZamora
d7915d372b refactor(adsense): remove dead code + PageSpeed CSS defer
- Remove unused roi_should_disable_auto_ads() function
- Remove enable_page_level_ads code (Auto Ads disabled in Google panel)
- Defer non-critical CSS with media=print pattern (Fase 4.2 PageSpeed)
- Fix roi-accessibility dependency: roi-theme-style -> roi-main-style

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:38:49 -06:00
FrankZamora
99cde7c3d6 fix(adsense): registrar filtro the_content y corregir ancho de contenedor
- Registra filtro the_content para inyectar anuncios (post-top, post-bottom, content)
- Corrige CSS del contenedor .roi-ad-slot con width:100% para evitar availableWidth=0
- Usa ContentAdInjector para insertar ads dentro del contenido

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:07:12 -06:00
FrankZamora
50a8c2bf18 debug: remove condition to test if enqueue works 2025-11-27 14:42:43 -06:00
FrankZamora
096f9716ef fix(youtube-facade): use is_singular() instead of is_single()
Changed condition from is_single() to is_singular() to ensure
YouTube facade assets load on all singular content types.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:41:42 -06:00
FrankZamora
cd09666f1d Backup antes de optimizar Bootstrap Icons (subset)
Estado actual:
- Bootstrap Icons completo: 211 KB (2050 iconos)
- Solo usamos 105 iconos (5.1%)

Próximo paso: crear subset de iconos para ahorrar ~199 KB

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:31:04 -06:00
FrankZamora
b43cb22dc1 feat(youtube-facade): Phase 2.4 complete - YouTube Facade for PageSpeed
- Replace YouTube iframes with lightweight facade (thumbnail + play button)
- Load real iframe only on user click
- Reduces TBT by ~2000ms
- Works with mu-plugin allow-unfiltered-html.php
- Filter priority 101 (after RCP)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:05:34 -06:00
FrankZamora
deef577c36 fix: Change filter priority to 101 (after RCP) 2025-11-27 13:58:20 -06:00
FrankZamora
d5bdb81cbe debug: Add result verification logging 2025-11-27 13:57:17 -06:00
FrankZamora
56a7c29653 debug: Add renderer output logging 2025-11-27 13:55:09 -06:00
FrankZamora
acdfeffd75 debug: Add detailed pattern matching logging 2025-11-27 13:53:56 -06:00
FrankZamora
d867212790 Debug: Add logging to hooks registration 2025-11-27 13:41:13 -06:00
FrankZamora
98c90756f8 Debug: Add minimal logging to verify filter execution 2025-11-27 13:40:09 -06:00
FrankZamora
52e2698279 feat(youtube-facade): Phase 2.4 - YouTube Facade Pattern for PageSpeed optimization
- Replace YouTube iframes with lightweight facade (thumbnail + play button)
- Load real iframe only on user click
- Reduces TBT by ~2000ms
- Uses youtube-nocookie.com for privacy-enhanced mode
2025-11-27 13:37:36 -06:00
FrankZamora
83b594a750 Debug: Add file-based logging to bypass WP_DEBUG 2025-11-27 13:36:41 -06:00
FrankZamora
4ac03bd3e2 Debug: Add logging to YouTube Facade filter to diagnose issue 2025-11-27 13:33:45 -06:00
FrankZamora
ec8f1f0589 fix(youtube-facade): improve regex pattern for iframe detection
- Made regex more flexible to handle various attribute orders
- Added quick check before regex processing
- Added null check for preg_replace_callback result
- Supports both single and double quotes in src attribute

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 13:31:11 -06:00
FrankZamora
133b364c78 feat(pagespeed): implement YouTube Facade Pattern - Phase 2.4
PageSpeed Optimization to reduce TBT by ~2000ms:
- Add YoutubeFacade module following Clean Architecture
- Replace YouTube iframes with thumbnail + play button
- Load real iframe only on user click (lazy-load)
- Reduces initial page blocking time significantly

Files added:
- Public/YoutubeFacade/Infrastructure/Wordpress/YoutubeFacadeHooksRegistrar.php
- Public/YoutubeFacade/Infrastructure/Services/YoutubeFacadeContentFilter.php
- Public/YoutubeFacade/Infrastructure/Ui/YoutubeFacadeRenderer.php
- Public/YoutubeFacade/Infrastructure/Ui/Assets/Css/youtube-facade.css
- Public/YoutubeFacade/Infrastructure/Ui/Assets/Js/youtube-facade.js

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 13:28:20 -06:00
FrankZamora
90ac8a16cc perf: Agregar min-height a Hero Section para reducir CLS
- Leer campos min_height, title_min_height, badge_min_height del schema
- Aplicar min-height a .hero-section (120px)
- Aplicar min-height a .hero-section__title (3rem)
- Aplicar min-height a .hero-section__badge (32px)

Fase 1 del plan de optimización PageSpeed (99-pagespeed-optimization-plan.md)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 11:56:08 -06:00