fix(analytics): Corregir queries y unificar UI de recomendaciones
Fixes: - CTR 0%: Cambiar query de IS NULL a HAVING clicks=0 para CTR global real - Decay content: Aumentar umbral de 3 a 5 clicks para evitar ruido - Click distribution: Expandir de posiciones 1-5 a 1-10 individual - Remover URL redundante de tabla Top Posts UI: - Convertir 3 secciones de recomendaciones a formato tabla consistente: * ACCIÓN URGENTE: Contenido a Crear * REVISAR: Títulos con CTR 0% * QUICK WINS: Oportunidades Fáciles 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -153,7 +153,8 @@ final class ROI_APU_Metrics_Repository
|
||||
}
|
||||
|
||||
/**
|
||||
* Get terms with CTR 0% (have results but no clicks)
|
||||
* Get terms with truly 0% CTR (have results but ZERO clicks globally)
|
||||
* Only shows terms where no search instance ever got a click
|
||||
*
|
||||
* @param int $days Number of days to query
|
||||
* @param int $limit Max results
|
||||
@@ -162,14 +163,18 @@ final class ROI_APU_Metrics_Repository
|
||||
public function getCTRZero(int $days = 30, int $limit = 20): array
|
||||
{
|
||||
try {
|
||||
$sql = "SELECT s.q_term, COUNT(DISTINCT s.id) as busquedas, MAX(s.total_results) as resultados
|
||||
// Get terms with results but 0 total clicks (true 0% CTR)
|
||||
$sql = "SELECT
|
||||
s.q_term,
|
||||
COUNT(DISTINCT s.id) as busquedas,
|
||||
MAX(s.total_results) as resultados,
|
||||
COUNT(DISTINCT c.id) as clicks
|
||||
FROM {$this->prefix}rcp_paginas_querys s
|
||||
LEFT JOIN {$this->prefix}rcp_paginas_querys_log c ON s.id = c.search_id
|
||||
WHERE s.total_results > 0
|
||||
AND c.id IS NULL
|
||||
AND s.ts >= DATE_SUB(NOW(), INTERVAL :days DAY)
|
||||
GROUP BY s.q_term
|
||||
HAVING busquedas >= 3
|
||||
HAVING clicks = 0 AND busquedas >= 3
|
||||
ORDER BY busquedas DESC
|
||||
LIMIT :limit";
|
||||
|
||||
@@ -415,7 +420,7 @@ final class ROI_APU_Metrics_Repository
|
||||
}
|
||||
|
||||
/**
|
||||
* Get click distribution by position
|
||||
* Get click distribution by position (positions 1-10 individually, 11+ grouped)
|
||||
*
|
||||
* @param int $days Number of days to query
|
||||
* @return array<array{posicion: string, clicks: int, porcentaje: float}>
|
||||
@@ -430,7 +435,12 @@ final class ROI_APU_Metrics_Repository
|
||||
WHEN position = 3 THEN 'Pos 3'
|
||||
WHEN position = 4 THEN 'Pos 4'
|
||||
WHEN position = 5 THEN 'Pos 5'
|
||||
ELSE 'Pos 6+'
|
||||
WHEN position = 6 THEN 'Pos 6'
|
||||
WHEN position = 7 THEN 'Pos 7'
|
||||
WHEN position = 8 THEN 'Pos 8'
|
||||
WHEN position = 9 THEN 'Pos 9'
|
||||
WHEN position = 10 THEN 'Pos 10'
|
||||
ELSE 'Pos 11+'
|
||||
END as posicion,
|
||||
COUNT(*) as clicks,
|
||||
ROUND(COUNT(*) * 100.0 / NULLIF((
|
||||
@@ -456,6 +466,7 @@ final class ROI_APU_Metrics_Repository
|
||||
|
||||
/**
|
||||
* Get decaying content: posts that lost clicks vs previous period
|
||||
* Only shows posts with significant traffic (≥5 clicks before) to avoid statistical noise
|
||||
*
|
||||
* @param int $days Number of days to query
|
||||
* @param int $limit Max results
|
||||
@@ -485,7 +496,7 @@ final class ROI_APU_Metrics_Repository
|
||||
GROUP BY post_id
|
||||
) curr ON pa.post_id = curr.post_id
|
||||
JOIN {$this->prefix}posts p ON pa.post_id = p.ID
|
||||
WHERE pa.clicks_anterior >= 3
|
||||
WHERE pa.clicks_anterior >= 5
|
||||
AND (COALESCE(curr.clicks_actual, 0) - pa.clicks_anterior) * 100.0 / pa.clicks_anterior <= -20
|
||||
ORDER BY cambio_pct ASC
|
||||
LIMIT :limit";
|
||||
|
||||
Reference in New Issue
Block a user