Commit Graph

40 Commits

Author SHA1 Message Date
FrankZamora
3c8e5982ba fix: Update all paths to PascalCase (Css, Js, Fonts)
- Update enqueue-scripts.php: /Assets/css/ → /Assets/Css/, /Assets/js/ → /Assets/Js/
- Update related-posts.php, performance.php, minify-css.php, CSSConflictValidator.php
- Fix 404 errors for CSS/JS/Fonts on production

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 12:06:28 -06:00
FrankZamora
7667b7f02a refactor: Rename fonts to Fonts (PascalCase consistency)
- Rename Assets/fonts/ to Assets/Fonts/
- Update all references in PHP and CSS files
- Consistent with Css, Js, Vendor naming

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 11:40:45 -06:00
FrankZamora
c4dcdad14b fix(cls): load css-tablas-apu.css async to prevent render blocking
- Add complete APU table column widths to critical-bootstrap.css
- Load css-tablas-apu.css with media="print" + onload for async loading
- Critical styles (column widths, row backgrounds) now inline in <head>
- Full CSS loads non-blocking after initial render

Fixes PageSpeed "Render-blocking CSS" warning (120ms savings)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 11:28:53 -06:00
FrankZamora
d648e7ff4c fix(CLS): move APU table row classes from JS to PHP server-side
PROBLEM:
- apu-tables-auto-class.js was adding CSS classes to table rows after DOMContentLoaded
- This DOM manipulation caused CLS of 0.692 in Lab Data (PageSpeed Insights)
- body.wp-singular was the main culprit with 0.692 CLS contribution

SOLUTION:
- Added roi_add_apu_row_classes() function in Inc/apu-tables.php
- This applies the same logic server-side during the_content filter
- Classes (section-header, subtotal-row, total-row) are now in HTML from first render
- Disabled the JS script in Inc/enqueue-scripts.php

This should significantly reduce Lab Data CLS (target: < 0.1)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 11:12:34 -06:00
FrankZamora
842f529816 fix(cls): APU tables layout + hero badges min-height
- APU tables: Change media='print' to 'all' for immediate CSS loading
- APU tables: Add table-layout: fixed to prevent column reflow
- Hero: Add min-height: 40px to badge container to reserve space

These changes prevent CLS caused by:
1. Delayed APU table CSS causing table layout shift
2. Hero category badges appearing after page load

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 11:03:23 -06:00
FrankZamora
c7e8f14d83 perf: Optimización PageSpeed - Score 81→97
Cambios implementados:

1. CSS Crítico (critical-bootstrap.css):
   - Agregar clases responsive d-lg-none, d-lg-block, d-lg-flex
   - Prevenir CLS en TopNotificationBar al ocultar en móvil
   - Agregar estilos para tablas y main content (CLS fix)

2. Google Analytics Diferido (adsense-placement.php):
   - GA4 ahora carga después de 3s o primera interacción
   - Reduce ~59 KiB de JavaScript bloqueante
   - TBT mejorado significativamente

3. CSS Minificado (enqueue-scripts.php):
   - Usar style.min.css y css-global-accessibility.min.css
   - Ahorro ~6 KiB en transferencia

4. Nuevo script minify-css.php para generar versiones .min.css

Resultados PageSpeed Mobile:
- Performance: 81 → 97 (+16 puntos)
- FCP: 2.8s → 1.0s (-64%)
- LCP: 3.5s → 1.3s (-63%)
- Core Web Vitals: SUPERADA

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 13:23:20 -06:00
FrankZamora
31d4a41fc9 revert: restore style.css as blocking CSS to fix CLS
- Remove roi-main-style from deferred list
- Restore media='all' for style.css
- CLS was 0.392 when deferred, should return to ~0.06

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 12:26:31 -06:00
FrankZamora
9afdd6ee1d perf: defer style.css - eliminate last render-blocking CSS
- Add site structure, accessibility, typography to critical-bootstrap.css
- Defer roi-main-style (style.css) with media='print'
- Goal: 0 blocking CSS files (was 1 file, 19KB)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 12:19:26 -06:00
FrankZamora
b4071bf598 perf: Defer fonts.css and variables.css, inline critical CSS
- Add @font-face declarations to critical-bootstrap.css inline
- Add critical CSS variables (colors, fonts) inline
- Defer fonts.css (utilities only, @font-face inline)
- Defer variables.css (critical vars inline)

