Analytics
{{ number_format($onlineNow) }}
online now (last 5 min)
First-party traffic data. Visitor IPs are only ever stored as one-way hashes,
so “visitors” is a close estimate rather than an exact count.
@foreach($ranges as $value => $label)
{{ $label }}
@endforeach
{{-- --- Summary tiles ------------------------------------------------- --}}
@php
$tiles = [
['label' => 'Page views', 'value' => number_format($summary['views']), 'note' => $summary['views_change'] === null ? 'No earlier data to compare' : ($summary['views_change'] >= 0 ? '+' : '').$summary['views_change'].'% vs previous period'],
['label' => 'Visitors', 'value' => number_format($summary['visitors']), 'note' => 'Distinct hashed visitors'],
['label' => 'Pages per visitor', 'value' => $summary['views_per_visitor'], 'note' => 'Average over the period'],
['label' => 'Enquiries', 'value' => number_format($messageStats['range']), 'note' => $messageStats['unread'].' unread'],
];
@endphp
@foreach($tiles as $tile)
{{ $tile['label'] }}
{{ $tile['value'] }}
{{ $tile['note'] }}
@endforeach
{{-- --- Traffic over time --------------------------------------------- --}}
Traffic over time
@if($dailySeries->sum('views') === 0)
No visits recorded yet in this period.
@else
{{-- A CSS bar chart rather than a charting library: it is a single
series of counts, and adding a JS chart dependency to the admin
bundle for this would cost more than the feature is worth
(PRD 2.12 — no heavy dependencies where CSS suffices). --}}
@foreach($dailySeries as $day)
@endforeach
{{ $dailySeries->first()['label'] }}
Peak: {{ number_format($peak) }} views/day
{{ $dailySeries->last()['label'] }}
@endif
{{-- --- Top pages -------------------------------------------------- --}}
Top pages
@if($topPages->isEmpty())
No data yet.
@else
| Path | Views | Visitors |
@foreach($topPages as $page)
/{{ ltrim($page->path, '/') }} |
{{ number_format($page->views) }} |
{{ number_format($page->visitors) }} |
@endforeach
@endif
{{-- --- Traffic sources -------------------------------------------- --}}
Traffic sources
@if($topSources->isEmpty())
No data yet.
@else
| Source | Views |
@foreach($topSources as $source)
| {{ $source['label'] }} |
{{ number_format($source['views']) }} |
@endforeach
@endif
{{-- --- Where visitors come from -------------------------------------- --}}
Top countries
@if($countries->isEmpty())
@if(! $locationTracked)
No location data yet. Put the site behind Cloudflare (free) so the visitor's country header is sent, then new visits will appear here.
@else
No data yet.
@endif
@else
| Country | Views | Visitors |
@foreach($countries as $country)
| {{ $country['flag'] }} {{ $country['name'] }} |
{{ number_format($country['views']) }} |
{{ number_format($country['visitors']) }} |
@endforeach
@endif
Top cities
@if($cities->isEmpty())
No city data yet. In Cloudflare enable Rules → Managed Transforms → “Add visitor location headers”.
@else
| City | Views | Visitors |
@foreach($cities as $city)
| {{ $city['city'] }}@if($city['country']) , {{ $city['country'] }}@endif |
{{ number_format($city['views']) }} |
{{ number_format($city['visitors']) }} |
@endforeach
@endif
{{-- --- Devices + browsers ------------------------------------------ --}}
@foreach([['Devices', $devices], ['Browsers', $browsers]] as [$heading, $rows])
{{ $heading }}
@if($rows->isEmpty())
No data yet.
@else
@foreach($rows as $row)
{{ $row['label'] }}
{{ $row['percentage'] }}%
@endforeach
@endif
@endforeach
{{-- --- Most-read content ------------------------------------------ --}}
Most-read articles
@if($popularArticles->isEmpty())
No articles published yet.
@else
@foreach($popularArticles as $article)
-
{{ Str::limit($article->title, 52) }}
— {{ number_format($article->views_count) }} views
@endforeach
@endif
Most-viewed projects
@if($popularProjects->isEmpty())
No projects published yet.
@else
@foreach($popularProjects as $project)
-
{{ Str::limit($project->title, 52) }}
— {{ number_format($project->views_count) }} views
@endforeach
@endif
{{-- --- Enquiries -------------------------------------------------- --}}
Enquiries
@foreach([
'Today' => $messageStats['today'],
'This period' => $messageStats['range'],
'Unread' => $messageStats['unread'],
'Replied' => $messageStats['replied'],
'Archived' => $messageStats['archived'],
] as $label => $value)
{{ $label }}
{{ number_format($value) }}
@endforeach
Open inbox