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>
This commit is contained in:
@@ -73,6 +73,28 @@ final class AdsensePlacementFieldMapper implements FieldMapperInterface
|
|||||||
'adsense-placementMinContentLength' => ['group' => 'forms', 'attribute' => 'min_content_length'],
|
'adsense-placementMinContentLength' => ['group' => 'forms', 'attribute' => 'min_content_length'],
|
||||||
'adsense-placementDelayEnabled' => ['group' => 'forms', 'attribute' => 'delay_enabled'],
|
'adsense-placementDelayEnabled' => ['group' => 'forms', 'attribute' => 'delay_enabled'],
|
||||||
'adsense-placementDelayTimeout' => ['group' => 'forms', 'attribute' => 'delay_timeout'],
|
'adsense-placementDelayTimeout' => ['group' => 'forms', 'attribute' => 'delay_timeout'],
|
||||||
|
|
||||||
|
// ANCHOR ADS
|
||||||
|
'adsense-placementAnchorEnabled' => ['group' => 'anchor_ads', 'attribute' => 'anchor_enabled'],
|
||||||
|
'adsense-placementAnchorPosition' => ['group' => 'anchor_ads', 'attribute' => 'anchor_position'],
|
||||||
|
'adsense-placementAnchorHeight' => ['group' => 'anchor_ads', 'attribute' => 'anchor_height'],
|
||||||
|
'adsense-placementAnchorCollapsibleEnabled' => ['group' => 'anchor_ads', 'attribute' => 'anchor_collapsible_enabled'],
|
||||||
|
'adsense-placementAnchorShowOnMobile' => ['group' => 'anchor_ads', 'attribute' => 'anchor_show_on_mobile'],
|
||||||
|
'adsense-placementAnchorShowOnWideScreens' => ['group' => 'anchor_ads', 'attribute' => 'anchor_show_on_wide_screens'],
|
||||||
|
'adsense-placementAnchorRememberState' => ['group' => 'anchor_ads', 'attribute' => 'anchor_remember_state'],
|
||||||
|
'adsense-placementAnchorRememberDuration' => ['group' => 'anchor_ads', 'attribute' => 'anchor_remember_duration'],
|
||||||
|
|
||||||
|
// VIGNETTE ADS
|
||||||
|
'adsense-placementVignetteEnabled' => ['group' => 'vignette_ads', 'attribute' => 'vignette_enabled'],
|
||||||
|
'adsense-placementVignetteTrigger' => ['group' => 'vignette_ads', 'attribute' => 'vignette_trigger'],
|
||||||
|
'adsense-placementVignetteTriggerDelay' => ['group' => 'vignette_ads', 'attribute' => 'vignette_trigger_delay'],
|
||||||
|
'adsense-placementVignetteSize' => ['group' => 'vignette_ads', 'attribute' => 'vignette_size'],
|
||||||
|
'adsense-placementVignetteOverlayOpacity' => ['group' => 'vignette_ads', 'attribute' => 'vignette_overlay_opacity'],
|
||||||
|
'adsense-placementVignetteShowOnMobile' => ['group' => 'vignette_ads', 'attribute' => 'vignette_show_on_mobile'],
|
||||||
|
'adsense-placementVignetteShowOnDesktop' => ['group' => 'vignette_ads', 'attribute' => 'vignette_show_on_desktop'],
|
||||||
|
'adsense-placementVignetteReshowEnabled' => ['group' => 'vignette_ads', 'attribute' => 'vignette_reshow_enabled'],
|
||||||
|
'adsense-placementVignetteReshowTime' => ['group' => 'vignette_ads', 'attribute' => 'vignette_reshow_time'],
|
||||||
|
'adsense-placementVignetteMaxPerSession' => ['group' => 'vignette_ads', 'attribute' => 'vignette_max_per_session'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ final class AdsensePlacementFormBuilder
|
|||||||
$html .= $this->buildCredentialsGroup($componentId);
|
$html .= $this->buildCredentialsGroup($componentId);
|
||||||
$html .= $this->buildAnalyticsGroup($componentId);
|
$html .= $this->buildAnalyticsGroup($componentId);
|
||||||
$html .= $this->buildRailAdsGroup($componentId);
|
$html .= $this->buildRailAdsGroup($componentId);
|
||||||
|
$html .= $this->buildAnchorAdsGroup($componentId);
|
||||||
|
$html .= $this->buildVignetteAdsGroup($componentId);
|
||||||
$html .= $this->buildExclusionsGroup($componentId);
|
$html .= $this->buildExclusionsGroup($componentId);
|
||||||
$html .= ' </div>';
|
$html .= ' </div>';
|
||||||
|
|
||||||
@@ -114,6 +116,11 @@ final class AdsensePlacementFormBuilder
|
|||||||
// Diagrama visual del layout
|
// Diagrama visual del layout
|
||||||
$html .= '<div class="border rounded p-3" style="background: #f8f9fa; font-family: monospace; font-size: 11px;">';
|
$html .= '<div class="border rounded p-3" style="background: #f8f9fa; font-family: monospace; font-size: 11px;">';
|
||||||
|
|
||||||
|
// Anchor Top
|
||||||
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #d1ecf1; border: 2px solid #17a2b8;">';
|
||||||
|
$html .= ' <i class="bi bi-pin-angle"></i> <strong>ANCHOR TOP</strong> (fijo, collapsible)';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #e9ecef; border: 1px dashed #6c757d;">';
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #e9ecef; border: 1px dashed #6c757d;">';
|
||||||
$html .= ' <strong>HEADER</strong>';
|
$html .= ' <strong>HEADER</strong>';
|
||||||
@@ -169,10 +176,15 @@ final class AdsensePlacementFormBuilder
|
|||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|
||||||
// Footer
|
// Footer
|
||||||
$html .= '<div class="text-center p-2 rounded" style="background: #e9ecef; border: 1px dashed #6c757d;">';
|
$html .= '<div class="text-center p-2 mb-1 rounded" style="background: #e9ecef; border: 1px dashed #6c757d;">';
|
||||||
$html .= ' <strong>FOOTER</strong>';
|
$html .= ' <strong>FOOTER</strong>';
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|
||||||
|
// Anchor Bottom
|
||||||
|
$html .= '<div class="text-center p-2 rounded" style="background: #d1ecf1; border: 2px solid #17a2b8;">';
|
||||||
|
$html .= ' <i class="bi bi-pin-angle"></i> <strong>ANCHOR BOTTOM</strong> (fijo, collapsible)';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
// Rail Ads (laterales)
|
// Rail Ads (laterales)
|
||||||
$html .= '<div class="mt-2 d-flex justify-content-between">';
|
$html .= '<div class="mt-2 d-flex justify-content-between">';
|
||||||
$html .= ' <div class="p-2 rounded text-center" style="width: 45%; background: #f8d7da; border: 2px solid #dc3545; font-size: 10px;">';
|
$html .= ' <div class="p-2 rounded text-center" style="width: 45%; background: #f8d7da; border: 2px solid #dc3545; font-size: 10px;">';
|
||||||
@@ -183,11 +195,19 @@ final class AdsensePlacementFormBuilder
|
|||||||
$html .= ' </div>';
|
$html .= ' </div>';
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|
||||||
|
// Vignette Ad (modal)
|
||||||
|
$html .= '<div class="mt-2 p-2 rounded text-center" style="background: #f3e5f5; border: 2px solid #9c27b0;">';
|
||||||
|
$html .= ' <i class="bi bi-fullscreen"></i> <strong>VIGNETTE</strong> (modal pantalla completa)';
|
||||||
|
$html .= ' <br><small class="text-muted">Aparece segun trigger configurado</small>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|
||||||
$html .= '<div class="mt-2 small text-muted">';
|
$html .= '<div class="mt-2 small text-muted">';
|
||||||
$html .= ' <i class="bi bi-info-circle"></i> Los anuncios <span class="badge bg-warning text-dark">amarillos</span> son configurables abajo.';
|
$html .= ' <i class="bi bi-info-circle"></i> <span class="badge bg-warning text-dark">Amarillo</span> = Posts, ';
|
||||||
$html .= ' Los <span class="badge bg-danger">rojos</span> solo aparecen en pantallas >1600px.';
|
$html .= ' <span class="badge bg-danger">Rojo</span> = Rails >1600px, ';
|
||||||
|
$html .= ' <span class="badge" style="background:#17a2b8;color:white;">Cyan</span> = Anchors, ';
|
||||||
|
$html .= ' <span class="badge" style="background:#9c27b0;color:white;">Morado</span> = Vignette';
|
||||||
$html .= '</div>';
|
$html .= '</div>';
|
||||||
|
|
||||||
$html .= ' </div>';
|
$html .= ' </div>';
|
||||||
@@ -506,6 +526,177 @@ final class AdsensePlacementFormBuilder
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seccion para Anchor Ads (anuncios fijos top/bottom)
|
||||||
|
*/
|
||||||
|
private function buildAnchorAdsGroup(string $cid): string
|
||||||
|
{
|
||||||
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #17a2b8;">';
|
||||||
|
$html .= ' <div class="card-body">';
|
||||||
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
||||||
|
$html .= ' <i class="bi bi-pin-angle me-2" style="color: #17a2b8;"></i>';
|
||||||
|
$html .= ' Anuncios Fijos (Anchor)';
|
||||||
|
$html .= ' </h5>';
|
||||||
|
$html .= ' <p class="small text-muted mb-3">Anuncios fijos en el borde superior o inferior de la pantalla.</p>';
|
||||||
|
|
||||||
|
// Master switch
|
||||||
|
$anchorEnabled = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_enabled', false);
|
||||||
|
$html .= $this->buildSwitch($cid . 'AnchorEnabled', 'Activar Anchor Ads', $anchorEnabled, 'bi-power');
|
||||||
|
|
||||||
|
// Posicion
|
||||||
|
$anchorPosition = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_position', 'bottom');
|
||||||
|
$html .= $this->buildSelect($cid . 'AnchorPosition', 'Posicion del anuncio',
|
||||||
|
$anchorPosition,
|
||||||
|
[
|
||||||
|
'top' => 'Solo en la parte superior',
|
||||||
|
'bottom' => 'Solo en la parte inferior',
|
||||||
|
'both' => 'Superior e inferior'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Altura
|
||||||
|
$anchorHeight = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_height', '90');
|
||||||
|
$html .= $this->buildSelect($cid . 'AnchorHeight', 'Altura del anchor',
|
||||||
|
$anchorHeight,
|
||||||
|
['50' => '50px', '90' => '90px', '100' => '100px', '120' => '120px']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Collapsible toggle
|
||||||
|
$collapsible = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_collapsible_enabled', true);
|
||||||
|
$html .= $this->buildSwitch($cid . 'AnchorCollapsibleEnabled', 'Permitir minimizar', $collapsible, 'bi-arrows-collapse');
|
||||||
|
$html .= '<small class="text-muted d-block" style="margin-top: -8px; margin-left: 40px;">Usuario puede minimizar en lugar de cerrar</small>';
|
||||||
|
|
||||||
|
// Pantallas
|
||||||
|
$html .= '<div class="row g-2 mt-2">';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$showMobile = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_show_on_mobile', true);
|
||||||
|
$html .= $this->buildSwitch($cid . 'AnchorShowOnMobile', 'Mostrar en movil', $showMobile, 'bi-phone');
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$showWide = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_show_on_wide_screens', false);
|
||||||
|
$html .= $this->buildSwitch($cid . 'AnchorShowOnWideScreens', 'Pantallas anchas', $showWide, 'bi-display');
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
// Recordar estado
|
||||||
|
$html .= '<div class="mt-3 p-2 rounded" style="background: #e7f1ff;">';
|
||||||
|
$rememberState = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_remember_state', true);
|
||||||
|
$html .= $this->buildSwitch($cid . 'AnchorRememberState', 'Recordar cierre/colapso', $rememberState, 'bi-clock-history');
|
||||||
|
|
||||||
|
$rememberDuration = $this->renderer->getFieldValue($cid, 'anchor_ads', 'anchor_remember_duration', 'session');
|
||||||
|
$html .= $this->buildSelect($cid . 'AnchorRememberDuration', 'Duracion',
|
||||||
|
$rememberDuration,
|
||||||
|
[
|
||||||
|
'session' => 'Solo esta sesion',
|
||||||
|
'1hour' => '1 hora',
|
||||||
|
'1day' => '1 dia',
|
||||||
|
'1week' => '1 semana'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seccion para Vignette Ads (pantalla completa)
|
||||||
|
*/
|
||||||
|
private function buildVignetteAdsGroup(string $cid): string
|
||||||
|
{
|
||||||
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #9c27b0;">';
|
||||||
|
$html .= ' <div class="card-body">';
|
||||||
|
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
||||||
|
$html .= ' <i class="bi bi-fullscreen me-2" style="color: #9c27b0;"></i>';
|
||||||
|
$html .= ' Anuncios de Vineta';
|
||||||
|
$html .= ' <span class="badge bg-secondary ms-2">Pantalla Completa</span>';
|
||||||
|
$html .= ' </h5>';
|
||||||
|
$html .= ' <p class="small text-muted mb-3">Anuncios que ocupan toda la pantalla, aparecen segun el trigger configurado.</p>';
|
||||||
|
|
||||||
|
// Master switch
|
||||||
|
$vignetteEnabled = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_enabled', false);
|
||||||
|
$html .= $this->buildSwitch($cid . 'VignetteEnabled', 'Activar Vignette Ads', $vignetteEnabled, 'bi-power');
|
||||||
|
|
||||||
|
// Trigger
|
||||||
|
$vignetteTrigger = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_trigger', 'pageview');
|
||||||
|
$html .= $this->buildSelect($cid . 'VignetteTrigger', 'Cuando mostrar',
|
||||||
|
$vignetteTrigger,
|
||||||
|
[
|
||||||
|
'pageview' => 'Al cargar la pagina',
|
||||||
|
'scroll_50' => 'Al scrollear 50%',
|
||||||
|
'scroll_75' => 'Al scrollear 75%',
|
||||||
|
'exit_intent' => 'Al intentar salir',
|
||||||
|
'time_delay' => 'Despues de X segundos'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delay inicial
|
||||||
|
$triggerDelay = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_trigger_delay', '5');
|
||||||
|
$html .= $this->buildTextInput($cid . 'VignetteTriggerDelay', 'Delay inicial (segundos)', (string)$triggerDelay, '5');
|
||||||
|
|
||||||
|
// Tamano y opacidad
|
||||||
|
$html .= '<div class="row g-2 mt-2">';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$size = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_size', '300x250');
|
||||||
|
$html .= $this->buildSelect($cid . 'VignetteSize', 'Tamano',
|
||||||
|
$size,
|
||||||
|
['300x250' => '300x250', '336x280' => '336x280', 'responsive' => 'Responsive']
|
||||||
|
);
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$opacity = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_overlay_opacity', '0.7');
|
||||||
|
$html .= $this->buildSelect($cid . 'VignetteOverlayOpacity', 'Opacidad fondo',
|
||||||
|
$opacity,
|
||||||
|
['0.5' => '50%', '0.6' => '60%', '0.7' => '70%', '0.8' => '80%', '0.9' => '90%']
|
||||||
|
);
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
// Pantallas
|
||||||
|
$html .= '<div class="row g-2 mt-2">';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$showMobile = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_show_on_mobile', true);
|
||||||
|
$html .= $this->buildSwitch($cid . 'VignetteShowOnMobile', 'Mostrar en movil', $showMobile, 'bi-phone');
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$showDesktop = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_show_on_desktop', true);
|
||||||
|
$html .= $this->buildSwitch($cid . 'VignetteShowOnDesktop', 'Mostrar en desktop', $showDesktop, 'bi-display');
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
// Reaparicion
|
||||||
|
$html .= '<div class="mt-3 p-2 rounded" style="background: #f3e5f5;">';
|
||||||
|
$html .= '<p class="small fw-semibold mb-2"><i class="bi bi-arrow-repeat me-1"></i> Reaparicion</p>';
|
||||||
|
|
||||||
|
$reshowEnabled = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_reshow_enabled', true);
|
||||||
|
$html .= $this->buildSwitch($cid . 'VignetteReshowEnabled', 'Permitir reaparicion', $reshowEnabled);
|
||||||
|
|
||||||
|
$html .= '<div class="row g-2">';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$reshowTime = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_reshow_time', '5');
|
||||||
|
$html .= $this->buildSelect($cid . 'VignetteReshowTime', 'Tiempo (min)',
|
||||||
|
$reshowTime,
|
||||||
|
['1' => '1 min', '2' => '2 min', '3' => '3 min', '4' => '4 min', '5' => '5 min', '10' => '10 min', '15' => '15 min', '30' => '30 min']
|
||||||
|
);
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= ' <div class="col-6">';
|
||||||
|
$maxSession = $this->renderer->getFieldValue($cid, 'vignette_ads', 'vignette_max_per_session', '3');
|
||||||
|
$html .= $this->buildSelect($cid . 'VignetteMaxPerSession', 'Max/sesion',
|
||||||
|
$maxSession,
|
||||||
|
['1' => '1', '2' => '2', '3' => '3', '5' => '5', 'unlimited' => 'Sin limite']
|
||||||
|
);
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= '</div>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
$html .= ' </div>';
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
private function buildExclusionsGroup(string $cid): string
|
private function buildExclusionsGroup(string $cid): string
|
||||||
{
|
{
|
||||||
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #6c757d;">';
|
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #6c757d;">';
|
||||||
|
|||||||
@@ -5,10 +5,20 @@
|
|||||||
* Funciones para usar en templates:
|
* Funciones para usar en templates:
|
||||||
* - roi_render_ad_slot('post-top')
|
* - roi_render_ad_slot('post-top')
|
||||||
* - roi_render_rail_ads() - Para los margenes laterales del viewport
|
* - roi_render_rail_ads() - Para los margenes laterales del viewport
|
||||||
|
* - roi_render_anchor_ads() - Anuncios fijos top/bottom
|
||||||
|
* - roi_render_vignette_ad() - Anuncio pantalla completa
|
||||||
*
|
*
|
||||||
* Funciones auto-registradas en wp_head:
|
* Funciones auto-registradas en wp_head:
|
||||||
* - roi_enqueue_adsense_script() - Script principal de AdSense
|
* - roi_enqueue_adsense_script() - Script principal de AdSense
|
||||||
* - roi_enqueue_analytics_script() - Script de Google Analytics
|
* - roi_enqueue_analytics_script() - Script de Google Analytics
|
||||||
|
*
|
||||||
|
* Funciones auto-registradas en wp_footer:
|
||||||
|
* - roi_render_rail_ads() (priority 50)
|
||||||
|
* - roi_render_anchor_ads() (priority 51)
|
||||||
|
* - roi_render_vignette_ad() (priority 52)
|
||||||
|
*
|
||||||
|
* Funciones auto-registradas en wp_enqueue_scripts:
|
||||||
|
* - roi_enqueue_anchor_vignette_scripts() - Script JS para Anchor/Vignette
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!defined('ABSPATH')) {
|
if (!defined('ABSPATH')) {
|
||||||
@@ -374,3 +384,156 @@ function roi_render_universal_analytics_script(string $trackingId, bool $anonymi
|
|||||||
echo 'ga("send", "pageview");' . "\n";
|
echo 'ga("send", "pageview");' . "\n";
|
||||||
echo '</script>' . "\n";
|
echo '</script>' . "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renderiza Anchor Ads (anuncios fijos top/bottom)
|
||||||
|
*
|
||||||
|
* NOTA DIP: El renderer se obtiene del DIContainer, NO se instancia directamente.
|
||||||
|
*/
|
||||||
|
function roi_render_anchor_ads(): string
|
||||||
|
{
|
||||||
|
global $container;
|
||||||
|
|
||||||
|
if ($container === null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$repository = $container->getComponentSettingsRepository();
|
||||||
|
$settings = $repository->getComponentSettings('adsense-placement');
|
||||||
|
|
||||||
|
if (empty($settings)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si ocultar para usuarios logueados
|
||||||
|
if (roi_should_hide_for_logged_in($settings)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar exclusiones
|
||||||
|
if (roi_is_ad_excluded($settings)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener renderer desde DIContainer (DIP compliant)
|
||||||
|
$renderer = $container->getAdsensePlacementRenderer();
|
||||||
|
|
||||||
|
return $renderer->renderAnchorAds($settings);
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||||
|
error_log('ROI Anchor Ads: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renderiza Vignette Ad (pantalla completa)
|
||||||
|
*
|
||||||
|
* NOTA DIP: El renderer se obtiene del DIContainer, NO se instancia directamente.
|
||||||
|
*/
|
||||||
|
function roi_render_vignette_ad(): string
|
||||||
|
{
|
||||||
|
global $container;
|
||||||
|
|
||||||
|
if ($container === null) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$repository = $container->getComponentSettingsRepository();
|
||||||
|
$settings = $repository->getComponentSettings('adsense-placement');
|
||||||
|
|
||||||
|
if (empty($settings)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si ocultar para usuarios logueados
|
||||||
|
if (roi_should_hide_for_logged_in($settings)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar exclusiones
|
||||||
|
if (roi_is_ad_excluded($settings)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtener renderer desde DIContainer (DIP compliant)
|
||||||
|
$renderer = $container->getAdsensePlacementRenderer();
|
||||||
|
|
||||||
|
return $renderer->renderVignetteAd($settings);
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||||
|
error_log('ROI Vignette Ad: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook para inyectar Anchor Ads en el footer
|
||||||
|
*/
|
||||||
|
add_action('wp_footer', function() {
|
||||||
|
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
echo roi_render_anchor_ads();
|
||||||
|
}, 51);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook para inyectar Vignette Ad en el footer
|
||||||
|
*/
|
||||||
|
add_action('wp_footer', function() {
|
||||||
|
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||||
|
echo roi_render_vignette_ad();
|
||||||
|
}, 52);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encola el script JavaScript para Anchor y Vignette Ads
|
||||||
|
*/
|
||||||
|
function roi_enqueue_anchor_vignette_scripts(): void
|
||||||
|
{
|
||||||
|
global $container;
|
||||||
|
|
||||||
|
if ($container === null || is_admin()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$repository = $container->getComponentSettingsRepository();
|
||||||
|
$settings = $repository->getComponentSettings('adsense-placement');
|
||||||
|
|
||||||
|
if (!($settings['visibility']['is_enabled'] ?? false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si Anchor o Vignette estan habilitados
|
||||||
|
$anchorEnabled = $settings['anchor_ads']['anchor_enabled'] ?? false;
|
||||||
|
$vignetteEnabled = $settings['vignette_ads']['vignette_enabled'] ?? false;
|
||||||
|
|
||||||
|
if (!$anchorEnabled && !$vignetteEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si ocultar para usuarios logueados
|
||||||
|
if (roi_should_hide_for_logged_in($settings)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encolar script
|
||||||
|
wp_enqueue_script(
|
||||||
|
'roi-anchor-vignette',
|
||||||
|
get_template_directory_uri() . '/Public/AdsensePlacement/Infrastructure/Ui/Assets/anchor-vignette.js',
|
||||||
|
[],
|
||||||
|
'1.0.0',
|
||||||
|
true // En footer
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
||||||
|
error_log('ROI Anchor/Vignette Scripts: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add_action('wp_enqueue_scripts', 'roi_enqueue_anchor_vignette_scripts');
|
||||||
|
|||||||
@@ -549,4 +549,395 @@ final class AdsensePlacementRenderer
|
|||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renderiza Anchor Ads (anuncios fijos en top/bottom)
|
||||||
|
*
|
||||||
|
* @param array $settings Configuracion desde BD
|
||||||
|
* @return string HTML de los anchor ads
|
||||||
|
*/
|
||||||
|
public function renderAnchorAds(array $settings): string
|
||||||
|
{
|
||||||
|
// Verificar si Anchor Ads estan habilitados
|
||||||
|
if (!($settings['visibility']['is_enabled'] ?? false)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (!($settings['anchor_ads']['anchor_enabled'] ?? false)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$publisherId = esc_attr($settings['content']['publisher_id'] ?? '');
|
||||||
|
$slotId = $settings['content']['slot_auto'] ?? '';
|
||||||
|
|
||||||
|
if (empty($publisherId) || empty($slotId)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuracion de anchor
|
||||||
|
$anchorConfig = $settings['anchor_ads'] ?? [];
|
||||||
|
$position = $anchorConfig['anchor_position'] ?? 'bottom';
|
||||||
|
$height = (int)($anchorConfig['anchor_height'] ?? 90);
|
||||||
|
$showMobile = ($anchorConfig['anchor_show_on_mobile'] ?? true) === true;
|
||||||
|
$showWide = ($anchorConfig['anchor_show_on_wide_screens'] ?? false) === true;
|
||||||
|
$collapsible = ($anchorConfig['anchor_collapsible_enabled'] ?? true) === true;
|
||||||
|
$collapsedHeight = (int)($anchorConfig['anchor_collapsed_height'] ?? 24);
|
||||||
|
$collapseText = esc_html($anchorConfig['anchor_collapse_button_text'] ?? 'Ver anuncio');
|
||||||
|
$closePosition = $anchorConfig['anchor_close_position'] ?? 'right';
|
||||||
|
$rememberState = ($anchorConfig['anchor_remember_state'] ?? true) === true;
|
||||||
|
$rememberDuration = $anchorConfig['anchor_remember_duration'] ?? 'session';
|
||||||
|
|
||||||
|
$delayEnabled = ($settings['forms']['delay_enabled'] ?? true) === true;
|
||||||
|
$scriptType = $delayEnabled ? 'text/plain' : 'text/javascript';
|
||||||
|
$dataAttr = $delayEnabled ? ' data-adsense-push' : '';
|
||||||
|
|
||||||
|
// === CSS via CSSGenerator ===
|
||||||
|
$cssRules = [];
|
||||||
|
|
||||||
|
// Base anchor styles
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad', [
|
||||||
|
'position' => 'fixed',
|
||||||
|
'left' => '0',
|
||||||
|
'right' => '0',
|
||||||
|
'z-index' => '9999',
|
||||||
|
'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',
|
||||||
|
'display' => 'flex',
|
||||||
|
'align-items' => 'center',
|
||||||
|
'justify-content' => 'center',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad-top', [
|
||||||
|
'top' => '0',
|
||||||
|
'border-bottom-width' => '1px',
|
||||||
|
'border-bottom-style' => 'solid',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad-bottom', [
|
||||||
|
'bottom' => '0',
|
||||||
|
'border-top-width' => '1px',
|
||||||
|
'border-top-style' => 'solid',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Controls container
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-controls', [
|
||||||
|
'position' => 'absolute',
|
||||||
|
'top' => '4px',
|
||||||
|
'display' => 'flex',
|
||||||
|
'gap' => '4px',
|
||||||
|
'z-index' => '10',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-controls-left', ['left' => '8px']);
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-controls-right', ['right' => '8px']);
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-controls-center', ['left' => '50%', 'transform' => 'translateX(-50%)']);
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-btn', [
|
||||||
|
'width' => '28px',
|
||||||
|
'height' => '28px',
|
||||||
|
'border' => 'none',
|
||||||
|
'border-radius' => '4px',
|
||||||
|
'background' => 'rgba(0,0,0,0.1)',
|
||||||
|
'color' => '#333',
|
||||||
|
'cursor' => 'pointer',
|
||||||
|
'font-size' => '14px',
|
||||||
|
'display' => 'flex',
|
||||||
|
'align-items' => 'center',
|
||||||
|
'justify-content' => 'center',
|
||||||
|
'transition' => 'background 0.2s',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Collapsed state
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad.collapsed', [
|
||||||
|
'height' => $collapsedHeight . 'px !important',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad.collapsed .roi-anchor-content', [
|
||||||
|
'display' => 'none',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-expand-bar', [
|
||||||
|
'display' => 'none',
|
||||||
|
'width' => '100%',
|
||||||
|
'height' => '100%',
|
||||||
|
'background' => '#e9ecef',
|
||||||
|
'border' => 'none',
|
||||||
|
'cursor' => 'pointer',
|
||||||
|
'font-size' => '12px',
|
||||||
|
'color' => '#495057',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad.collapsed .roi-anchor-expand-bar', [
|
||||||
|
'display' => 'flex',
|
||||||
|
'align-items' => 'center',
|
||||||
|
'justify-content' => 'center',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-anchor-ad.hidden', [
|
||||||
|
'display' => 'none !important',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Media query para visibilidad
|
||||||
|
if (!$showMobile && $showWide) {
|
||||||
|
$cssRules[] = "@media (max-width: 999px) { .roi-anchor-ad { display: none !important; } }";
|
||||||
|
} elseif ($showMobile && !$showWide) {
|
||||||
|
$cssRules[] = "@media (min-width: 1000px) { .roi-anchor-ad { display: none !important; } }";
|
||||||
|
} elseif (!$showMobile && !$showWide) {
|
||||||
|
$cssRules[] = ".roi-anchor-ad { display: none !important; }";
|
||||||
|
}
|
||||||
|
|
||||||
|
$css = implode("\n", $cssRules);
|
||||||
|
$html = "<style id=\"roi-anchor-ads-css\">{$css}</style>\n";
|
||||||
|
|
||||||
|
// Renderizar anchor(s)
|
||||||
|
$controlsClass = 'roi-anchor-controls roi-anchor-controls-' . esc_attr($closePosition);
|
||||||
|
|
||||||
|
if ($position === 'top' || $position === 'both') {
|
||||||
|
$html .= $this->buildAnchorHTML('top', $height, $publisherId, $slotId, $scriptType, $dataAttr, $controlsClass, $collapsible, $collapseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($position === 'bottom' || $position === 'both') {
|
||||||
|
$html .= $this->buildAnchorHTML('bottom', $height, $publisherId, $slotId, $scriptType, $dataAttr, $controlsClass, $collapsible, $collapseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config para JavaScript (data attributes en lugar de inline JS)
|
||||||
|
$jsConfig = json_encode([
|
||||||
|
'rememberState' => $rememberState,
|
||||||
|
'rememberDuration' => $rememberDuration,
|
||||||
|
'collapsible' => $collapsible,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$html .= '<script id="roi-anchor-config" type="application/json">' . $jsConfig . '</script>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Genera HTML para un anchor individual
|
||||||
|
*/
|
||||||
|
private function buildAnchorHTML(
|
||||||
|
string $pos,
|
||||||
|
int $height,
|
||||||
|
string $client,
|
||||||
|
string $slot,
|
||||||
|
string $scriptType,
|
||||||
|
string $dataAttr,
|
||||||
|
string $controlsClass,
|
||||||
|
bool $collapsible,
|
||||||
|
string $collapseText
|
||||||
|
): string {
|
||||||
|
$posClass = 'roi-anchor-ad-' . $pos;
|
||||||
|
|
||||||
|
$collapseBtn = $collapsible
|
||||||
|
? '<button class="roi-anchor-btn" data-action="collapse" title="Minimizar"><i class="bi bi-dash"></i></button>'
|
||||||
|
: '';
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
'<div class="roi-anchor-ad %s" data-position="%s" style="height:%dpx;">
|
||||||
|
<div class="%s">
|
||||||
|
%s
|
||||||
|
<button class="roi-anchor-btn" data-action="close" title="Cerrar"><i class="bi bi-x"></i></button>
|
||||||
|
</div>
|
||||||
|
<div class="roi-anchor-content">
|
||||||
|
<ins class="adsbygoogle" style="display:block;width:100%%;height:%dpx"
|
||||||
|
data-ad-client="%s" data-ad-slot="%s"
|
||||||
|
data-ad-format="auto" data-full-width-responsive="true"></ins>
|
||||||
|
<script type="%s"%s>(adsbygoogle = window.adsbygoogle || []).push({});</script>
|
||||||
|
</div>
|
||||||
|
<button class="roi-anchor-expand-bar" data-action="expand">
|
||||||
|
<i class="bi bi-plus-circle me-1"></i> %s
|
||||||
|
</button>
|
||||||
|
</div>',
|
||||||
|
esc_attr($posClass),
|
||||||
|
esc_attr($pos),
|
||||||
|
$height,
|
||||||
|
esc_attr($controlsClass),
|
||||||
|
$collapseBtn,
|
||||||
|
$height - 10,
|
||||||
|
esc_attr($client),
|
||||||
|
esc_attr($slot),
|
||||||
|
$scriptType,
|
||||||
|
$dataAttr,
|
||||||
|
esc_html($collapseText)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renderiza Vignette Ad (pantalla completa)
|
||||||
|
*
|
||||||
|
* @param array $settings Configuracion desde BD
|
||||||
|
* @return string HTML del vignette ad
|
||||||
|
*/
|
||||||
|
public function renderVignetteAd(array $settings): string
|
||||||
|
{
|
||||||
|
// Verificar si Vignette Ads estan habilitados
|
||||||
|
if (!($settings['visibility']['is_enabled'] ?? false)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (!($settings['vignette_ads']['vignette_enabled'] ?? false)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$publisherId = esc_attr($settings['content']['publisher_id'] ?? '');
|
||||||
|
$slotId = $settings['content']['slot_display'] ?? $settings['content']['slot_auto'] ?? '';
|
||||||
|
|
||||||
|
if (empty($publisherId) || empty($slotId)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configuracion de vignette
|
||||||
|
$vignetteConfig = $settings['vignette_ads'] ?? [];
|
||||||
|
$trigger = $vignetteConfig['vignette_trigger'] ?? 'pageview';
|
||||||
|
$triggerDelay = (int)($vignetteConfig['vignette_trigger_delay'] ?? 5);
|
||||||
|
$showMobile = ($vignetteConfig['vignette_show_on_mobile'] ?? true) === true;
|
||||||
|
$showDesktop = ($vignetteConfig['vignette_show_on_desktop'] ?? true) === true;
|
||||||
|
$size = $vignetteConfig['vignette_size'] ?? '300x250';
|
||||||
|
$overlayOpacity = (float)($vignetteConfig['vignette_overlay_opacity'] ?? 0.7);
|
||||||
|
$closeDelay = (int)($vignetteConfig['vignette_close_button_delay'] ?? 0);
|
||||||
|
$reshowEnabled = ($vignetteConfig['vignette_reshow_enabled'] ?? true) === true;
|
||||||
|
$reshowTime = (int)($vignetteConfig['vignette_reshow_time'] ?? 5);
|
||||||
|
$maxPerSession = $vignetteConfig['vignette_max_per_session'] ?? '3';
|
||||||
|
$maxPerPage = $vignetteConfig['vignette_max_per_page'] ?? '1';
|
||||||
|
|
||||||
|
// Calcular dimensiones
|
||||||
|
list($adWidth, $adHeight) = $this->parseVignetteSize($size);
|
||||||
|
|
||||||
|
$delayEnabled = ($settings['forms']['delay_enabled'] ?? true) === true;
|
||||||
|
$scriptType = $delayEnabled ? 'text/plain' : 'text/javascript';
|
||||||
|
$dataAttr = $delayEnabled ? ' data-adsense-push' : '';
|
||||||
|
|
||||||
|
// === CSS via CSSGenerator ===
|
||||||
|
$cssRules = [];
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-vignette-overlay', [
|
||||||
|
'position' => 'fixed',
|
||||||
|
'top' => '0',
|
||||||
|
'left' => '0',
|
||||||
|
'right' => '0',
|
||||||
|
'bottom' => '0',
|
||||||
|
'background' => 'rgba(0,0,0,' . $overlayOpacity . ')',
|
||||||
|
'z-index' => '99999',
|
||||||
|
'display' => 'none',
|
||||||
|
'align-items' => 'center',
|
||||||
|
'justify-content' => 'center',
|
||||||
|
'opacity' => '0',
|
||||||
|
'transition' => 'opacity 0.3s ease',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-vignette-overlay.active', [
|
||||||
|
'display' => 'flex',
|
||||||
|
'opacity' => '1',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-vignette-modal', [
|
||||||
|
'position' => 'relative',
|
||||||
|
'background' => '#fff',
|
||||||
|
'border-radius' => '8px',
|
||||||
|
'padding' => '20px',
|
||||||
|
'box-shadow' => '0 10px 40px rgba(0,0,0,0.3)',
|
||||||
|
'max-width' => '95vw',
|
||||||
|
'max-height' => '95vh',
|
||||||
|
'overflow' => 'auto',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-vignette-close', [
|
||||||
|
'position' => 'absolute',
|
||||||
|
'top' => '-12px',
|
||||||
|
'right' => '-12px',
|
||||||
|
'width' => '32px',
|
||||||
|
'height' => '32px',
|
||||||
|
'border' => 'none',
|
||||||
|
'border-radius' => '50%',
|
||||||
|
'background' => '#dc3545',
|
||||||
|
'color' => '#fff',
|
||||||
|
'cursor' => 'pointer',
|
||||||
|
'font-size' => '18px',
|
||||||
|
'display' => 'flex',
|
||||||
|
'align-items' => 'center',
|
||||||
|
'justify-content' => 'center',
|
||||||
|
'box-shadow' => '0 2px 8px rgba(0,0,0,0.2)',
|
||||||
|
'transition' => 'transform 0.2s, opacity 0.3s',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-vignette-close.delayed', [
|
||||||
|
'opacity' => '0',
|
||||||
|
'pointer-events' => 'none',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$cssRules[] = $this->cssGenerator->generate('.roi-vignette-close:not(.delayed)', [
|
||||||
|
'opacity' => '1',
|
||||||
|
'pointer-events' => 'auto',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Media query para visibilidad
|
||||||
|
if (!$showMobile && $showDesktop) {
|
||||||
|
$cssRules[] = "@media (max-width: 991px) { .roi-vignette-overlay { display: none !important; } }";
|
||||||
|
} elseif ($showMobile && !$showDesktop) {
|
||||||
|
$cssRules[] = "@media (min-width: 992px) { .roi-vignette-overlay { display: none !important; } }";
|
||||||
|
} elseif (!$showMobile && !$showDesktop) {
|
||||||
|
$cssRules[] = ".roi-vignette-overlay { display: none !important; }";
|
||||||
|
}
|
||||||
|
|
||||||
|
$css = implode("\n", $cssRules);
|
||||||
|
$html = "<style id=\"roi-vignette-css\">{$css}</style>\n";
|
||||||
|
|
||||||
|
// Determinar estilo de anuncio segun tamano
|
||||||
|
$adStyle = $size === 'responsive'
|
||||||
|
? 'display:block;min-width:300px;min-height:250px'
|
||||||
|
: sprintf('display:inline-block;width:%dpx;height:%dpx', $adWidth, $adHeight);
|
||||||
|
|
||||||
|
$adFormat = $size === 'responsive' ? ' data-ad-format="auto" data-full-width-responsive="true"' : '';
|
||||||
|
|
||||||
|
$closeDelayClass = $closeDelay > 0 ? ' delayed' : '';
|
||||||
|
|
||||||
|
$html .= sprintf(
|
||||||
|
'<div id="roi-vignette-overlay" class="roi-vignette-overlay">
|
||||||
|
<div class="roi-vignette-modal">
|
||||||
|
<button class="roi-vignette-close%s" data-action="close-vignette" title="Cerrar" data-delay="%d">
|
||||||
|
<i class="bi bi-x"></i>
|
||||||
|
</button>
|
||||||
|
<ins class="adsbygoogle" style="%s"
|
||||||
|
data-ad-client="%s" data-ad-slot="%s"%s></ins>
|
||||||
|
<script type="%s"%s>(adsbygoogle = window.adsbygoogle || []).push({});</script>
|
||||||
|
</div>
|
||||||
|
</div>',
|
||||||
|
$closeDelayClass,
|
||||||
|
$closeDelay,
|
||||||
|
$adStyle,
|
||||||
|
esc_attr($publisherId),
|
||||||
|
esc_attr($slotId),
|
||||||
|
$adFormat,
|
||||||
|
$scriptType,
|
||||||
|
$dataAttr
|
||||||
|
);
|
||||||
|
|
||||||
|
// Config para JavaScript
|
||||||
|
$jsConfig = json_encode([
|
||||||
|
'trigger' => $trigger,
|
||||||
|
'triggerDelay' => $triggerDelay,
|
||||||
|
'closeDelay' => $closeDelay,
|
||||||
|
'reshowEnabled' => $reshowEnabled,
|
||||||
|
'reshowTime' => $reshowTime,
|
||||||
|
'maxPerSession' => $maxPerSession,
|
||||||
|
'maxPerPage' => $maxPerPage,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$html .= '<script id="roi-vignette-config" type="application/json">' . $jsConfig . '</script>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parsea el tamano del vignette
|
||||||
|
*/
|
||||||
|
private function parseVignetteSize(string $size): array
|
||||||
|
{
|
||||||
|
return match($size) {
|
||||||
|
'300x250' => [300, 250],
|
||||||
|
'336x280' => [336, 280],
|
||||||
|
default => [300, 250],
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,365 @@
|
|||||||
|
/**
|
||||||
|
* ROI Theme - Anchor & Vignette Ads JavaScript
|
||||||
|
*
|
||||||
|
* Logica para:
|
||||||
|
* - Mostrar/ocultar/colapsar anchors
|
||||||
|
* - Triggers de vignette (pageview, scroll, exit_intent, time_delay)
|
||||||
|
* - Persistencia con localStorage
|
||||||
|
* - Tiempo de reaparicion configurable
|
||||||
|
*
|
||||||
|
* NO usa onclick inline - usa addEventListener
|
||||||
|
*/
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
// UTILIDADES
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtiene configuracion desde script type="application/json"
|
||||||
|
*/
|
||||||
|
function getConfig(id) {
|
||||||
|
var el = document.getElementById(id);
|
||||||
|
if (!el) return null;
|
||||||
|
try {
|
||||||
|
return JSON.parse(el.textContent);
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calcula duracion en milisegundos
|
||||||
|
*/
|
||||||
|
function getDurationMs(duration) {
|
||||||
|
switch (duration) {
|
||||||
|
case 'session': return 0; // sessionStorage
|
||||||
|
case '1hour': return 60 * 60 * 1000;
|
||||||
|
case '1day': return 24 * 60 * 60 * 1000;
|
||||||
|
case '1week': return 7 * 24 * 60 * 60 * 1000;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guarda estado en storage
|
||||||
|
*/
|
||||||
|
function saveState(key, value, duration) {
|
||||||
|
var data = {
|
||||||
|
value: value,
|
||||||
|
expires: duration === 'session' ? 0 : Date.now() + getDurationMs(duration)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (duration === 'session') {
|
||||||
|
sessionStorage.setItem(key, JSON.stringify(data));
|
||||||
|
} else {
|
||||||
|
localStorage.setItem(key, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recupera estado desde storage
|
||||||
|
*/
|
||||||
|
function getState(key, duration) {
|
||||||
|
var storage = duration === 'session' ? sessionStorage : localStorage;
|
||||||
|
var raw = storage.getItem(key);
|
||||||
|
|
||||||
|
if (!raw) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var data = JSON.parse(raw);
|
||||||
|
|
||||||
|
// Verificar expiracion
|
||||||
|
if (data.expires && data.expires < Date.now()) {
|
||||||
|
storage.removeItem(key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.value;
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
// ANCHOR ADS
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
function initAnchorAds() {
|
||||||
|
var config = getConfig('roi-anchor-config');
|
||||||
|
if (!config) return;
|
||||||
|
|
||||||
|
var anchors = document.querySelectorAll('.roi-anchor-ad');
|
||||||
|
if (!anchors.length) return;
|
||||||
|
|
||||||
|
// Restaurar estados guardados
|
||||||
|
anchors.forEach(function(anchor) {
|
||||||
|
var pos = anchor.dataset.position;
|
||||||
|
var stateKey = 'roi_anchor_' + pos + '_state';
|
||||||
|
|
||||||
|
if (config.rememberState) {
|
||||||
|
var savedState = getState(stateKey, config.rememberDuration);
|
||||||
|
|
||||||
|
if (savedState === 'closed') {
|
||||||
|
anchor.classList.add('hidden');
|
||||||
|
} else if (savedState === 'collapsed' && config.collapsible) {
|
||||||
|
anchor.classList.add('collapsed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Event delegation para botones
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
var btn = e.target.closest('[data-action]');
|
||||||
|
if (!btn) return;
|
||||||
|
|
||||||
|
var action = btn.dataset.action;
|
||||||
|
var anchor = btn.closest('.roi-anchor-ad');
|
||||||
|
|
||||||
|
if (!anchor) return;
|
||||||
|
|
||||||
|
var pos = anchor.dataset.position;
|
||||||
|
var stateKey = 'roi_anchor_' + pos + '_state';
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'close':
|
||||||
|
anchor.classList.add('hidden');
|
||||||
|
if (config.rememberState) {
|
||||||
|
saveState(stateKey, 'closed', config.rememberDuration);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'collapse':
|
||||||
|
if (config.collapsible) {
|
||||||
|
anchor.classList.add('collapsed');
|
||||||
|
if (config.rememberState) {
|
||||||
|
saveState(stateKey, 'collapsed', config.rememberDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'expand':
|
||||||
|
anchor.classList.remove('collapsed');
|
||||||
|
if (config.rememberState) {
|
||||||
|
saveState(stateKey, 'expanded', config.rememberDuration);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
// VIGNETTE ADS
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
function initVignetteAds() {
|
||||||
|
var config = getConfig('roi-vignette-config');
|
||||||
|
if (!config) return;
|
||||||
|
|
||||||
|
var overlay = document.getElementById('roi-vignette-overlay');
|
||||||
|
if (!overlay) return;
|
||||||
|
|
||||||
|
var STORAGE_KEYS = {
|
||||||
|
lastClosed: 'roi_vignette_last_closed',
|
||||||
|
sessionCount: 'roi_vignette_session_count',
|
||||||
|
pageCount: 'roi_vignette_page_count_' + window.location.pathname
|
||||||
|
};
|
||||||
|
|
||||||
|
// Estado local
|
||||||
|
var pageShowCount = 0;
|
||||||
|
var triggered = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifica si se puede mostrar el vignette
|
||||||
|
*/
|
||||||
|
function canShow() {
|
||||||
|
// Verificar max por pagina
|
||||||
|
var maxPage = config.maxPerPage === 'unlimited' ? 999 : parseInt(config.maxPerPage);
|
||||||
|
if (pageShowCount >= maxPage) return false;
|
||||||
|
|
||||||
|
// Verificar max por sesion
|
||||||
|
var maxSession = config.maxPerSession === 'unlimited' ? 999 : parseInt(config.maxPerSession);
|
||||||
|
var sessionCount = parseInt(sessionStorage.getItem(STORAGE_KEYS.sessionCount) || '0');
|
||||||
|
if (sessionCount >= maxSession) return false;
|
||||||
|
|
||||||
|
// Verificar tiempo de reaparicion
|
||||||
|
if (config.reshowEnabled) {
|
||||||
|
var lastClosed = parseInt(localStorage.getItem(STORAGE_KEYS.lastClosed) || '0');
|
||||||
|
var minWait = config.reshowTime * 60 * 1000; // minutos a ms
|
||||||
|
|
||||||
|
if (lastClosed && (Date.now() - lastClosed) < minWait) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Si no se permite reaparicion, verificar si ya se cerro
|
||||||
|
if (sessionStorage.getItem(STORAGE_KEYS.lastClosed)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Muestra el vignette
|
||||||
|
*/
|
||||||
|
function showVignette() {
|
||||||
|
if (!canShow() || triggered) return;
|
||||||
|
|
||||||
|
triggered = true;
|
||||||
|
|
||||||
|
// Mostrar overlay
|
||||||
|
overlay.classList.add('active');
|
||||||
|
document.body.style.overflow = 'hidden';
|
||||||
|
|
||||||
|
// Incrementar contadores
|
||||||
|
pageShowCount++;
|
||||||
|
var sessionCount = parseInt(sessionStorage.getItem(STORAGE_KEYS.sessionCount) || '0');
|
||||||
|
sessionStorage.setItem(STORAGE_KEYS.sessionCount, (sessionCount + 1).toString());
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cierra el vignette
|
||||||
|
*/
|
||||||
|
function closeVignette() {
|
||||||
|
overlay.classList.remove('active');
|
||||||
|
document.body.style.overflow = '';
|
||||||
|
|
||||||
|
// Guardar tiempo de cierre
|
||||||
|
localStorage.setItem(STORAGE_KEYS.lastClosed, Date.now().toString());
|
||||||
|
|
||||||
|
if (!config.reshowEnabled) {
|
||||||
|
sessionStorage.setItem(STORAGE_KEYS.lastClosed, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permitir nueva trigger si se permite reaparicion
|
||||||
|
if (config.reshowEnabled) {
|
||||||
|
triggered = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listeners para cerrar
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
var btn = e.target.closest('[data-action="close-vignette"]');
|
||||||
|
if (btn) {
|
||||||
|
closeVignette();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click fuera del modal
|
||||||
|
if (e.target === overlay) {
|
||||||
|
closeVignette();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Escape key
|
||||||
|
document.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Escape' && overlay.classList.contains('active')) {
|
||||||
|
closeVignette();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// === TRIGGERS ===
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger: Al cargar pagina
|
||||||
|
*/
|
||||||
|
function setupPageviewTrigger() {
|
||||||
|
setTimeout(function() {
|
||||||
|
showVignette();
|
||||||
|
}, config.triggerDelay * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger: Al scrollear X%
|
||||||
|
*/
|
||||||
|
function setupScrollTrigger(percent) {
|
||||||
|
var scrollHandler = function() {
|
||||||
|
if (triggered) return;
|
||||||
|
|
||||||
|
var scrollHeight = document.documentElement.scrollHeight - window.innerHeight;
|
||||||
|
var scrolled = window.scrollY / scrollHeight;
|
||||||
|
|
||||||
|
if (scrolled >= percent / 100) {
|
||||||
|
showVignette();
|
||||||
|
window.removeEventListener('scroll', scrollHandler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('scroll', scrollHandler, { passive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger: Exit intent (mouse sale del viewport)
|
||||||
|
*/
|
||||||
|
function setupExitIntentTrigger() {
|
||||||
|
var exitHandler = function(e) {
|
||||||
|
if (triggered) return;
|
||||||
|
|
||||||
|
// Solo activar si el mouse sale por arriba
|
||||||
|
if (e.clientY <= 0) {
|
||||||
|
showVignette();
|
||||||
|
document.removeEventListener('mouseout', exitHandler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('mouseout', exitHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger: Despues de X segundos
|
||||||
|
*/
|
||||||
|
function setupTimeDelayTrigger() {
|
||||||
|
setTimeout(function() {
|
||||||
|
showVignette();
|
||||||
|
}, config.triggerDelay * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configurar trigger segun config
|
||||||
|
switch (config.trigger) {
|
||||||
|
case 'pageview':
|
||||||
|
setupPageviewTrigger();
|
||||||
|
break;
|
||||||
|
case 'scroll_50':
|
||||||
|
setupScrollTrigger(50);
|
||||||
|
break;
|
||||||
|
case 'scroll_75':
|
||||||
|
setupScrollTrigger(75);
|
||||||
|
break;
|
||||||
|
case 'exit_intent':
|
||||||
|
setupExitIntentTrigger();
|
||||||
|
break;
|
||||||
|
case 'time_delay':
|
||||||
|
setupTimeDelayTrigger();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =====================================================
|
||||||
|
// INICIALIZACION
|
||||||
|
// =====================================================
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
initAnchorAds();
|
||||||
|
initVignetteAds();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ejecutar cuando el DOM este listo
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', init);
|
||||||
|
} else {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"component_name": "adsense-placement",
|
"component_name": "adsense-placement",
|
||||||
"version": "1.2.0",
|
"version": "1.3.0",
|
||||||
"description": "Control de AdSense y Google Analytics - Panel reorganizado",
|
"description": "Control de AdSense y Google Analytics - Con Anchor y Vignette Ads",
|
||||||
"groups": {
|
"groups": {
|
||||||
"visibility": {
|
"visibility": {
|
||||||
"label": "Activacion",
|
"label": "Activacion",
|
||||||
@@ -261,6 +261,182 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"anchor_ads": {
|
||||||
|
"label": "Anuncios Fijos (Anchor)",
|
||||||
|
"priority": 71,
|
||||||
|
"fields": {
|
||||||
|
"anchor_enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Activar Anchor Ads",
|
||||||
|
"default": false,
|
||||||
|
"editable": true,
|
||||||
|
"description": "Anuncios fijos en el borde de la pantalla"
|
||||||
|
},
|
||||||
|
"anchor_position": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Posicion del anuncio fijo",
|
||||||
|
"default": "bottom",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["top", "bottom", "both"],
|
||||||
|
"description": "Solo superior, solo inferior, o ambos"
|
||||||
|
},
|
||||||
|
"anchor_height": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Altura del anchor",
|
||||||
|
"default": "90",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["50", "90", "100", "120"],
|
||||||
|
"description": "Altura en pixeles"
|
||||||
|
},
|
||||||
|
"anchor_show_on_mobile": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Mostrar en movil",
|
||||||
|
"default": true,
|
||||||
|
"editable": true,
|
||||||
|
"description": "Pantallas menores a 1000px"
|
||||||
|
},
|
||||||
|
"anchor_show_on_wide_screens": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Permitir en pantallas anchas (>1000px)",
|
||||||
|
"default": false,
|
||||||
|
"editable": true,
|
||||||
|
"description": "Como las de computadora"
|
||||||
|
},
|
||||||
|
"anchor_collapsible_enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Permitir anchors contraibles",
|
||||||
|
"default": true,
|
||||||
|
"editable": true,
|
||||||
|
"description": "Usuario puede minimizar en lugar de cerrar"
|
||||||
|
},
|
||||||
|
"anchor_collapsed_height": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Altura contraido",
|
||||||
|
"default": "24",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["20", "24", "28", "32"],
|
||||||
|
"description": "Altura cuando esta minimizado"
|
||||||
|
},
|
||||||
|
"anchor_collapse_button_text": {
|
||||||
|
"type": "text",
|
||||||
|
"label": "Texto boton expandir",
|
||||||
|
"default": "Ver anuncio",
|
||||||
|
"editable": true
|
||||||
|
},
|
||||||
|
"anchor_close_position": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Posicion boton cerrar",
|
||||||
|
"default": "right",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["left", "right", "center"]
|
||||||
|
},
|
||||||
|
"anchor_remember_state": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Recordar cierre/colapso",
|
||||||
|
"default": true,
|
||||||
|
"editable": true,
|
||||||
|
"description": "Usa localStorage para recordar estado"
|
||||||
|
},
|
||||||
|
"anchor_remember_duration": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Duracion del recuerdo",
|
||||||
|
"default": "session",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["session", "1hour", "1day", "1week"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vignette_ads": {
|
||||||
|
"label": "Anuncios de Vineta (Pantalla Completa)",
|
||||||
|
"priority": 72,
|
||||||
|
"fields": {
|
||||||
|
"vignette_enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Activar Vignette Ads",
|
||||||
|
"default": false,
|
||||||
|
"editable": true,
|
||||||
|
"description": "Anuncios pantalla completa entre cargas de pagina"
|
||||||
|
},
|
||||||
|
"vignette_trigger": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Cuando mostrar",
|
||||||
|
"default": "pageview",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["pageview", "scroll_50", "scroll_75", "exit_intent", "time_delay"],
|
||||||
|
"description": "Disparador del vignette"
|
||||||
|
},
|
||||||
|
"vignette_trigger_delay": {
|
||||||
|
"type": "text",
|
||||||
|
"label": "Delay inicial (segundos)",
|
||||||
|
"default": "5",
|
||||||
|
"editable": true,
|
||||||
|
"description": "Segundos antes de mostrar"
|
||||||
|
},
|
||||||
|
"vignette_show_on_mobile": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Mostrar en movil",
|
||||||
|
"default": true,
|
||||||
|
"editable": true
|
||||||
|
},
|
||||||
|
"vignette_show_on_desktop": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Mostrar en desktop",
|
||||||
|
"default": true,
|
||||||
|
"editable": true
|
||||||
|
},
|
||||||
|
"vignette_size": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Tamano del anuncio",
|
||||||
|
"default": "300x250",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["300x250", "336x280", "responsive"]
|
||||||
|
},
|
||||||
|
"vignette_overlay_opacity": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Opacidad del fondo",
|
||||||
|
"default": "0.7",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["0.5", "0.6", "0.7", "0.8", "0.9"]
|
||||||
|
},
|
||||||
|
"vignette_close_button_delay": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Delay boton cerrar (segundos)",
|
||||||
|
"default": "0",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["0", "1", "2", "3", "5"],
|
||||||
|
"description": "Segundos antes de mostrar el boton X"
|
||||||
|
},
|
||||||
|
"vignette_reshow_enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"label": "Permitir reaparicion",
|
||||||
|
"default": true,
|
||||||
|
"editable": true,
|
||||||
|
"description": "Puede volver a aparecer despues de cerrarlo"
|
||||||
|
},
|
||||||
|
"vignette_reshow_time": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Tiempo para reaparecer (minutos)",
|
||||||
|
"default": "5",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["1", "2", "3", "4", "5", "10", "15", "30"],
|
||||||
|
"description": "Minutos antes de poder volver a mostrar"
|
||||||
|
},
|
||||||
|
"vignette_max_per_session": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Maximo por sesion",
|
||||||
|
"default": "3",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["1", "2", "3", "5", "unlimited"]
|
||||||
|
},
|
||||||
|
"vignette_max_per_page": {
|
||||||
|
"type": "select",
|
||||||
|
"label": "Maximo por pagina",
|
||||||
|
"default": "1",
|
||||||
|
"editable": true,
|
||||||
|
"options": ["1", "2", "unlimited"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"layout": {
|
"layout": {
|
||||||
"label": "Ubicaciones Archivos/Globales",
|
"label": "Ubicaciones Archivos/Globales",
|
||||||
"priority": 80,
|
"priority": 80,
|
||||||
|
|||||||
Reference in New Issue
Block a user