# Especificacion: AdSense Auto Ads Toggle ## Purpose Define el comportamiento de un interruptor "Auto Ads" que cuando se activa, delega el control de ubicacion de anuncios a Google AdSense Auto Ads, desactivando automaticamente todas las ubicaciones manuales del tema EXCEPTO los anuncios en resultados de busqueda del plugin ROI APU Search. **Problema que resuelve:** El usuario necesita probar Google Auto Ads sin tener que deshabilitar manualmente cada ubicacion de anuncio. Ademas, Auto Ads tiende a romper el layout de tablas HTML, por lo que se requiere excluirlas automaticamente. **Beneficio esperado:** Comparar facilmente el rendimiento (RPM, CTR, revenue) entre ubicaciones manuales vs Auto Ads de Google, manteniendo siempre activos los anuncios en el buscador APU. --- ## Requirements ### Requirement: Campo enable_auto_ads en Schema El schema adsense-placement.json DEBE incluir un nuevo campo para activar Auto Ads. #### Scenario: Definicion del campo en JSON Schema - **WHEN** se define el campo `enable_auto_ads` - **THEN** DEBE ubicarse en el grupo `visibility` con priority 10 - **AND** DEBE tener type `boolean` - **AND** DEBE tener default `false` - **AND** DEBE tener label `Activar Google Auto Ads` - **AND** DEBE tener description `Cuando esta activo, Google controla automaticamente donde mostrar anuncios. Se desactivan las ubicaciones manuales excepto los anuncios en busqueda.` #### Scenario: Posicion del campo en el formulario - **WHEN** se renderiza el formulario de configuracion - **THEN** el campo `enable_auto_ads` DEBE aparecer inmediatamente despues de `is_enabled` - **AND** DEBE tener un indicador visual destacado (badge o icono) indicando que es modo automatico --- ### Requirement: Desactivacion Automatica de Ubicaciones Manuales Cuando Auto Ads esta activo, el sistema DEBE ignorar todas las configuraciones de ubicacion manual. #### Scenario: Grupos afectados por enable_auto_ads - **GIVEN** `enable_auto_ads === true` - **WHEN** se evaluan las ubicaciones de anuncios - **THEN** los siguientes grupos DEBEN comportarse como si estuvieran desactivados: - `incontent_advanced` (In-Content Ads Avanzado) - `behavior` (Ubicaciones en Posts) - EXCEPTO `javascript_first_mode` - `anchor_ads` (Anuncios Fijos) - `vignette_ads` (Anuncios de Vineta) - `layout` (Ubicaciones Archivos/Globales) - **AND** el grupo `search_results` DEBE permanecer activo - **AND** el grupo `analytics` DEBE permanecer activo - **AND** el grupo `content` (credenciales) DEBE permanecer activo #### Scenario: Preservacion de configuracion en base de datos - **GIVEN** el usuario activa `enable_auto_ads` - **WHEN** se guardan los settings - **THEN** los valores de los campos desactivados NO DEBEN modificarse en la BD - **AND** cuando el usuario desactive `enable_auto_ads`, sus configuraciones previas DEBEN estar intactas #### Scenario: Evaluacion en PHP (Server-Side) - **GIVEN** `enable_auto_ads === true` en los settings - **WHEN** un Renderer evalua si debe insertar un slot de anuncio - **THEN** DEBE verificar primero si `enable_auto_ads` esta activo - **AND** si esta activo, DEBE retornar inmediatamente sin insertar el slot manual - **AND** EXCEPTO para slots del grupo `search_results` #### Scenario: Evaluacion en JavaScript (Client-Side) - **GIVEN** JavaScript-First Mode esta activo - **AND** `enable_auto_ads === true` - **WHEN** el controller JavaScript evalua visibilidad - **THEN** DEBE incluir `enable_auto_ads` en el response del endpoint REST - **AND** el script DEBE ocultar slots manuales marcados con `data-ad-manual` - **AND** NO DEBE ocultar slots marcados con `data-ad-search` --- ### Requirement: Excepcion para ROI APU Search Los anuncios en resultados de busqueda DEBEN permanecer activos independientemente del estado de Auto Ads. #### Scenario: Configuracion de busqueda siempre disponible - **GIVEN** `enable_auto_ads === true` - **WHEN** se obtiene la configuracion para el plugin roi-apu-search via `roi_get_adsense_search_config()` - **THEN** DEBE retornar la configuracion del grupo `search_results` - **AND** `search_ads_enabled` DEBE evaluarse independientemente de `enable_auto_ads` #### Scenario: Slots de busqueda con atributo especial - **WHEN** se renderizan slots de anuncios para resultados de busqueda - **THEN** DEBEN incluir atributo `data-ad-search="true"` - **AND** DEBEN incluir clase CSS `roi-ad-search-slot` - **AND** NO DEBEN incluir atributo `data-ad-manual` #### Scenario: JavaScript no oculta slots de busqueda - **GIVEN** el controller JavaScript detecta `enable_auto_ads === true` - **WHEN** procesa los slots de anuncios - **THEN** NO DEBE agregar clase `roi-ad-hidden` a elementos con `data-ad-search` - **AND** DEBE disparar evento `roi-adsense-activate` para slots de busqueda --- ### Requirement: CSS para Excluir Tablas de Auto Ads El sistema DEBE inyectar CSS que indica a Google Auto Ads que NO inserte anuncios dentro de tablas. #### Scenario: Inyeccion de CSS google-auto-ads ignore - **GIVEN** `enable_auto_ads === true` - **WHEN** se renderiza el header del sitio - **THEN** DEBE inyectar el siguiente CSS: ```css table, .wp-block-table, .tablepress, figure.wp-block-table, .entry-content table { google-auto-ads: ignore; } ``` - **AND** el CSS DEBE cargarse ANTES del script de AdSense #### Scenario: CSS solo cuando Auto Ads esta activo - **GIVEN** `enable_auto_ads === false` - **WHEN** se renderiza el header - **THEN** NO DEBE inyectar el CSS de `google-auto-ads: ignore` #### Scenario: Selectores adicionales configurables - **GIVEN** el usuario necesita excluir elementos adicionales - **WHEN** existe un campo `auto_ads_exclude_selectors` en el schema - **THEN** DEBE agregar esos selectores al CSS de exclusion - **AND** el campo DEBE ser de tipo `textarea` - **AND** DEBE tener default vacio --- ### Requirement: Script de Google Auto Ads Cuando Auto Ads esta activo, el sistema DEBE insertar el script requerido por Google. #### Scenario: Insercion del script adsbygoogle - **GIVEN** `enable_auto_ads === true` - **AND** `is_enabled === true` - **WHEN** se renderiza el head del documento - **THEN** DEBE insertar el script de AdSense: ```html ``` - **AND** DEBE usar el `publisher_id` configurado en el grupo `content` #### Scenario: No duplicar scripts - **GIVEN** el tema ya encola el script de AdSense para ubicaciones manuales - **WHEN** `enable_auto_ads === true` - **THEN** NO DEBE duplicar el script - **AND** DEBE reutilizar el script existente #### Scenario: Delay de carga respetado - **GIVEN** `delay_enabled === true` en el grupo `forms` - **AND** `enable_auto_ads === true` - **WHEN** se carga la pagina - **THEN** el script de AdSense DEBE cargarse con delay - **AND** DEBE respetar el valor de `delay_timeout` --- ### Requirement: Indicador Visual en Admin UI El panel de administracion DEBE mostrar claramente cuando Auto Ads esta activo. #### Scenario: Badge de estado Auto Ads - **GIVEN** el usuario accede al panel de configuracion de AdSense - **WHEN** `enable_auto_ads === true` - **THEN** DEBE mostrar un badge visible "AUTO ADS ACTIVO" en color naranja (#FF8600) - **AND** los grupos desactivados DEBEN aparecer con opacidad reducida (0.5) - **AND** los grupos desactivados DEBEN mostrar tooltip "Desactivado por Auto Ads" #### Scenario: Seccion de grupos no afectados - **GIVEN** `enable_auto_ads === true` - **WHEN** se renderiza el formulario - **THEN** los grupos `search_results`, `analytics`, y `content` DEBEN renderizarse normalmente - **AND** DEBEN tener indicador "Siempre activo" visible #### Scenario: Confirmacion al activar - **GIVEN** el usuario hace click en `enable_auto_ads` - **WHEN** el campo cambia de false a true - **THEN** DEBE mostrar dialogo de confirmacion con mensaje: "Al activar Auto Ads, Google controlara automaticamente donde mostrar anuncios. Tus configuraciones manuales se mantendran guardadas pero no se usaran. Los anuncios en resultados de busqueda seguiran funcionando. Continuar?" - **AND** DEBE tener botones "Activar Auto Ads" y "Cancelar" --- ### Requirement: Separacion de Capas segun Clean Architecture La implementacion DEBE seguir Clean Architecture. #### Scenario: Value Object AutoAdsConfiguration en Domain - **WHEN** se crea el Value Object AutoAdsConfiguration - **THEN** DEBE ubicarse en `Shared/Domain/ValueObjects/` - **AND** DEBE ser inmutable despues de construccion - **AND** DEBE exponer `isAutoAdsEnabled()`, `getExcludedSelectors()`, `getPublisherId()` - **AND** NO DEBE contener logica de WordPress #### Scenario: Interface en Domain - **WHEN** se define el contrato para verificar si un grupo esta activo - **THEN** DEBE existir metodo en `AdsenseSettingsInterface`: `isGroupActiveWithAutoAds(string $groupName): bool` - **AND** DEBE retornar false para grupos manuales cuando Auto Ads esta activo - **AND** DEBE retornar true para `search_results`, `analytics`, `content` #### Scenario: Service en Infrastructure - **WHEN** se implementa la logica de evaluacion - **THEN** el `AdsenseSettingsService` DEBE verificar `enable_auto_ads` antes de evaluar ubicaciones - **AND** DEBE exponer metodo `getActiveGroups(): array` que retorna solo grupos activos --- ### Requirement: Endpoint REST para Estado de Auto Ads El endpoint de visibilidad DEBE informar el estado de Auto Ads. #### Scenario: Inclusion en response de visibility - **GIVEN** el endpoint `/wp-json/roi-theme/v1/adsense-placement/visibility` - **WHEN** responde exitosamente - **THEN** DEBE incluir campo `auto_ads_enabled: boolean` - **AND** DEBE incluir campo `auto_ads_exclude_selectors: string` #### Scenario: Response cuando Auto Ads esta activo - **GIVEN** `enable_auto_ads === true` - **WHEN** se llama al endpoint - **THEN** el response DEBE incluir: ```json { "show_ads": true, "auto_ads_enabled": true, "auto_ads_exclude_selectors": "table,.wp-block-table", "manual_slots_disabled": true, "search_slots_enabled": true, "reasons": [], "cache_seconds": 300, "timestamp": 1733900000 } ``` --- ### Requirement: Migracion y Retrocompatibilidad La implementacion DEBE mantener compatibilidad con instalaciones existentes. #### Scenario: Valor default para instalaciones existentes - **GIVEN** una instalacion existente sin el campo `enable_auto_ads` - **WHEN** se ejecuta sync-component - **THEN** DEBE crear el campo con valor `false` - **AND** el comportamiento existente NO DEBE cambiar #### Scenario: Sin cambios en logica si Auto Ads esta desactivado - **GIVEN** `enable_auto_ads === false` - **WHEN** se evaluan ubicaciones de anuncios - **THEN** el comportamiento DEBE ser identico al actual - **AND** NO DEBE haber impacto en rendimiento --- ### Requirement: Logging y Diagnostico El sistema DEBE proveer informacion de diagnostico para troubleshooting. #### Scenario: Log cuando Auto Ads ignora ubicacion - **GIVEN** `enable_auto_ads === true` - **AND** WP_DEBUG === true - **WHEN** un Renderer es llamado para ubicacion manual - **THEN** DEBE loguear mensaje: "AdSense: Skipping manual slot '{slot_name}' - Auto Ads active" - **AND** el log DEBE ser level DEBUG #### Scenario: Comentario HTML de diagnostico - **GIVEN** `enable_auto_ads === true` - **AND** WP_DEBUG === true - **WHEN** se renderiza el header - **THEN** DEBE incluir comentario HTML: ```html ``` --- ## Implementation Notes ### Schema Changes (adsense-placement.json) Agregar al grupo `visibility`: ```json "enable_auto_ads": { "type": "boolean", "label": "Activar Google Auto Ads", "default": false, "editable": true, "description": "Google controla automaticamente la ubicacion de anuncios. Se desactivan ubicaciones manuales excepto busqueda." } ``` Agregar al grupo `forms` (nuevo campo): ```json "auto_ads_exclude_selectors": { "type": "textarea", "label": "Selectores adicionales a excluir de Auto Ads", "default": "", "editable": true, "description": "Selectores CSS adicionales donde Auto Ads no debe insertar anuncios (uno por linea)" } ``` ### CSS Default Exclusions ```css /* Elementos que Google Auto Ads debe ignorar */ table, .wp-block-table, .tablepress, figure.wp-block-table, .entry-content table, .roi-apu-results, .roi-apu-result-item, pre, code, .wp-block-code, .syntax-highlighted { google-auto-ads: ignore; } ``` ### Grupos y su comportamiento con Auto Ads | Grupo | Con Auto Ads OFF | Con Auto Ads ON | |-------|------------------|-----------------| | visibility | Activo | Activo (controla is_enabled global) | | analytics | Activo | Activo | | content | Activo | Activo (provee publisher_id) | | incontent_advanced | Activo | IGNORADO | | behavior | Activo | IGNORADO (excepto javascript_first_mode) | | anchor_ads | Activo | IGNORADO | | vignette_ads | Activo | IGNORADO | | search_results | Activo | ACTIVO (excepcion) | | layout | Activo | IGNORADO | | forms | Activo | Activo (delay, exclusiones) | --- ## Validation Checklist Antes de considerar esta especificacion implementada: - [ ] Campo `enable_auto_ads` existe en schema y BD - [ ] Campo `auto_ads_exclude_selectors` existe en schema y BD - [ ] CSS de exclusion se inyecta solo cuando Auto Ads activo - [ ] Slots manuales no se renderizan cuando Auto Ads activo - [ ] Slots de busqueda SI se renderizan cuando Auto Ads activo - [ ] `roi_get_adsense_search_config()` funciona independiente de Auto Ads - [ ] Admin UI muestra indicador visual de Auto Ads activo - [ ] Grupos desactivados aparecen con opacidad reducida - [ ] Endpoint REST incluye `auto_ads_enabled` en response - [ ] JavaScript oculta slots manuales pero no de busqueda - [ ] Script de AdSense se carga correctamente - [ ] No hay duplicacion de scripts - [ ] Logs de debug funcionan cuando WP_DEBUG activo - [ ] Sync-component migra correctamente instalaciones existentes