'Overview', 'artists' => 'Artists', 'tracks' => 'Tracks', ]; $activeTabLabel = $tabLabels[$tab] ?? 'Overview'; $overviewGross = (float)($overview['gross_revenue'] ?? 0); $overviewRefunded = (float)($overview['refunded_revenue'] ?? 0); $overviewNet = (float)($overview['net_revenue'] ?? 0); $overviewNetAfterFees = (float)($overview['net_after_fees'] ?? 0); $selectedFrom = (string)($filters['from'] ?? ''); $selectedTo = (string)($filters['to'] ?? ''); $selectedArtistId = (int)($filters['artist_id'] ?? 0); $selectedQuery = (string)($filters['q'] ?? ''); $today = new DateTimeImmutable('today'); $monthStart = $today->modify('first day of this month'); $monthEnd = $today->modify('last day of this month'); $lastMonthStart = $monthStart->modify('-1 month'); $lastMonthEnd = $monthStart->modify('-1 day'); $quarter = (int)floor((((int)$today->format('n')) - 1) / 3); $quarterStartMonth = ($quarter * 3) + 1; $quarterStart = new DateTimeImmutable($today->format('Y') . '-' . str_pad((string)$quarterStartMonth, 2, '0', STR_PAD_LEFT) . '-01'); $lastQuarterEnd = $quarterStart->modify('-1 day'); $lastQuarterStartMonth = (int)$lastQuarterEnd->format('n') - (((int)$lastQuarterEnd->format('n') - 1) % 3); $lastQuarterStart = new DateTimeImmutable($lastQuarterEnd->format('Y') . '-' . str_pad((string)$lastQuarterStartMonth, 2, '0', STR_PAD_LEFT) . '-01'); $quickRanges = [ '7d' => ['label' => 'Last 7 days', 'from' => $today->modify('-6 days')->format('Y-m-d'), 'to' => $today->format('Y-m-d')], '30d' => ['label' => 'Last 30 days', 'from' => $today->modify('-29 days')->format('Y-m-d'), 'to' => $today->format('Y-m-d')], 'month' => ['label' => 'This month', 'from' => $monthStart->format('Y-m-d'), 'to' => $monthEnd->format('Y-m-d')], 'last-month' => ['label' => 'Last month', 'from' => $lastMonthStart->format('Y-m-d'), 'to' => $lastMonthEnd->format('Y-m-d')], 'quarter' => ['label' => 'This quarter', 'from' => $quarterStart->format('Y-m-d'), 'to' => $today->format('Y-m-d')], 'last-quarter' => ['label' => 'Last quarter', 'from' => $lastQuarterStart->format('Y-m-d'), 'to' => $lastQuarterEnd->format('Y-m-d')], 'ytd' => ['label' => 'Year to date', 'from' => $today->format('Y') . '-01-01', 'to' => $today->format('Y-m-d')], ]; $activeRangeLabel = 'Custom range'; foreach ($quickRanges as $range) { if ($selectedFrom === $range['from'] && $selectedTo === $range['to']) { $activeRangeLabel = $range['label']; break; } } $artistExportUrl = '/admin/store/reports/export?type=artists' . '&from=' . rawurlencode($selectedFrom) . '&to=' . rawurlencode($selectedTo) . '&artist_id=' . $selectedArtistId . '&q=' . rawurlencode($selectedQuery); $trackExportUrl = '/admin/store/reports/export?type=tracks' . '&from=' . rawurlencode($selectedFrom) . '&to=' . rawurlencode($selectedTo) . '&artist_id=' . $selectedArtistId . '&q=' . rawurlencode($selectedQuery); $exportUrl = '/admin/store/reports/export?type=' . ($tab === 'tracks' ? 'tracks' : 'artists') . '&from=' . rawurlencode($selectedFrom) . '&to=' . rawurlencode($selectedTo) . '&artist_id=' . $selectedArtistId . '&q=' . rawurlencode($selectedQuery); ob_start(); ?>
Store Analytics

Sales Reports

Revenue, allocations, and performance reporting across orders, artists, releases, and tracks.

Current View
Back to Store
Reporting tables are not ready. Initialize the Store plugin first so allocation and reporting tables exist.
Reporting Period
$range): ?>
Reset
Before Fees Total sales before processor fees.
After Fees Total sales after captured PayPal fees.

Top Artists

Best performing artist allocations for the selected period.

Net After Fees
No artist sales in this period. Try widening the date range or clearing the artist filter.
$row): ?>
sold / paid orders / releases

Top Tracks

Derived track performance from direct, release, and bundle allocations.

Net After Fees
No track sales in this period. Track-level allocations appear once paid orders exist in the selected range.
$row): ?>
/

Artist Ledger

Grouped artist performance with paid orders, units, refunds, captured fees, and net after fees.

rows
No artist sales found. Try widening the date range or clearing the artist filter.
releases / direct tracks
Paid Orders
Units
Refunded Units
Gross
Refunded
PayPal Fees
Net After Fees

Track Ledger

Track-level breakdown derived from direct sales, release sales, bundle allocations, and captured PayPal fees.

rows
No track sales found. Track metrics will populate once paid orders exist in the selected range.
/
Sold
Refunded Units
Downloads
Gross
Refunded
PayPal Fees
Net After Fees