diff --git a/Admin/AdsensePlacement/Infrastructure/Ui/AdsensePlacementFormBuilder.php b/Admin/AdsensePlacement/Infrastructure/Ui/AdsensePlacementFormBuilder.php index 7dee0aa8..5fb1bed4 100644 --- a/Admin/AdsensePlacement/Infrastructure/Ui/AdsensePlacementFormBuilder.php +++ b/Admin/AdsensePlacement/Infrastructure/Ui/AdsensePlacementFormBuilder.php @@ -47,6 +47,7 @@ final class AdsensePlacementFormBuilder $html .= $this->buildDiagramSection(); $html .= $this->buildPostLocationsGroup($componentId); $html .= $this->buildInContentAdsGroup($componentId); + $html .= $this->buildExclusionsGroup($componentId); $html .= ' '; // COLUMNA DERECHA (5 cols) @@ -56,7 +57,6 @@ final class AdsensePlacementFormBuilder $html .= $this->buildRailAdsGroup($componentId); $html .= $this->buildAnchorAdsGroup($componentId); $html .= $this->buildVignetteAdsGroup($componentId); - $html .= $this->buildExclusionsGroup($componentId); $html .= ' '; $html .= ''; diff --git a/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php b/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php index c2aacc02..44ae1fcc 100644 --- a/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php +++ b/Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php @@ -594,7 +594,8 @@ final class AdsensePlacementRenderer // === CSS via CSSGenerator === $cssRules = []; - // Base anchor styles - OCULTO POR DEFECTO hasta que AdSense llene el slot + // Base anchor styles - FUERA DE PANTALLA por defecto (NO usar visibility:hidden) + // Usamos transform para mover fuera de la pantalla, asi AdSense puede medir el slot $cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad', [ 'position' => 'fixed', 'left' => '0', @@ -603,32 +604,31 @@ final class AdsensePlacementRenderer 'background' => '#f8f9fa', 'border-color' => '#dee2e6', 'box-shadow' => '0 -2px 10px rgba(0,0,0,0.1)', - 'transition' => 'height 0.3s ease, transform 0.3s ease, opacity 0.3s ease', + 'transition' => 'height 0.3s ease, transform 0.3s ease', 'display' => 'flex', 'align-items' => 'center', 'justify-content' => 'center', - 'opacity' => '0', - 'visibility' => 'hidden', - 'pointer-events' => 'none', - ]); - - // Mostrar anchor cuando AdSense llena el slot - $cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad.ad-loaded', [ - 'opacity' => '1', - 'visibility' => 'visible', - 'pointer-events' => 'auto', ]); + // Anchor TOP: fuera de pantalla hacia arriba, visible cuando se carga $cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad-top', [ 'top' => '0', 'border-bottom-width' => '1px', 'border-bottom-style' => 'solid', + 'transform' => 'translateY(-100%)', ]); + // Anchor BOTTOM: fuera de pantalla hacia abajo, visible cuando se carga $cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad-bottom', [ 'bottom' => '0', 'border-top-width' => '1px', 'border-top-style' => 'solid', + 'transform' => 'translateY(100%)', + ]); + + // Mostrar anchor cuando AdSense llena el slot (desliza a posicion visible) + $cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad.ad-loaded', [ + 'transform' => 'translateY(0)', ]); // Controls container diff --git a/Public/AdsensePlacement/Infrastructure/Ui/Assets/anchor-vignette.js b/Public/AdsensePlacement/Infrastructure/Ui/Assets/anchor-vignette.js index 1bd89f11..866b3656 100644 --- a/Public/AdsensePlacement/Infrastructure/Ui/Assets/anchor-vignette.js +++ b/Public/AdsensePlacement/Infrastructure/Ui/Assets/anchor-vignette.js @@ -254,31 +254,68 @@ } /** - * Muestra el vignette + * Muestra el vignette SOLO si AdSense lleno el slot */ function showVignette() { if (!canShow() || triggered) return; triggered = true; - // Mostrar overlay - overlay.classList.add('active'); - document.body.style.overflow = 'hidden'; + // Buscar el elemento ins de AdSense dentro del overlay + var ins = overlay.querySelector('ins.adsbygoogle'); + if (!ins) return; - // Incrementar contadores - pageShowCount++; - var sessionCount = parseInt(sessionStorage.getItem(STORAGE_KEYS.sessionCount) || '0'); - sessionStorage.setItem(STORAGE_KEYS.sessionCount, (sessionCount + 1).toString()); + // Funcion para mostrar el overlay cuando el ad esta listo + function showIfFilled() { + var status = ins.getAttribute('data-ad-status'); + if (status === 'filled') { + // AdSense lleno el slot - mostrar overlay + overlay.classList.add('active'); + document.body.style.overflow = 'hidden'; - // Manejar delay del boton cerrar - var closeBtn = overlay.querySelector('.roi-vignette-close'); - if (closeBtn && closeBtn.classList.contains('delayed')) { - var delay = parseInt(closeBtn.dataset.delay || '0') * 1000; - - setTimeout(function() { - closeBtn.classList.remove('delayed'); - }, delay); + // Incrementar contadores + pageShowCount++; + var sessionCount = parseInt(sessionStorage.getItem(STORAGE_KEYS.sessionCount) || '0'); + sessionStorage.setItem(STORAGE_KEYS.sessionCount, (sessionCount + 1).toString()); + return true; + } else if (status === 'unfilled') { + // AdSense no tiene anuncio - no mostrar nada + triggered = false; // Permitir reintento mas tarde + return true; // Detener observacion + } + return false; } + + // Verificar si ya tiene estado + if (showIfFilled()) { + return; + } + + // Observar cambios en data-ad-status + var observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.type === 'attributes' && mutation.attributeName === 'data-ad-status') { + if (showIfFilled()) { + observer.disconnect(); + } + } + }); + }); + + observer.observe(ins, { + attributes: true, + attributeFilter: ['data-ad-status'] + }); + + // Timeout de seguridad: despues de 5s desconectar observer + setTimeout(function() { + observer.disconnect(); + // Si no se lleno, permitir reintento + var status = ins.getAttribute('data-ad-status'); + if (status !== 'filled') { + triggered = false; + } + }, 5000); } /**