getComponentSettingsRepository(); $settings = $repository->getComponentSettings('adsense-placement'); if (empty($settings)) { return ''; } // Verificar exclusiones if (roi_is_ad_excluded($settings)) { return ''; } // Obtener renderer desde DIContainer (DIP compliant) $renderer = $container->getAdsensePlacementRenderer(); return $renderer->renderSlot($settings, $location); } catch (\Throwable $e) { if (defined('WP_DEBUG') && WP_DEBUG) { error_log('ROI AdSense: ' . $e->getMessage()); } return ''; } } /** * Verifica si el contenido actual esta excluido */ function roi_is_ad_excluded(array $settings): bool { $forms = $settings['forms'] ?? []; // Excluir categorias $excludeCats = array_filter(array_map('trim', explode(',', $forms['exclude_categories'] ?? ''))); if (!empty($excludeCats) && is_single()) { $postCats = wp_get_post_categories(get_the_ID()); if (array_intersect($excludeCats, $postCats)) { return true; } } // Excluir tipos de post $excludeTypes = array_filter(array_map('trim', explode(',', $forms['exclude_post_types'] ?? ''))); if (!empty($excludeTypes) && in_array(get_post_type(), $excludeTypes, true)) { return true; } // Excluir posts especificos $excludeIds = array_filter(array_map('trim', explode(',', $forms['exclude_post_ids'] ?? ''))); if (!empty($excludeIds) && in_array((string)get_the_ID(), $excludeIds, true)) { return true; } return false; } /** * Renderiza los Rail Ads (margenes laterales del viewport) * Se llama desde wp_footer para inyectar al final del body * * NOTA DIP: El renderer se obtiene del DIContainer, NO se instancia directamente. */ function roi_render_rail_ads(): string { global $container; if ($container === null) { return ''; } try { $repository = $container->getComponentSettingsRepository(); $settings = $repository->getComponentSettings('adsense-placement'); if (empty($settings)) { return ''; } // Verificar exclusiones if (roi_is_ad_excluded($settings)) { return ''; } // Obtener renderer desde DIContainer (DIP compliant) $renderer = $container->getAdsensePlacementRenderer(); return $renderer->renderRailAds($settings); } catch (\Throwable $e) { if (defined('WP_DEBUG') && WP_DEBUG) { error_log('ROI AdSense Rail Ads: ' . $e->getMessage()); } return ''; } } /** * Hook para inyectar Rail Ads en el footer */ add_action('wp_footer', function() { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo roi_render_rail_ads(); }, 50); /** * Carga el script principal de AdSense */ function roi_enqueue_adsense_script(): void { global $container; if ($container === null || is_admin()) { return; } try { $repository = $container->getComponentSettingsRepository(); $settings = $repository->getComponentSettings('adsense-placement'); if (!($settings['visibility']['is_enabled'] ?? false)) { return; } $publisherId = $settings['content']['publisher_id'] ?? ''; if (empty($publisherId)) { return; } $delayEnabled = ($settings['forms']['delay_enabled'] ?? true) === true; if ($delayEnabled) { echo '' . "\n"; } else { echo '' . "\n"; } } catch (\Throwable $e) { if (defined('WP_DEBUG') && WP_DEBUG) { error_log('ROI AdSense: ' . $e->getMessage()); } } } add_action('wp_head', 'roi_enqueue_adsense_script', 5); /** * Registra el filtro the_content para inyectar anuncios */ // Prioridad 150 para ejecutar DESPUÉS de restrict-content-pro (100) add_filter('the_content', 'roi_inject_content_ads', 150); function roi_inject_content_ads(string $content): string { global $container; // DEBUG: Log para diagnosticar problema de ads no inyectados $post_id = get_the_ID(); $post_url = get_permalink(); error_log('ROI AdSense Debug: roi_inject_content_ads called for post_id=' . $post_id . ', url=' . $post_url); // Solo en posts individuales if (!is_single() || !in_the_loop() || !is_main_query()) { error_log('ROI AdSense Debug: Skip - not single/loop/main_query. is_single=' . (is_single() ? '1' : '0') . ', in_the_loop=' . (in_the_loop() ? '1' : '0') . ', is_main_query=' . (is_main_query() ? '1' : '0')); return $content; } if ($container === null) { error_log('ROI AdSense Debug: Skip - container is null'); return $content; } try { $repository = $container->getComponentSettingsRepository(); $settings = $repository->getComponentSettings('adsense-placement'); error_log('ROI AdSense Debug: Settings loaded. is_enabled=' . ($settings['visibility']['is_enabled'] ?? 'NOT SET')); if (empty($settings) || !($settings['visibility']['is_enabled'] ?? false)) { error_log('ROI AdSense Debug: Skip - settings empty or not enabled'); return $content; } // Verificar exclusiones if (roi_is_ad_excluded($settings)) { error_log('ROI AdSense Debug: Skip - post excluded'); return $content; } $renderer = $container->getAdsensePlacementRenderer(); // Inyectar anuncio al inicio (post-top) $postTopHtml = ''; if ($settings['behavior']['post_top_enabled'] ?? false) { $postTopHtml = $renderer->renderSlot($settings, 'post-top'); error_log('ROI AdSense Debug: post-top rendered, length=' . strlen($postTopHtml)); } // Inyectar anuncio al final (post-bottom) $postBottomHtml = ''; if ($settings['behavior']['post_bottom_enabled'] ?? false) { $postBottomHtml = $renderer->renderSlot($settings, 'post-bottom'); error_log('ROI AdSense Debug: post-bottom rendered, length=' . strlen($postBottomHtml)); } // Inyectar anuncios dentro del contenido $injector = new \ROITheme\Public\AdsensePlacement\Infrastructure\Services\ContentAdInjector( $settings, $renderer ); $content = $injector->inject($content); // DEBUG: Agregar marcador visible para rastrear si el contenido se pierde después del filtro $debugMarker = ''; $finalContent = $debugMarker . $postTopHtml . $content . $postBottomHtml . $debugMarker; error_log('ROI AdSense Debug: Final injection done. postTop=' . strlen($postTopHtml) . ', postBottom=' . strlen($postBottomHtml) . ', finalLength=' . strlen($finalContent)); error_log('ROI AdSense Debug: First 200 chars of postTopHtml: ' . substr($postTopHtml, 0, 200)); return $finalContent; } catch (\Throwable $e) { error_log('ROI AdSense Content ERROR: ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine()); return $content; } } /** * Carga el script de Google Analytics (GA4 o Universal Analytics) */ function roi_enqueue_analytics_script(): void { global $container; if ($container === null || is_admin()) { return; } try { $repository = $container->getComponentSettingsRepository(); $settings = $repository->getComponentSettings('adsense-placement'); // Verificar si Analytics esta habilitado if (!($settings['analytics']['analytics_enabled'] ?? false)) { return; } $trackingId = trim($settings['analytics']['ga_tracking_id'] ?? ''); if (empty($trackingId)) { return; } // Verificar si GA ya esta cargado por otro plugin if (roi_is_analytics_loaded()) { return; } $anonymizeIp = ($settings['analytics']['ga_anonymize_ip'] ?? true) === true; // Detectar tipo de ID (GA4 vs Universal Analytics) if (strpos($trackingId, 'G-') === 0) { roi_render_ga4_script($trackingId, $anonymizeIp); } elseif (strpos($trackingId, 'UA-') === 0) { roi_render_universal_analytics_script($trackingId, $anonymizeIp); } } catch (\Throwable $e) { if (defined('WP_DEBUG') && WP_DEBUG) { error_log('ROI Analytics: ' . $e->getMessage()); } } } add_action('wp_head', 'roi_enqueue_analytics_script', 1); /** * Verifica si Google Analytics ya esta cargado por otro plugin */ function roi_is_analytics_loaded(): bool { // Verificar si MonsterInsights esta activo if (class_exists('MonsterInsights_Lite') || class_exists('MonsterInsights')) { return true; } // Verificar si Site Kit de Google esta activo if (class_exists('Google\Site_Kit\Plugin')) { return true; } return false; } /** * Renderiza script de Google Analytics 4 */ function roi_render_ga4_script(string $trackingId, bool $anonymizeIp): void { $config = $anonymizeIp ? "{ 'anonymize_ip': true }" : '{}'; echo '' . "\n"; echo '' . "\n"; echo '' . "\n"; } /** * Renderiza script de Universal Analytics (legacy) */ function roi_render_universal_analytics_script(string $trackingId, bool $anonymizeIp): void { $anonymizeConfig = $anonymizeIp ? 'ga("set", "anonymizeIp", true);' : ''; echo '' . "\n"; echo '' . "\n"; }