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>
This commit is contained in:
@@ -17,10 +17,14 @@ final class AdsensePlacementFieldMapper implements FieldMapperInterface
|
||||
return [
|
||||
// VISIBILITY
|
||||
'adsense-placementEnabled' => ['group' => 'visibility', 'attribute' => 'is_enabled'],
|
||||
'adsense-placementDisableAutoAds' => ['group' => 'visibility', 'attribute' => 'disable_auto_ads'],
|
||||
'adsense-placementShowOnMobile' => ['group' => 'visibility', 'attribute' => 'show_on_mobile'],
|
||||
'adsense-placementShowOnDesktop' => ['group' => 'visibility', 'attribute' => 'show_on_desktop'],
|
||||
|
||||
// ANALYTICS (Google Analytics)
|
||||
'adsense-placementAnalyticsEnabled' => ['group' => 'analytics', 'attribute' => 'analytics_enabled'],
|
||||
'adsense-placementGaTrackingId' => ['group' => 'analytics', 'attribute' => 'ga_tracking_id'],
|
||||
'adsense-placementGaAnonymizeIp' => ['group' => 'analytics', 'attribute' => 'ga_anonymize_ip'],
|
||||
|
||||
// CONTENT (Credentials)
|
||||
'adsense-placementPublisherId' => ['group' => 'content', 'attribute' => 'publisher_id'],
|
||||
'adsense-placementSlotDisplay' => ['group' => 'content', 'attribute' => 'slot_display'],
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace ROITheme\Admin\AdsensePlacement\Infrastructure\Ui;
|
||||
use ROITheme\Admin\Infrastructure\Ui\AdminDashboardRenderer;
|
||||
|
||||
/**
|
||||
* FormBuilder para AdSense Placement
|
||||
* FormBuilder para AdSense Placement y Google Analytics
|
||||
*/
|
||||
final class AdsensePlacementFormBuilder
|
||||
{
|
||||
@@ -24,10 +24,10 @@ final class AdsensePlacementFormBuilder
|
||||
$html .= ' <div>';
|
||||
$html .= ' <h3 class="h4 mb-1 fw-bold">';
|
||||
$html .= ' <i class="bi bi-megaphone me-2" style="color: #FF8600;"></i>';
|
||||
$html .= ' Control de Anuncios AdSense';
|
||||
$html .= ' AdSense y Analytics';
|
||||
$html .= ' </h3>';
|
||||
$html .= ' <p class="mb-0 small" style="opacity: 0.85;">';
|
||||
$html .= ' Configura ubicaciones manuales de anuncios para evitar Auto Ads';
|
||||
$html .= ' Configura Google AdSense y Google Analytics';
|
||||
$html .= ' </p>';
|
||||
$html .= ' </div>';
|
||||
$html .= ' </div>';
|
||||
@@ -39,6 +39,7 @@ final class AdsensePlacementFormBuilder
|
||||
// COLUMNA IZQUIERDA
|
||||
$html .= ' <div class="col-lg-6">';
|
||||
$html .= $this->buildVisibilityGroup($componentId);
|
||||
$html .= $this->buildAnalyticsGroup($componentId);
|
||||
$html .= $this->buildCredentialsGroup($componentId);
|
||||
$html .= $this->buildPostLocationsGroup($componentId);
|
||||
$html .= ' </div>';
|
||||
@@ -61,16 +62,12 @@ final class AdsensePlacementFormBuilder
|
||||
$html .= ' <div class="card-body">';
|
||||
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
||||
$html .= ' <i class="bi bi-toggle-on me-2" style="color: #FF8600;"></i>';
|
||||
$html .= ' Activacion y Visibilidad';
|
||||
$html .= ' Activacion AdSense';
|
||||
$html .= ' </h5>';
|
||||
|
||||
// Switch: Enabled
|
||||
$enabled = $this->renderer->getFieldValue($cid, 'visibility', 'is_enabled', false);
|
||||
$html .= $this->buildSwitch($cid . 'Enabled', 'Activar Placement Manual', $enabled, 'bi-power');
|
||||
|
||||
// Switch: Disable Auto Ads
|
||||
$disableAuto = $this->renderer->getFieldValue($cid, 'visibility', 'disable_auto_ads', true);
|
||||
$html .= $this->buildSwitch($cid . 'DisableAutoAds', 'Deshabilitar Auto Ads de Google', $disableAuto, 'bi-shield-x');
|
||||
$html .= $this->buildSwitch($cid . 'Enabled', 'Activar AdSense', $enabled, 'bi-power');
|
||||
|
||||
// Switch: Show on Mobile
|
||||
$showMobile = $this->renderer->getFieldValue($cid, 'visibility', 'show_on_mobile', true);
|
||||
@@ -86,6 +83,39 @@ final class AdsensePlacementFormBuilder
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildAnalyticsGroup(string $cid): string
|
||||
{
|
||||
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
||||
$html .= ' <div class="card-body">';
|
||||
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
||||
$html .= ' <i class="bi bi-graph-up me-2" style="color: #FF8600;"></i>';
|
||||
$html .= ' Google Analytics';
|
||||
$html .= ' </h5>';
|
||||
|
||||
// Switch: Analytics Enabled
|
||||
$analyticsEnabled = $this->renderer->getFieldValue($cid, 'analytics', 'analytics_enabled', false);
|
||||
$html .= $this->buildSwitch($cid . 'AnalyticsEnabled', 'Activar Analytics', $analyticsEnabled, 'bi-power');
|
||||
|
||||
// Tracking ID
|
||||
$gaTrackingId = $this->renderer->getFieldValue($cid, 'analytics', 'ga_tracking_id', '');
|
||||
$html .= $this->buildTextInput($cid . 'GaTrackingId', 'Google Analytics ID', $gaTrackingId, 'G-XXXXXXXXXX');
|
||||
$html .= '<div class="form-text small mb-2">Formato: G-XXXXXXXXXX o UA-XXXXXXXX-X</div>';
|
||||
|
||||
// Anonymize IP
|
||||
$gaAnonymizeIp = $this->renderer->getFieldValue($cid, 'analytics', 'ga_anonymize_ip', true);
|
||||
$html .= $this->buildSwitch($cid . 'GaAnonymizeIp', 'Anonimizar IP (GDPR)', $gaAnonymizeIp, 'bi-shield-check');
|
||||
|
||||
$html .= ' <div class="alert alert-warning small mb-0 mt-2">';
|
||||
$html .= ' <i class="bi bi-exclamation-triangle me-1"></i>';
|
||||
$html .= ' Recomendado activar para cumplir con GDPR/RGPD';
|
||||
$html .= ' </div>';
|
||||
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildCredentialsGroup(string $cid): string
|
||||
{
|
||||
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
||||
|
||||
@@ -24,14 +24,6 @@ final class ThemeSettingsFieldMapper implements FieldMapperInterface
|
||||
public function getFieldMapping(): array
|
||||
{
|
||||
return [
|
||||
// Analytics
|
||||
'themeSettingsGaTrackingId' => ['group' => 'analytics', 'attribute' => 'ga_tracking_id'],
|
||||
'themeSettingsGaAnonymizeIp' => ['group' => 'analytics', 'attribute' => 'ga_anonymize_ip'],
|
||||
|
||||
// AdSense
|
||||
'themeSettingsAdsensePublisherId' => ['group' => 'adsense', 'attribute' => 'adsense_publisher_id'],
|
||||
'themeSettingsAdsenseAutoAds' => ['group' => 'adsense', 'attribute' => 'adsense_auto_ads'],
|
||||
|
||||
// Custom Code
|
||||
'themeSettingsCustomCss' => ['group' => 'custom_code', 'attribute' => 'custom_css'],
|
||||
'themeSettingsCustomJsHeader' => ['group' => 'custom_code', 'attribute' => 'custom_js_header'],
|
||||
|
||||
@@ -9,9 +9,9 @@ use ROITheme\Admin\Infrastructure\Ui\AdminDashboardRenderer;
|
||||
* FormBuilder para Theme Settings
|
||||
*
|
||||
* RESPONSABILIDAD: Generar formulario de configuraciones globales del tema
|
||||
* (analytics, adsense, codigo personalizado)
|
||||
* (codigo personalizado - CSS y JavaScript)
|
||||
*
|
||||
* NOTA: Logo/branding se gestiona desde el componente navbar
|
||||
* NOTA: Analytics y AdSense se gestionan desde el componente adsense-placement
|
||||
*
|
||||
* @package ROITheme\Admin\ThemeSettings\Infrastructure\Ui
|
||||
*/
|
||||
@@ -29,14 +29,8 @@ final class ThemeSettingsFormBuilder
|
||||
|
||||
$html .= '<div class="row g-3">';
|
||||
|
||||
// Columna izquierda - Analytics + AdSense
|
||||
$html .= '<div class="col-lg-6">';
|
||||
$html .= $this->buildAnalyticsGroup($componentId);
|
||||
$html .= $this->buildAdSenseGroup($componentId);
|
||||
$html .= '</div>';
|
||||
|
||||
// Columna derecha - Custom Code
|
||||
$html .= '<div class="col-lg-6">';
|
||||
// Columna unica - Custom Code
|
||||
$html .= '<div class="col-lg-8 mx-auto">';
|
||||
$html .= $this->buildCustomCodeGroup($componentId);
|
||||
$html .= '</div>';
|
||||
|
||||
@@ -56,7 +50,7 @@ final class ThemeSettingsFormBuilder
|
||||
$html .= ' Configuraciones Globales del Tema';
|
||||
$html .= ' </h3>';
|
||||
$html .= ' <p class="mb-0 small" style="opacity: 0.85;">';
|
||||
$html .= ' Analytics, AdSense y Codigo Personalizado';
|
||||
$html .= ' Codigo Personalizado (CSS y JavaScript)';
|
||||
$html .= ' </p>';
|
||||
$html .= ' </div>';
|
||||
$html .= ' <button type="button" class="btn btn-sm btn-outline-light btn-reset-defaults" data-component="theme-settings">';
|
||||
@@ -69,62 +63,6 @@ final class ThemeSettingsFormBuilder
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildAnalyticsGroup(string $componentId): string
|
||||
{
|
||||
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
||||
$html .= ' <div class="card-body">';
|
||||
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
||||
$html .= ' <i class="bi bi-graph-up me-2" style="color: #FF8600;"></i>';
|
||||
$html .= ' Analytics';
|
||||
$html .= ' </h5>';
|
||||
|
||||
$gaTrackingId = $this->renderer->getFieldValue($componentId, 'analytics', 'ga_tracking_id', '');
|
||||
$html .= $this->buildTextInput('themeSettingsGaTrackingId', 'Google Analytics ID', 'bi-bar-chart', $gaTrackingId);
|
||||
|
||||
$html .= ' <div class="form-text small mb-2">Formato: G-XXXXXXXXXX o UA-XXXXXXXX-X</div>';
|
||||
|
||||
$gaAnonymizeIp = $this->renderer->getFieldValue($componentId, 'analytics', 'ga_anonymize_ip', true);
|
||||
$html .= $this->buildSwitch('themeSettingsGaAnonymizeIp', 'Anonimizar IP (GDPR)', 'bi-shield-check', $gaAnonymizeIp);
|
||||
|
||||
$html .= ' <div class="alert alert-warning small mb-0 mt-2">';
|
||||
$html .= ' <i class="bi bi-exclamation-triangle me-1"></i>';
|
||||
$html .= ' Recomendado activar para cumplir con GDPR/RGPD';
|
||||
$html .= ' </div>';
|
||||
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildAdSenseGroup(string $componentId): string
|
||||
{
|
||||
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
||||
$html .= ' <div class="card-body">';
|
||||
$html .= ' <h5 class="fw-bold mb-3" style="color: #1e3a5f;">';
|
||||
$html .= ' <i class="bi bi-badge-ad me-2" style="color: #FF8600;"></i>';
|
||||
$html .= ' Google AdSense';
|
||||
$html .= ' </h5>';
|
||||
|
||||
$publisherId = $this->renderer->getFieldValue($componentId, 'adsense', 'adsense_publisher_id', '');
|
||||
$html .= $this->buildTextInput('themeSettingsAdsensePublisherId', 'Publisher ID', 'bi-key', $publisherId);
|
||||
|
||||
$html .= ' <div class="form-text small mb-2">Formato: ca-pub-1234567890123456</div>';
|
||||
|
||||
$autoAds = $this->renderer->getFieldValue($componentId, 'adsense', 'adsense_auto_ads', false);
|
||||
$html .= $this->buildSwitch('themeSettingsAdsenseAutoAds', 'Activar Auto Ads', 'bi-magic', $autoAds);
|
||||
|
||||
$html .= ' <div class="alert alert-info small mb-0 mt-2">';
|
||||
$html .= ' <i class="bi bi-info-circle me-1"></i>';
|
||||
$html .= ' Auto Ads permite que Google coloque anuncios automaticamente en las mejores ubicaciones.';
|
||||
$html .= ' </div>';
|
||||
|
||||
$html .= ' </div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildCustomCodeGroup(string $componentId): string
|
||||
{
|
||||
$html = '<div class="card shadow-sm mb-3" style="border-left: 4px solid #1e3a5f;">';
|
||||
@@ -154,37 +92,6 @@ final class ThemeSettingsFormBuilder
|
||||
return $html;
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
private function buildSwitch(string $id, string $label, string $icon, $value): string
|
||||
{
|
||||
$checked = $value === true || $value === '1' || $value === 1 ? 'checked' : '';
|
||||
|
||||
$html = ' <div class="form-check form-switch mb-2">';
|
||||
$html .= ' <input class="form-check-input" type="checkbox" id="' . esc_attr($id) . '" ' . $checked . '>';
|
||||
$html .= ' <label class="form-check-label small" for="' . esc_attr($id) . '">';
|
||||
$html .= ' <i class="bi ' . esc_attr($icon) . ' me-1" style="color: #FF8600;"></i>';
|
||||
$html .= ' ' . esc_html($label);
|
||||
$html .= ' </label>';
|
||||
$html .= ' </div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildTextInput(string $id, string $label, string $icon, mixed $value): string
|
||||
{
|
||||
$value = $this->normalizeStringValue($value);
|
||||
|
||||
$html = ' <div class="mb-3">';
|
||||
$html .= ' <label for="' . esc_attr($id) . '" class="form-label small mb-1 fw-semibold">';
|
||||
$html .= ' <i class="bi ' . esc_attr($icon) . ' me-1" style="color: #FF8600;"></i>';
|
||||
$html .= ' ' . esc_html($label);
|
||||
$html .= ' </label>';
|
||||
$html .= ' <input type="text" class="form-control form-control-sm" id="' . esc_attr($id) . '" value="' . esc_attr($value) . '">';
|
||||
$html .= ' </div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function buildTextareaCode(string $id, string $label, string $icon, mixed $value, string $helpText = ''): string
|
||||
{
|
||||
$value = $this->normalizeStringValue($value);
|
||||
|
||||
Reference in New Issue
Block a user