Now only style.css is render-blocking (~19KB)
All other CSS deferred with media=print + onload

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 12:12:57 -06:00
FrankZamora
62a0f17b21 perf: Defer Bootstrap with inline critical CSS for LCP optimization
- Add grid system (row, col-*) to critical-bootstrap.css to prevent CLS
- Add text utilities, sizing, spacing, and alert component to critical CSS
- Enable CriticalBootstrapService to inline critical Bootstrap in <head>
- Defer bootstrap-subset.min.css (21KB) via media=print + onload
- Fix preload pointing to wrong Bootstrap file (was 227KB, now 147KB)

Expected improvement: ~970ms reduction in render-blocking CSS

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 12:05:50 -06:00
FrankZamora
b7ae8cac21 perf(bootstrap): Reduce Bootstrap CSS de 227KB a 145KB con PurgeCSS
- Genera bootstrap-subset.min.css con solo clases usadas (36% reduccion)
- Actualiza enqueue-scripts.php para usar el subset
- Agrega scripts de build: npm run build:bootstrap
- Mejora LCP al reducir tiempo de parseo CSS

Impacto estimado:
- Bootstrap: 227KB -> 145KB (-82KB)
- Tiempo parseo CSS: ~800ms -> ~500ms
- LCP: mejora esperada ~300-500ms

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 11:26:18 -06:00
FrankZamora
6004420620 fix: eliminate forced reflows in TOC ScrollSpy + revert Bootstrap defer
- Replace scroll event listener with Intersection Observer in TableOfContentsRenderer
- Eliminates ~100ms forced reflows from offsetTop reads during scroll
- Revert Bootstrap CSS to blocking (media='all') - deferring caused CLS 0.954
- Keep CriticalBootstrapService available for future optimization
- Simplify CriticalCSSHooksRegistrar to only use CriticalCSSService

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 10:52:25 -06:00
FrankZamora
d5a2fd2702 perf: defer Bootstrap CSS with critical subset inline
- Created Assets/css/critical-bootstrap.css (~10KB subset)
  Contains only Bootstrap classes used in above-the-fold components:
  container, navbar, flexbox, dropdown, spacing utilities

- Created CriticalBootstrapService (singleton)
  Injects minified critical Bootstrap in <head> at priority 0
  Output: <style id="roi-critical-bootstrap">...</style>

- Modified enqueue-scripts.php
  Bootstrap now loads with media="print" + onload="this.media='all'"
  Full 31KB Bootstrap loads async, doesn't block rendering

- Updated CriticalCSSHooksRegistrar
  Now registers both CriticalBootstrapService (priority 0)
  and CriticalCSSService (priority 1)

Flow:
1. wp_head (priority 0) → Critical Bootstrap (~10KB inline)
2. wp_head (priority 1) → Critical Component CSS (~4KB inline)
3. Bootstrap full (31KB) loads deferred, non-blocking

Expected PageSpeed improvement: ~400-600ms LCP reduction

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 10:26:24 -06:00
FrankZamora
b96a13427e 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>
2025-11-28 21:00:00 -06:00
FrankZamora
4d5cc1a58c feat(adsense): agregar opcion para ocultar anuncios a usuarios logueados
- Nuevo campo hide_for_logged_in en schema visibility group
- Switch en panel de administracion con icono bi-person-lock
- Mapeo en FieldMapper para persistencia
- Validacion en roi_render_ad_slot, roi_render_rail_ads,
  roi_enqueue_adsense_script y roi_inject_content_ads
- No carga script ni muestra ads si usuario tiene sesion activa

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 10:31:49 -06:00
FrankZamora
21ac98c969 fix(rail-ads): revertir a anuncio 160px fijo centrado en container responsive 2025-11-27 22:07:04 -06:00
FrankZamora
de4f808a1a debug: add logging to rail ads rendering 2025-11-27 22:03:05 -06:00
FrankZamora
6e2ef67dc4 chore: bump css-global-responsive version to 1.1.0 for cache bust
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:32:30 -06:00
FrankZamora
1a069a1336 fix(adsense): Remove debug code after finding root cause
Root cause: mu-plugin allow-unfiltered-html.php was replacing all
filtered content with raw DB content at PHP_INT_MAX priority.

Solution: Modified mu-plugin on server to call roi_inject_content_ads()
after getting raw content.

NOTE: The mu-plugin change is only on the production server at:
/wp-content/mu-plugins/allow-unfiltered-html.php

