Commit Graph

359 Commits

Author SHA1 Message Date
FrankZamora
1b9910165b fix(rail-ads): Position rails fixed at viewport edges
- Changed Rail Ads positioning from container-width-based formula to fixed 15px from viewport edges
- Rails no longer move inward when container width is reduced
- Fixes overlap issue when layout width setting changes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:38:04 -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
72ef7580fc fix: Container width setting now applies correctly + Rail Ads improvements
- Fix container width not applying: css-global-responsive.css now uses
  CSS variable --roi-container-width instead of hardcoded values
- Add 8 Rail format options: slim-small (160x300), slim-medium (160x400),
  slim-large (160x500), skyscraper (160x600), slim-xlarge (160x700),
  wide-skyscraper (160x800), half-page (300x600), large-skyscraper (300x1050)
- Change rail_top_offset from text input to select with preset values
- Fix Rail Ads JavaScript positioning (moved after HTML, added retries)
- ThemeSettingsRenderer now always outputs CSS variables for layout

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:30:06 -06:00
FrankZamora
122bcd4750 feat(adsense): agregar mas opciones de formato y altura para Rail Ads
- Formatos: skyscraper (160x600), wide-skyscraper (160x800), half-page (300x600), large-skyscraper (300x1050)
- Distancia desde arriba: 150, 200, 300 (default), 400, 500, 700px
- Cambiar rail_top_offset de text a select con opciones predefinidas

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:05:49 -06:00
FrankZamora
0dfe3fcd2c feat(theme-settings): agregar configuracion de ancho del contenedor
- Nuevo grupo 'Layout y Contenedor' en theme-settings
- Opciones: 1140px, 1200px, 1320px (default), 1400px, 100%
- CSS dinamico aplicado via ThemeSettingsRenderer
- Corregir selectores de hero en Rail Ads (.hero-section, .featured-image-container)
- Agregar setTimeout para esperar carga de DOM
- Aumentar gap de separacion a 30px
- Subir maxTop al 40% del viewport

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 21:03:43 -06:00
FrankZamora
2fa112ab7f fix(adsense): corregir posicionamiento de Rail Ads
- Usar CSS max() para evitar rail izquierdo cortado fuera del viewport
- Agregar JavaScript inteligente para detectar navbar/hero dinámicamente
- Rail ads se posicionan debajo del hero cuando es visible
- Usar requestAnimationFrame para throttle de scroll
- Eliminar dependencia de valores fijos en pixels

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:55:18 -06:00
FrankZamora
55f061df67 feat(adsense): reorganizar panel con UX mejorada y soporte 1-8 ads random
Panel AdSense reorganizado:
- Diagrama visual mostrando ubicaciones de anuncios (POST-TOP, IN-CONTENT, POST-BOTTOM, RAIL)
- Secciones colapsables por ubicación con badges de color
- Slots con descripciones claras indicando uso (Auto, In-Article, Display, etc.)

In-Content Ads mejorado:
- Soporte para 1-8 anuncios dentro del contenido
- Modo aleatorio (random) que varía posiciones en cada visita
- Configuración de mínimo/máximo de ads
- Párrafos mínimos entre anuncios configurable (2-6)
- Primer ad siempre en posición fija configurada

Archivos modificados:
- Schema v1.2.0 con 4 nuevos campos (random_mode, min_ads, max_ads, min_paragraphs_between)
- FormBuilder con diagrama visual y mejor organización
- ContentAdInjector con lógica de posicionamiento random
- Renderer con soporte para post-content-1 hasta post-content-8
- FieldMapper actualizado con nuevos campos

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 20:45:40 -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
cfcc38c0f7 debug: Add template-level debug to trace content output 2025-11-27 20:12:31 -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
79b48ad94f fix(di): declare $container as global before assignment
The $container variable was being assigned inside a try-catch block
without being declared as global first, making it unavailable to
Inc/adsense-placement.php functions. This caused AdSense slots to
not be injected into the content.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 19:35:22 -06:00
FrankZamora
82abdf047a ui(theme-settings): split into two cards (CSS left, JS right)
- CSS Personalizado card on left column (10 rows textarea)
- JavaScript Personalizado card on right column (Header + Footer)
- Improved visual organization with separate alerts per card

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 18:47:13 -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
3279b7df2b Add WordPress posts malformed lists fixer for post_content field 2025-11-27 18:10:37 -06:00
FrankZamora
a3fa5fe22e Add specific cases test script 2025-11-27 17:46:51 -06:00
FrankZamora
84441af9c0 Add varied cases finder script 2025-11-27 17:45:55 -06:00
FrankZamora
651e8124d4 Add validation script for list fixes
Generates HTML files for visual comparison before/after
correction. Creates comparison_report.html for review.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:40:18 -06:00
FrankZamora
a10831e2c2 Add DOMDocument-based malformed lists fixer
Robust HTML list structure correction using PHP DOM parser.
Three modes: scan (detect), test (preview), fix (apply).
Properly moves nested lists inside parent <li> elements.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:34:27 -06:00
FrankZamora
d7c42f26ef Add test script for malformed lists fix validation
Demonstrates proposed regex replacement pattern without
applying changes. For validation before mass update.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:29:47 -06:00
FrankZamora
4dbf73f226 Fix column name in malformed lists scanner
Changed 'url' to 'page' to match actual table schema
in preciosunitarios_seo.datos_seo_pagina

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:24:47 -06:00
FrankZamora
f4bd013271 Add diagnostic script for malformed HTML lists
Phase 4.4 Accessibility: Script to scan database for posts
with invalid list structures (<ul> containing non-<li> children).
Read-only analysis, no modifications.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:20:00 -06:00
FrankZamora
371995d151 fix(accessibility): Add main landmark and fix cta-box-title heading
Phase 4.4 Accessibility fixes:
- single.php: Add <main id="main-content" role="main"> landmark
- CtaBoxSidebarRenderer: h5 cta-box-title changed to span

