# Tasks: Refactorizar AdSense Lazy Loading > **Nota:** Las tareas siguen el flujo de 5 fases del proyecto. Pasos adicionales (FieldMapper, Asset Enqueuer, JS) son subtareas de infraestructura. --- ## FASE 1: Schema JSON ### 1.1 Actualizar adsense-placement.json - [x] Incrementar version de `1.4.0` a `1.5.0` - [x] Agregar campo `lazy_loading_enabled` al grupo `behavior`: ```json "lazy_loading_enabled": { "type": "boolean", "label": "Lazy Loading de Anuncios", "default": true, "editable": true, "description": "Cargar anuncios individualmente al entrar al viewport (mejora fill rate)" } ``` - [x] Agregar campo `lazy_rootmargin` al grupo `behavior` (tipo select, default "200") - [x] Agregar campo `lazy_fill_timeout` al grupo `behavior` (tipo select, default "5000") ### 1.2 Sincronizar a BD - [x] Ejecutar `wp roi-theme sync-component adsense-placement` - [x] Verificar campos creados en BD con valores default --- ## FASE 2: Renderer (BD → HTML + CSS) ### 2.1 Actualizar AdsensePlacementRenderer.php - [x] Leer `lazy_loading_enabled` desde settings - [x] Generar CSS dinamico via `CSSGeneratorService`: ```php if ($settings['lazy_loading_enabled']) { $this->cssGenerator->generate([ '.roi-ad-slot' => ['display' => 'none'], '.roi-ad-slot.roi-ad-filled' => ['display' => 'block'], '.roi-ad-slot.roi-ad-empty' => ['display' => 'none'], ]); } ``` - [x] Agregar `data-ad-lazy="true"` al markup del slot si lazy enabled - [x] Mantener compatibilidad con `lazy_loading_enabled: false` ### 2.2 Actualizar enqueue-scripts.php (AssetEnqueuer) - [x] Leer settings de lazy loading desde BD - [x] Usar `wp_localize_script()` para pasar config a JS: ```php wp_localize_script('adsense-loader', 'roiAdsenseConfig', [ 'lazyEnabled' => (bool) $settings['lazy_loading_enabled'], 'rootMargin' => (int) $settings['lazy_rootmargin'] . 'px 0px', 'fillTimeout' => (int) $settings['lazy_fill_timeout'], 'debug' => WP_DEBUG, ]); ``` - [x] Remover cualquier configuracion hardcodeada existente ### 2.3 Actualizar AdsensePlacementFieldMapper.php - [x] Agregar `lazy_loading_enabled` al array de mappings - [x] Agregar `lazy_rootmargin` al array de mappings - [x] Agregar `lazy_fill_timeout` al array de mappings - [x] Verificar tipos correctos (boolean, string, string → parseados en Enqueuer) --- ## FASE 3: FormBuilder (UI Admin) ### 3.1 Actualizar AdsensePlacementFormBuilder.php - [x] Agregar seccion "Lazy Loading" dentro del grupo Exclusions/Forms - [x] Agregar toggle para `lazy_loading_enabled` - [x] Agregar select para `lazy_rootmargin` (label: "Pre-carga (px)") - [x] Agregar select para `lazy_fill_timeout` (label: "Timeout fill (ms)") - [x] Agregar nota indicando que cambios requieren vaciar cache --- ## FASE 4: JavaScript (Infrastructure) ### 4.1 Backup - [x] Crear backup `adsense-loader.legacy.js` ### 4.2 Refactorizar adsense-loader.js - [x] Refactorizar para leer config de `window.roiAdsenseConfig` - [x] Implementar deteccion de soporte Intersection Observer - [x] Implementar `observeAdSlots()` con Intersection Observer - [x] Implementar `activateAdSlot(slot)` para activacion individual - [x] Implementar MutationObserver para detectar contenido en `` - [x] Implementar `checkAdFill()` con criterios concretos: - Verificar `data-ad-status` primero - Fallback a verificar children (iframe, div[id]) - [x] Implementar timeout por slot para marcar como vacio - [x] Implementar manejo de error de red con retry (2s delay, max 1 retry) - [x] Implementar fallback para navegadores sin soporte - [x] Mantener carga diferida de `adsbygoogle.js` (primera activacion) - [x] Mantener compatibilidad con `lazyEnabled: false` (modo legacy) --- ## FASE 5: Validacion ### 5.1 Validacion de Arquitectura - [x] Ejecutar `php Shared/Infrastructure/Scripts/validate-architecture.php adsense-placement` - [x] Verificar que no hay CSS estatico nuevo - [x] Verificar que config viene de BD, no hardcodeada - [x] Verificar que FieldMapper tiene todos los campos ### 5.2 Testing Local - [ ] Probar con lazy_loading_enabled: true - [ ] Verificar ads cargan al scroll (DevTools Network) - [ ] Verificar slots vacios NO se muestran - [ ] Probar con lazy_loading_enabled: false (modo legacy) - [ ] Verificar fallback en navegador sin Intersection Observer - [ ] Medir Core Web Vitals con Lighthouse (antes/despues) --- ## POST-IMPLEMENTACION ### Deploy - [ ] Commit con mensaje descriptivo - [ ] Deploy a produccion - [ ] Ejecutar sync-component en produccion - [ ] Vaciar cache (Redis, W3TC) - [ ] Verificar funcionamiento en produccion ### Monitoreo (24-48h) - [ ] Monitorear fill rate en AdSense dashboard - [ ] Verificar no hay errores en consola de usuarios - [ ] Comparar Core Web Vitals antes/despues ### Cleanup - [ ] Remover `debug: true` de adsense-loader.js (ya pendiente) - [ ] Remover debug de ContentAdInjector.php (ya pendiente) - [ ] Remover `adsense-loader.legacy.js` si todo funciona (7+ dias) - [ ] Archivar esta especificacion en `openspec/archive/`