The change adds roi_inject_content_ads() call after YouTube Facade filter.
This allows ads to be injected into posts even with the raw content bypass.

Cleaned up:
- Removed debug logging from adsense-placement.php
- Removed template-level debug from single.php
- Removed debug markers

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:19:43 -06:00
FrankZamora
c564ee7a2a debug: Add visible marker to trace content loss 2025-11-27 20:09:47 -06:00
FrankZamora
4119f2e86d fix(adsense): Disable output buffer causing content loss
The output buffer in adsense-delay.php was causing conflicts with
zlib compression buffer, resulting in ads being generated but not
appearing in final HTML.

Root cause: Multiple output buffers (zlib + adsense-delay) were
nested improperly, causing ob_end_flush() failures and content loss.

Solution: Disable the output buffer since AdsensePlacementRenderer
already generates scripts with type="text/plain" data-adsense-push.
The buffer was redundant and only needed for external AdSense sources.

Debug logs confirmed:
- Filter generates ads correctly (598+601 chars)
- Content exists after filter (54765 chars)
- But ads missing in final HTML (0 roi-ad-slot found)
- ob_end_flush() errors in debug.log

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:07:09 -06:00
FrankZamora
e52df682ae fix(adsense): Use adsense-placement settings instead of non-existent adsense-delay component
- Change roi_delay_adsense_scripts() to read from 'adsense-placement' component
- Change roi_add_adsense_init_script() to use same settings source
- Use 'forms.delay_enabled' field path instead of 'visibility.is_enabled'
- Add clarifying comments about output buffer purpose

The 'adsense-delay' component was never created in the database, causing
the delay functions to always use default values. Now properly reads
from the existing 'adsense-placement' component settings.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:00:23 -06:00
FrankZamora
58a4cc2c56 fix: Increase the_content filter priority to 150
Changed AdSense injection filter from priority 100 to 150 to ensure
it runs AFTER restrict-content-pro's rcp_filter_restricted_content
filter which also uses priority 100.

This should fix ads not appearing in post content.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 19:55:13 -06:00
FrankZamora
b9b21c390a debug: Add more logging including post_id and postTopHtml preview
Additional debug info:
- Log post_id and URL to identify which post is being processed
- Log first 200 chars of postTopHtml to verify content
- Log final content length

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 19:50:53 -06:00
FrankZamora
22e9273b4f debug: Add logging to diagnose AdSense ads not injecting
Added error_log statements to roi_inject_content_ads() to trace:
- Function entry point
- Conditions failing (is_single, in_the_loop, is_main_query)
- Container null check
- Settings loaded status
- Post exclusion check
- Rendered slot lengths
- Any exceptions with full trace

This will help identify why ads are not appearing on production
despite all database settings being correctly configured.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 19:42:17 -06:00
FrankZamora
b70e11be62 refactor: move Analytics from ThemeSettings to AdsensePlacement
- Remove Analytics and AdSense tabs from theme-settings component
- Add Analytics group to adsense-placement component
- Add roi_enqueue_analytics_script() for GA4/UA support
- Clean up ThemeSettings to only handle custom code (CSS/JS)
- Update FormBuilders and FieldMappers accordingly

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 18:43:39 -06:00
FrankZamora
23a3c4d074 perf(pagespeed): Preload todas las fuentes + diferir CSS no críticos
Fase 4.3 optimización CLS:
- Preload Poppins 400, 500, 600, 700 (antes solo 400, 600)
- Preload bootstrap-icons font
- Diferir: bootstrap-icons, accessibility, responsive, utilities CSS

Objetivo: CLS 0.109 → ≤0.10, Performance 96 → 100

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:00:57 -06:00
FrankZamora
83717771c0 feat(pagespeed): Fase 4.3 - Preload fuentes para reducir CLS
- Agregar preload de Poppins regular (400) y semibold (600)
- Agregar fallback font con size-adjust para minimizar layout shift
- Actualizar font stack con 'Poppins Fallback'

Impacto esperado: CLS 0.133 → ~0.05-0.08

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:45:01 -06:00
FrankZamora
d7915d372b refactor(adsense): remove dead code + PageSpeed CSS defer
- Remove unused roi_should_disable_auto_ads() function
- Remove enable_page_level_ads code (Auto Ads disabled in Google panel)
- Defer non-critical CSS with media=print pattern (Fase 4.2 PageSpeed)
- Fix roi-accessibility dependency: roi-theme-style -> roi-main-style

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:38:49 -06:00
FrankZamora
2acce34d9e fix(adsense): Disable Auto Ads when disable_auto_ads is enabled
- Add enable_page_level_ads: false to prevent Google from
  automatically inserting ads in unwanted locations
