Files
roi-theme/openspec/changes/refactor-adsense-lazy-loading/proposal.md
FrankZamora 179a83e9cd feat(js): implement intersection observer lazy loading for adsense
- Add per-slot lazy loading with Intersection Observer API
- Implement fill detection via MutationObserver and data-ad-status
- Add configurable rootMargin and fillTimeout from database
- Generate dynamic CSS based on lazy_loading_enabled setting
- Add legacy mode fallback for browsers without IO support
- Include backup of previous implementation (adsense-loader.legacy.js)
- Add OpenSpec documentation with test plan (72 tests verified)

Schema changes:
- Add lazy_loading_enabled (boolean, default: true)
- Add lazy_rootmargin (select: 0-500px, default: 200)
- Add lazy_fill_timeout (select: 3000-10000ms, default: 5000)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 15:48:20 -06:00

2.6 KiB

Change: Refactorizar AdSense Lazy Loading con Intersection Observer

Why

La implementacion actual carga TODOS los ads simultaneamente despues de interaccion del usuario o timeout de 5 segundos. Esto causa:

  1. Slots vacios visibles: Cuando hay mas ads que inventario disponible, los slots vacios quedan visibles en la pagina creando espacios en blanco.
  2. Sobrecarga inicial: Cargar 20+ ads simultaneamente impacta el rendimiento y el fill rate de Google.
  3. Desperdicio de impresiones: Ads below-the-fold se cargan aunque el usuario nunca llegue a verlos.

What Changes

  • BREAKING: El comportamiento de carga cambia de "cargar todo" a "cargar por visibilidad"
  • Nuevos campos de configuracion en schema adsense-placement.json (grupo forms)
  • Extension del modulo AdsensePlacement existente (NO modulo nuevo)
  • Implementar Intersection Observer para detectar cuando un slot entra al viewport
  • Cargar cada ad individualmente cuando el usuario se aproxima (rootMargin configurable)
  • NO mostrar el contenedor .roi-ad-slot hasta que el ad tenga contenido real
  • Estilos generados via CSSGeneratorService (NO CSS estatico)

Impact

  • Affected specs: Extension de especificacion existente adsense-placement
  • Affected code:
    • Schemas/adsense-placement.json - Nuevos campos en grupo forms
    • Assets/Js/adsense-loader.js - Refactorizacion con Intersection Observer
    • Public/AdsensePlacement/Infrastructure/Ui/AdsensePlacementRenderer.php - Ajustar markup y estilos
    • Public/AdsensePlacement/Infrastructure/Services/AdsenseAssetEnqueuer.php - Pasar config a JS
    • Admin/AdsensePlacement/Infrastructure/Ui/AdsensePlacementFormBuilder.php - Nuevos campos UI
    • Admin/AdsensePlacement/Infrastructure/FieldMapping/AdsensePlacementFieldMapper.php - Mapping

Arquitectura

Esta mejora se integra al modulo existente AdsensePlacement:

Public/AdsensePlacement/
├── Domain/                    # Sin cambios (no hay logica de negocio nueva)
├── Application/               # Sin cambios
└── Infrastructure/
    ├── Ui/
    │   └── AdsensePlacementRenderer.php  # Genera CSS dinamico via CSSGenerator
    └── Services/
        └── AdsenseAssetEnqueuer.php      # Enqueue JS con config desde BD

Admin/AdsensePlacement/
├── Infrastructure/
│   ├── Ui/
│   │   └── AdsensePlacementFormBuilder.php  # Nuevos campos lazy loading
│   └── FieldMapping/
│       └── AdsensePlacementFieldMapper.php  # Mapping nuevos campos

NO se crea modulo nuevo - es extension del componente existente.