- Replace scroll event listener with Intersection Observer in TableOfContentsRenderer
- Eliminates ~100ms forced reflows from offsetTop reads during scroll
- Revert Bootstrap CSS to blocking (media='all') - deferring caused CLS 0.954
- Keep CriticalBootstrapService available for future optimization
- Simplify CriticalCSSHooksRegistrar to only use CriticalCSSService
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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>
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>
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>
- 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>
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>
- 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>
- 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>
- 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
- 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
- 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>
- 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>
- 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>
- 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>
- 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>
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>
- 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>
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>
- 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>
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>
- 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>
- 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
- 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>
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>