- This prevents ads from appearing inside table cells and
  other inappropriate places

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:29:16 -06:00
FrankZamora
99cde7c3d6 fix(adsense): registrar filtro the_content y corregir ancho de contenedor
- Registra filtro the_content para inyectar anuncios (post-top, post-bottom, content)
- Corrige CSS del contenedor .roi-ad-slot con width:100% para evitar availableWidth=0
- Usa ContentAdInjector para insertar ads dentro del contenido

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 15:07:12 -06:00
FrankZamora
2f19a7c077 Fase 4.1: Bootstrap Icons subset (94% reduccion)
Optimizacion PageSpeed:
- Original: 211 KB (2050 iconos)
- Subset: 13 KB (104 iconos usados)
- Ahorro: 198 KB (94% reduccion)

Cambios:
- Creado script create-icons-subset.py para generar subsets
- Generado bootstrap-icons-subset.min.css (4.5 KB)
- Generado bootstrap-icons-subset.woff2 (8.7 KB)
- Agregado font-display:swap (elimina bloqueo de 420ms)
- Actualizado enqueue-scripts.php para usar subset

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:34:52 -06:00
FrankZamora
cd09666f1d Backup antes de optimizar Bootstrap Icons (subset)
Estado actual:
- Bootstrap Icons completo: 211 KB (2050 iconos)
- Solo usamos 105 iconos (5.1%)

Próximo paso: crear subset de iconos para ahorrar ~199 KB

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:31:04 -06:00
FrankZamora
b0def25348 perf(TBT): Fase 2.3 - Eliminar código JS muerto (-96%)
Diagnóstico:
- main.js: ~95% código muerto (IDs no coinciden con DOM)
- header.js: ~90% código muerto (usa Bootstrap, no custom menu)

Cambios:
- main.js: 315 → 25 líneas (solo navbar scroll effect)
- header.js: DESHABILITADO completamente (343 líneas)
- Reducción total: ~633 líneas de JS innecesario

Impacto esperado: TBT -50-100ms

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 12:59:19 -06:00
FrankZamora
7e13678e0b fix(CLS): Add hero critical CSS to HEAD to prevent layout shift
- Add roi_output_hero_critical_css() function to inject CSS in <head>
- CSS now loads BEFORE hero HTML renders, preventing CLS
- Update min_height from 120px to 260px to match actual content height
- Update title_min_height from 3rem to 3.5rem
- Add responsive breakpoints for mobile (200px min-height)

This fixes CLS in Lighthouse Lab tests (was 0.265, now should be ~0.01)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 12:08:10 -06:00
FrankZamora
1876231ac1 Fix: AdSense delay regex now preserves ?client= parameter
The AdSense delay system was stripping the ?client=ca-pub-XXXXXX
parameter from script URLs during the regex replacement, causing
ads to fail loading silently.

Changed regex patterns to use capture groups ($1) to preserve the
complete URL including query parameters.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 09:47:07 -06:00
FrankZamora
4cbde7e1b7 Fix: allow dropdown parent links with URLs to navigate on click
- Only add data-bs-toggle=dropdown for items without real URL
- CSS hover handles dropdown display on desktop
- Enables Buscador General link to navigate to /buscar-apus/
2025-11-26 23:46:38 -06:00
FrankZamora
af16230cf9 fix: corregir rutas case-sensitive para Linux
- Renombrar Assets/Vendor/Fonts → fonts (Bootstrap Icons CSS espera lowercase)
- Corregir path del preload en performance.php: Vendor/Bootstrap/Css (PascalCase)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 23:19:10 -06:00
FrankZamora
0f947f6677 fix(assets): Add Bootstrap vendor files with PascalCase paths
- Add Assets/Vendor/Bootstrap/ (CSS and JS)
- Add Assets/Vendor/Fonts/ (Bootstrap Icons fonts)
- Fix path references in enqueue-scripts.php to use PascalCase
- Remove vendor/ from .gitignore (not using Composer)

Fixes CSS 404 errors on Linux production server.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 23:04:32 -06:00
FrankZamora
33d17f4b56 fix(structure): Rename assets and inc folders for Linux compatibility
- assets → Assets
- inc → Inc

Completes the case-sensitivity fixes for Linux servers.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 22:55:31 -06:00