{{-- Advertiser dashboard (all campaigns, or one). $d = Dashboards::advertiser(); $csv = download link. --}} @php use App\Support\Charts; $range = $d['range']; $pct = fn ($a, $b) => $b > 0 ? number_format($a / $b * 100, 2).'%' : '–'; $hoursTable = fn (array $h, string $noun) => ['head' => ['Hour (US Eastern)', ucfirst($noun)], 'rows' => array_map(fn ($k, $v) => [Charts::hour($k), number_format($v)], array_keys($h), $h)]; @endphp @include('charts.range', ['range' => $range, 'csv' => $csv ?? null]) @include('charts.kpis', ['tiles' => $d['kpis']])
@include('dash._trend', ['series' => $d['series'], 'range' => $range, 'title' => 'Over time'])

Time of day

@include('charts.columns', ['values' => $d['hours']['views'], 'noun' => 'views'])

US Eastern time.

@include('dash._table', ['table' => $hoursTable($d['hours']['views'], 'views')])

Devices

@include('charts.bars', ['rows' => array_map(fn ($r) => $r + ['note' => number_format($r['clicks']).' clicks · '.$pct($r['clicks'], $r['n'])], $d['devices'])])

Where people saw it

Views by state. Places come from each visitor's network address; the address itself is never stored. Places with fewer than {{ $d['min'] }} views are grouped together.

@include('charts.usmap', ['values' => $d['states'], 'noun' => 'views', 'min' => $d['min']])
@php $known = array_values(array_filter($d['stateRows'], fn ($r) => empty($r['muted']))); $restRows = array_merge(array_slice($known, 10), array_values(array_filter($d['stateRows'], fn ($r) => ! empty($r['muted'])))); $list = array_slice($known, 0, 10); if ($restRows) { $list[] = ['label' => count($known) > 10 ? 'Everywhere else' : 'Other places and unknown', 'n' => array_sum(array_column($restRows, 'n')), 'clicks' => array_sum(array_column($restRows, 'clicks')), 'spend' => array_sum(array_column($restRows, 'spend')), 'muted' => true]; } @endphp @include('charts.bars', ['rows' => array_map(fn ($r) => $r + ['note' => number_format($r['clicks']).' clicks · '.Charts::money($r['spend'])], $list)])
@include('dash._table', ['table' => ['head' => ['Place', 'Views', 'Clicks', 'Click rate', 'Spend'], 'rows' => array_map(fn ($r) => [$r['label'], number_format($r['n']), number_format($r['clicks']), $pct($r['clicks'], $r['n']), Charts::money($r['spend'])], $d['stateRows'])]])

Where on the site

Slot 1 is the first sponsored row in a page of job results.

@include('charts.bars', ['rows' => array_map(fn ($r) => $r + ['note' => number_format($r['clicks']).' clicks · '.$pct($r['clicks'], $r['n']).' · '.Charts::money($r['spend'])], $d['placements'])]) @include('dash._table', ['table' => ['head' => ['Placement', 'Views', 'Clicks', 'Click rate', 'Spend'], 'rows' => array_map(fn ($r) => [$r['label'], number_format($r['n']), number_format($r['clicks']), $pct($r['clicks'], $r['n']), Charts::money($r['spend'])], $d['placements'])]])
@if ($d['since'])

Views, clicks and spend are exactly what was counted and charged. Breakdowns by place, device, time of day and position start {{ $d['since'] }}, and update every 10 minutes.

@endif