feat: add getDailyConversions() — demo boots, downloads, abandoned carts
Daily time-series data for conversion funnel metrics, compatible with NVD3 chart format. Abandoned carts = visited cart but no order confirmation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -237,6 +237,88 @@ class VisitorStats
|
||||
) ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get daily demo boots + demo downloads + abandoned carts for charting.
|
||||
*
|
||||
* @param string $dateFrom Y-m-d
|
||||
* @param string $dateTo Y-m-d
|
||||
* @return array ['demo_boots' => [[ts,val],...], 'demo_downloads' => [...], 'abandoned_carts' => [...]]
|
||||
*/
|
||||
public static function getDailyConversions(string $dateFrom, string $dateTo): array
|
||||
{
|
||||
$db = \Db::getInstance((bool) _PS_USE_SQL_SLAVE_);
|
||||
$prefix = _DB_PREFIX_;
|
||||
|
||||
// Demo boots
|
||||
$bootRows = $db->executeS(
|
||||
"SELECT DATE(date_add) as day, COUNT(*) as cnt
|
||||
FROM `{$prefix}mprdigitalrevolution_demo_boot`
|
||||
WHERE date_add >= '" . pSQL($dateFrom) . " 00:00:00'
|
||||
AND date_add <= '" . pSQL($dateTo) . " 23:59:59'
|
||||
GROUP BY DATE(date_add)"
|
||||
) ?: [];
|
||||
|
||||
// Demo downloads
|
||||
$dlRows = $db->executeS(
|
||||
"SELECT DATE(date_add) as day, COUNT(*) as cnt
|
||||
FROM `{$prefix}mprdigitalrevolution_demo_request`
|
||||
WHERE date_add >= '" . pSQL($dateFrom) . " 00:00:00'
|
||||
AND date_add <= '" . pSQL($dateTo) . " 23:59:59'
|
||||
GROUP BY DATE(date_add)"
|
||||
) ?: [];
|
||||
|
||||
// Abandoned carts: visitors who viewed cart (page_type=5) but NOT order confirmation (page_type=7)
|
||||
$cartRows = $db->executeS(
|
||||
"SELECT DATE(s.date_add) as day, COUNT(DISTINCT s.ip_address) as cnt
|
||||
FROM `{$prefix}mpr_sessions` s
|
||||
JOIN `{$prefix}mpr_page_views` pv ON s.id_session = pv.id_session AND pv.page_type = 5
|
||||
LEFT JOIN `{$prefix}mpr_page_views` pv2 ON s.id_session = pv2.id_session AND pv2.page_type = 7
|
||||
WHERE s.is_bot = 0 AND s.js_verified = 1
|
||||
AND s.date_add >= '" . pSQL($dateFrom) . " 00:00:00'
|
||||
AND s.date_add <= '" . pSQL($dateTo) . " 23:59:59'
|
||||
AND pv2.id_page_view IS NULL
|
||||
GROUP BY DATE(s.date_add)"
|
||||
) ?: [];
|
||||
|
||||
// Index by day
|
||||
$byDay = ['boots' => [], 'downloads' => [], 'carts' => []];
|
||||
foreach ($bootRows as $r) $byDay['boots'][$r['day']] = (int) $r['cnt'];
|
||||
foreach ($dlRows as $r) $byDay['downloads'][$r['day']] = (int) $r['cnt'];
|
||||
foreach ($cartRows as $r) $byDay['carts'][$r['day']] = (int) $r['cnt'];
|
||||
|
||||
// Fill dates
|
||||
$boots = $downloads = $carts = [];
|
||||
$date = new \DateTime($dateFrom);
|
||||
$end = new \DateTime($dateTo);
|
||||
while ($date <= $end) {
|
||||
$key = $date->format('Y-m-d');
|
||||
$ts = $date->getTimestamp();
|
||||
$boots[] = [$ts, $byDay['boots'][$key] ?? 0];
|
||||
$downloads[] = [$ts, $byDay['downloads'][$key] ?? 0];
|
||||
$carts[] = [$ts, $byDay['carts'][$key] ?? 0];
|
||||
$date->modify('+1 day');
|
||||
}
|
||||
|
||||
return [
|
||||
'demo_boots' => $boots,
|
||||
'demo_downloads' => $downloads,
|
||||
'abandoned_carts' => $carts,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get conversion totals for a date range.
|
||||
*/
|
||||
public static function getConversionTotals(string $dateFrom, string $dateTo): array
|
||||
{
|
||||
$data = self::getDailyConversions($dateFrom, $dateTo);
|
||||
$totals = [];
|
||||
foreach ($data as $key => $points) {
|
||||
$totals[$key] = array_sum(array_column($points, 1));
|
||||
}
|
||||
return $totals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get full dashboard payload (for AJAX).
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user