diff --git a/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php b/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php index 50e6a9fa..d5aca7aa 100644 --- a/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php +++ b/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php @@ -66,33 +66,56 @@ final class AdsensePlacementRenderer // 4. Generar CSS (usando CSSGeneratorService) $lazyEnabled = ($settings['behavior']['lazy_loading_enabled'] ?? true) === true; - // Estrategia basada en documentación oficial de Google AdSense: - // https://support.google.com/adsense/answer/10762946 + // Estrategia para evitar "flash" de slots vacíos: // - // IMPORTANTE: NO ocultar slots inicialmente porque AdSense puede no - // ejecutar la solicitud de anuncios para slots ocultos. + // PROBLEMA: Si mostramos slots con min-height, hay un "flash" visible + // entre que el slot aparece y AdSense lo marca como unfilled. // - // La solución correcta es: - // 1. Mostrar slots con min-height para reservar espacio (evita CLS) - // 2. Usar CSS oficial de Google para ocultar slots unfilled: - // ins.adsbygoogle[data-ad-status="unfilled"] { display: none !important; } - // 3. El contenedor colapsa automáticamente cuando el ins se oculta + // SOLUCIÓN: Ocultar slots INICIALMENTE (height:0, overflow:hidden) + // y SOLO mostrarlos cuando tienen data-ad-status="filled". + // + // NOTA: Usamos height:0 + overflow:hidden en vez de display:none + // porque AdSense necesita que el elemento exista en el layout para procesarlo. - // CSS base para todos los slots + // CSS base: slots COLAPSADOS por defecto (sin flash) $css = $this->cssGenerator->generate( ".roi-ad-slot", [ 'width' => '100%', 'min_width' => '300px', - 'margin_top' => '1.5rem', - 'margin_bottom' => '1.5rem', 'text_align' => 'center', - 'min_height' => '100px', // Reservar espacio mínimo para evitar CLS + 'overflow' => 'hidden', + // COLAPSADO por defecto - evita el flash + 'height' => '0', + 'margin' => '0', + 'padding' => '0', + 'opacity' => '0', + 'transition' => 'height 0.3s ease, margin 0.3s ease, opacity 0.3s ease', ] ); - // Solución oficial de Google para ocultar slots sin anuncios - // Ref: https://support.google.com/adsense/answer/10762946 + // SOLO mostrar cuando AdSense confirma que hay anuncio (filled) + // Esto es la clave: el slot permanece oculto hasta confirmación + $css .= $this->cssGenerator->generate( + ".roi-ad-slot:has(ins.adsbygoogle[data-ad-status='filled'])", + [ + 'height' => 'auto', + 'margin_top' => '1.5rem', + 'margin_bottom' => '1.5rem', + 'opacity' => '1', + ] + ); + + // Fallback JS: clase añadida por adsense-loader.js cuando detecta filled + $css .= $this->cssGenerator->generate('.roi-ad-slot.roi-ad-filled', [ + 'height' => 'auto', + 'margin_top' => '1.5rem', + 'margin_bottom' => '1.5rem', + 'opacity' => '1', + ]); + + // Slots unfilled permanecen colapsados (ya lo están por defecto) + // Pero añadimos el selector explícito para claridad $css .= $this->cssGenerator->generate( "ins.adsbygoogle[data-ad-status='unfilled']", [ @@ -100,23 +123,8 @@ final class AdsensePlacementRenderer ] ); - // Cuando el ins está oculto, colapsar el contenedor también - // Usamos :has() para detectar cuando el ins hijo está unfilled - // Nota: :has() tiene buen soporte en navegadores modernos (2023+) - $css .= $this->cssGenerator->generate( - ".roi-ad-slot:has(ins.adsbygoogle[data-ad-status='unfilled'])", - [ - 'min_height' => '0', - 'margin' => '0', - 'padding' => '0', - ] - ); - - // Fallback para navegadores sin soporte :has() - usar clase JS + // Fallback para navegadores sin soporte :has() - clase JS $css .= $this->cssGenerator->generate('.roi-ad-slot.roi-ad-empty', [ - 'min_height' => '0', - 'margin' => '0', - 'padding' => '0', 'display' => 'none', ]); diff --git a/functions.php b/functions.php index 6333f62d..814461ed 100644 --- a/functions.php +++ b/functions.php @@ -18,7 +18,7 @@ if (!defined('ABSPATH')) { } // Definir constante de versión del tema -define('ROI_VERSION', '1.0.27'); +define('ROI_VERSION', '1.0.28'); // ============================================================================= // 1. CARGAR AUTOLOADER MANUAL