first commit from hostslim

This commit is contained in:
2026-03-24 21:12:21 +01:00
commit 20fee7784c
252 changed files with 27385 additions and 0 deletions
+209
View File
@@ -0,0 +1,209 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Concerns\ParsesDateRange;
use App\Models\Website;
use App\Services\AnalyticsQueryService;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;
class ExportController extends Controller
{
use ParsesDateRange;
public function export(Request $request, Website $website, string $report): StreamedResponse
{
$this->authorize('view', $website);
[$from, $to] = $this->parseDateRange($request);
$service = AnalyticsQueryService::for($website, $from, $to);
[$headers, $rows] = match ($report) {
'pages' => $this->pagesExport($service),
'landing-pages' => $this->landingPagesExport($service),
'exit-pages' => $this->exitPagesExport($service),
'sources' => $this->sourcesExport($service),
'referrers' => $this->referrersExport($service),
'campaigns' => $this->campaignsExport($service),
'events' => $this->eventsExport($service),
'countries' => $this->countriesExport($service),
'browsers' => $this->browsersExport($service),
'languages' => $this->languagesExport($service),
'summary' => $this->summaryExport($service, $from, $to),
default => abort(404, 'Unknown report type.'),
};
$filename = "{$website->domain}_{$report}_{$from->format('Y-m-d')}_to_{$to->format('Y-m-d')}.csv";
return $this->streamCsv($filename, $headers, $rows);
}
private function streamCsv(string $filename, array $headers, iterable $rows): StreamedResponse
{
return response()->streamDownload(function () use ($headers, $rows) {
$handle = fopen('php://output', 'w');
fputcsv($handle, $headers);
foreach ($rows as $row) {
fputcsv($handle, $row);
}
fclose($handle);
}, $filename, [
'Content-Type' => 'text/csv',
]);
}
private function pagesExport(AnalyticsQueryService $service): array
{
$data = $service->topPages(500);
return [
['Path', 'Views', 'Unique Views', 'Avg Time on Page (s)'],
$data->map(fn ($r) => [
$r->path,
$r->views,
$r->unique_views,
round($r->avg_time ?? 0, 1),
]),
];
}
private function landingPagesExport(AnalyticsQueryService $service): array
{
$data = $service->landingPages(500);
return [
['Path', 'Entrances', 'Bounce Rate (%)'],
$data->map(fn ($r) => [
$r->entry_page ?? $r->path ?? '—',
$r->entrances ?? $r->sessions ?? 0,
$r->bounce_rate ?? 0,
]),
];
}
private function exitPagesExport(AnalyticsQueryService $service): array
{
$data = $service->exitPages(500);
return [
['Path', 'Exits'],
$data->map(fn ($r) => [
$r->exit_page ?? $r->path ?? '—',
$r->exits ?? 0,
]),
];
}
private function sourcesExport(AnalyticsQueryService $service): array
{
$data = $service->trafficSources(500);
return [
['Source', 'Sessions', 'Bounces', 'Avg Duration (s)', 'Avg Pages'],
$data->map(fn ($r) => [
$r->source,
$r->sessions,
$r->bounces,
round($r->avg_duration ?? 0, 1),
round($r->avg_pages ?? 0, 1),
]),
];
}
private function referrersExport(AnalyticsQueryService $service): array
{
$data = $service->referrers(500);
return [
['Referrer Domain', 'Sessions', 'Bounces', 'Avg Duration (s)'],
$data->map(fn ($r) => [
$r->referrer_domain,
$r->sessions,
$r->bounces,
round($r->avg_duration ?? 0, 1),
]),
];
}
private function campaignsExport(AnalyticsQueryService $service): array
{
$data = $service->campaigns(500);
return [
['UTM Source', 'UTM Medium', 'UTM Campaign', 'Sessions', 'Bounces', 'Avg Duration (s)'],
$data->map(fn ($r) => [
$r->utm_source,
$r->utm_medium,
$r->utm_campaign,
$r->sessions,
$r->bounces,
round($r->avg_duration ?? 0, 1),
]),
];
}
private function eventsExport(AnalyticsQueryService $service): array
{
$data = $service->eventsOverview(500);
return [
['Event Name', 'Category', 'Total', 'Unique Visitors', 'Total Value'],
$data->map(fn ($r) => [
$r->name,
$r->category,
$r->total,
$r->unique_visitors,
$r->total_value,
]),
];
}
private function countriesExport(AnalyticsQueryService $service): array
{
$data = $service->visitorsByCountry(500);
return [
['Country', 'Visitors'],
$data->map(fn ($r) => [$r->country, $r->visitors]),
];
}
private function browsersExport(AnalyticsQueryService $service): array
{
$data = $service->visitorsByBrowser(100);
return [
['Browser', 'Visitors'],
$data->map(fn ($r) => [$r->browser, $r->visitors]),
];
}
private function languagesExport(AnalyticsQueryService $service): array
{
$data = $service->visitorsByLanguage(100);
return [
['Language', 'Visitors'],
$data->map(fn ($r) => [$r->language, $r->visitors]),
];
}
private function summaryExport(AnalyticsQueryService $service, $from, $to): array
{
$summary = $service->summary();
return [
['Metric', 'Value'],
collect([
['Period', $from->format('Y-m-d') . ' to ' . $to->format('Y-m-d')],
['Page Views', $summary['page_views']],
['Unique Visitors', $summary['visitors']],
['Sessions', $summary['sessions']],
['Bounce Rate (%)', $summary['bounce_rate']],
['Avg Duration (s)', $summary['avg_duration']],
['Pages / Session', $summary['avg_pages']],
]),
];
}
}