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).
|
* Get full dashboard payload (for AJAX).
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user