Fixes: "No main landmark" and "Headings skip levels"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 17:03:22 -06:00
FrankZamora
1c901ecdf9 fix(accessibility): Fix cta-post contrast and heading hierarchy
Phase 4.4 Accessibility fixes:
- cta-post: button_text_color from #ffffff to #0E2337 (WCAG AA 4.8:1)
- TableOfContentsRenderer: h4 toc-title changed to span (semantic)
- FooterRenderer: h5 widget-title changed to span (5 instances)

Fixes: "Low contrast on cta-button" and "Headings skip levels"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:59:06 -06:00
FrankZamora
281c05fa33 fix(accessibility): Correct heading hierarchy and identical links
Phase 4.4 Accessibility fixes:
- ContactFormRenderer: Change h6 info-labels to span (WhatsApp, Email, Location)
- RelatedPostRenderer: Change h5 card-title to span (semantic hierarchy)
- top-notification-bar schema: Change link_url default from # to /suscripcion-vip
  (identical links must have same destination)

Fixes: "Headings not in sequential order" and "Identical links have different purposes"

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:45:38 -06:00
FrankZamora
0a303be198 fix(accessibility): Update cta-box-sidebar button text color for WCAG AA
Changed button_text_color from #FF8600 to #0E2337 (navy-dark)
- Orange on white had only 2.9:1 contrast ratio
- Navy-dark on white provides 12.6:1 contrast ratio (WCAG AAA)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:40:58 -06:00
FrankZamora
6edb2ebeaa fix(accessibility): Update colors for WCAG AA contrast compliance
Phase 4.4 PageSpeed Accessibility fixes:
- cta-box-sidebar: title/description colors from white to navy-dark (#0E2337)
- contact-form: info_value_color from #D5D8DA to #495057, button text to navy-dark
- cta-lets-talk: text_color from white to navy-dark
- css-tablas-apu: .c3 column color from #6c757d to #495057 (7.0:1 ratio)

All changes ensure minimum 4.5:1 contrast ratio for normal text (WCAG AA).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:31:18 -06:00
FrankZamora
4ad48b4326 fix(accessibility): Improve color contrast for WCAG AA compliance
Phase 4.4 Accessibility:
- Change white text to navy-dark on orange table headers (ratio 4.8:1)
- Fix subtotal rows in APU tables: orange text to navy for better contrast
- Affects styles 2, 5, 7, 10 in generic tables
- Fixes PageSpeed accessibility warnings

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 16:16:55 -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
50a8c2bf18 debug: remove condition to test if enqueue works 2025-11-27 14:42:43 -06:00
FrankZamora
096f9716ef fix(youtube-facade): use is_singular() instead of is_single()
Changed condition from is_single() to is_singular() to ensure
YouTube facade assets load on all singular content types.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:41:42 -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
b43cb22dc1 feat(youtube-facade): Phase 2.4 complete - YouTube Facade for PageSpeed
- Replace YouTube iframes with lightweight facade (thumbnail + play button)
- Load real iframe only on user click
- Reduces TBT by ~2000ms
- Works with mu-plugin allow-unfiltered-html.php
- Filter priority 101 (after RCP)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 14:05:34 -06:00
FrankZamora
deef577c36 fix: Change filter priority to 101 (after RCP) 2025-11-27 13:58:20 -06:00
FrankZamora
d5bdb81cbe debug: Add result verification logging 2025-11-27 13:57:17 -06:00
FrankZamora
56a7c29653 debug: Add renderer output logging 2025-11-27 13:55:09 -06:00
FrankZamora
acdfeffd75 debug: Add detailed pattern matching logging 2025-11-27 13:53:56 -06:00
FrankZamora
eeacfdb284 debug: Add trace logging to functions.php try-catch block 2025-11-27 13:44:11 -06:00
FrankZamora
d867212790 Debug: Add logging to hooks registration 2025-11-27 13:41:13 -06:00
FrankZamora
98c90756f8 Debug: Add minimal logging to verify filter execution 2025-11-27 13:40:09 -06:00
FrankZamora
52e2698279 feat(youtube-facade): Phase 2.4 - YouTube Facade Pattern for PageSpeed optimization
- Replace YouTube iframes with lightweight facade (thumbnail + play button)
- Load real iframe only on user click
- Reduces TBT by ~2000ms
- Uses youtube-nocookie.com for privacy-enhanced mode
2025-11-27 13:37:36 -06:00