2026-03-18 13:32:36 +02:00
|
|
|
<x-report-layout :website="$website" :from="$from" :to="$to" title="Traffic Sources">
|
|
|
|
|
|
2026-03-19 18:42:19 +02:00
|
|
|
@if ($sources->isEmpty())
|
|
|
|
|
<div class="bg-white rounded-xl border border-gray-200">
|
|
|
|
|
<x-empty-state message="No traffic source data available for this period." />
|
|
|
|
|
</div>
|
|
|
|
|
@else
|
|
|
|
|
@php
|
|
|
|
|
$chartSources = $sources->take(10);
|
|
|
|
|
@endphp
|
|
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl border border-gray-200 p-6 mb-6">
|
|
|
|
|
<h3 class="text-sm font-semibold text-gray-900 mb-4">Top Sources by Sessions</h3>
|
|
|
|
|
<div style="height: 280px;"><canvas id="sources-chart"></canvas></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl border border-gray-200">
|
2026-03-18 13:32:36 +02:00
|
|
|
<div class="overflow-x-auto">
|
|
|
|
|
<table class="min-w-full divide-y divide-gray-200">
|
|
|
|
|
<thead class="bg-gray-50">
|
|
|
|
|
<tr>
|
2026-03-19 18:42:19 +02:00
|
|
|
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Source</th>
|
|
|
|
|
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Sessions</th>
|
|
|
|
|
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Bounce Rate</th>
|
|
|
|
|
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Avg. Duration</th>
|
|
|
|
|
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Pages / Session</th>
|
2026-03-18 13:32:36 +02:00
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody class="divide-y divide-gray-200">
|
|
|
|
|
@foreach ($sources as $row)
|
|
|
|
|
<tr>
|
2026-03-19 18:42:19 +02:00
|
|
|
<td class="px-4 py-2.5 text-sm text-gray-900 font-medium">{{ $row->source }}</td>
|
|
|
|
|
<td class="px-4 py-2.5 text-sm text-gray-900 text-right tabular-nums">{{ number_format($row->sessions) }}</td>
|
|
|
|
|
<td class="px-4 py-2.5 text-sm text-gray-900 text-right tabular-nums">{{ $row->sessions > 0 ? round(($row->bounces / $row->sessions) * 100, 1) : 0 }}%</td>
|
|
|
|
|
<td class="px-4 py-2.5 text-sm text-gray-900 text-right tabular-nums">{{ gmdate('i:s', (int) round($row->avg_duration)) }}</td>
|
|
|
|
|
<td class="px-4 py-2.5 text-sm text-gray-900 text-right tabular-nums">{{ round($row->avg_pages, 1) }}</td>
|
2026-03-18 13:32:36 +02:00
|
|
|
</tr>
|
|
|
|
|
@endforeach
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
</div>
|
2026-03-19 18:42:19 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<x-slot name="scripts">
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js"></script>
|
|
|
|
|
<script>
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
|
|
|
const colors = ['#6366f1', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899', '#14b8a6', '#6366f1', '#10b981', '#f59e0b'];
|
|
|
|
|
const srcData = @json($chartSources->map(fn($s) => ['source' => $s->source, 'sessions' => $s->sessions])->values());
|
|
|
|
|
new Chart(document.getElementById('sources-chart'), {
|
|
|
|
|
type: 'bar',
|
|
|
|
|
data: {
|
|
|
|
|
labels: srcData.map(d => d.source),
|
|
|
|
|
datasets: [{ label: 'Sessions', data: srcData.map(d => d.sessions), backgroundColor: colors, borderRadius: 6 }]
|
|
|
|
|
},
|
|
|
|
|
options: {
|
|
|
|
|
indexAxis: 'y',
|
|
|
|
|
responsive: true,
|
|
|
|
|
maintainAspectRatio: false,
|
|
|
|
|
plugins: {
|
|
|
|
|
legend: { display: false },
|
|
|
|
|
tooltip: { backgroundColor: 'rgba(17,24,39,0.95)', padding: 10, cornerRadius: 8 }
|
|
|
|
|
},
|
|
|
|
|
scales: {
|
|
|
|
|
x: { beginAtZero: true, grid: { color: 'rgba(0,0,0,0.04)' } },
|
|
|
|
|
y: { grid: { display: false } }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
</x-slot>
|
|
|
|
|
@endif
|
2026-03-18 13:32:36 +02:00
|
|
|
|
|
|
|
|
</x-report-layout>
|