Analytics administration dashboard
* Page-view tracking * Unique visitor and session metrics * Content-view events * Search analytics * Conversion tracking * Form-submission events * Commerce events * Site-aware analytics * Privacy-conscious visitor hashing * Optional IP anonymisation * Do Not Track support * Configurable excluded paths * Daily metric aggregation * Top-page reporting * Recent-event activity * Report definitions * Scheduled report foundation * CSV and JSON report formats * Report execution history schema * Analytics retention and pruning * Administration navigation * Analytics permissions * Module registration * Feature test
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace Modules\Analytics\Services;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Modules\Analytics\Models\AnalyticsEvent;
|
||||
use Modules\Analytics\Models\DailyMetric;
|
||||
final class AnalyticsAggregator
|
||||
{
|
||||
public function aggregate(?string $date=null): int
|
||||
{
|
||||
$date=$date ?: now()->subHour()->toDateString(); $written=0;
|
||||
$base=AnalyticsEvent::query()->whereDate('occurred_at',$date);
|
||||
foreach ($base->clone()->select('site_id')->distinct()->pluck('site_id') as $siteId) {
|
||||
$query=$base->clone()->where('site_id',$siteId);
|
||||
$metrics=[
|
||||
['page_views','all',$query->clone()->where('event_type','page_view')->count()],
|
||||
['visitors','all',$query->clone()->whereNotNull('visitor_hash')->distinct('visitor_hash')->count('visitor_hash')],
|
||||
['sessions','all',$query->clone()->whereNotNull('session_hash')->distinct('session_hash')->count('session_hash')],
|
||||
['conversions','all',$query->clone()->where('event_type','conversion')->count()],
|
||||
['searches','all',$query->clone()->where('event_type','search')->count()],
|
||||
];
|
||||
foreach ($metrics as [$metric,$dimension,$value]) {
|
||||
DailyMetric::updateOrCreate(['site_id'=>$siteId,'metric_date'=>$date,'metric'=>$metric,'dimension'=>$dimension],['value'=>$value]); $written++;
|
||||
}
|
||||
}
|
||||
return $written;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace Modules\Analytics\Services;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
use Modules\Analytics\Models\AnalyticsEvent;
|
||||
final class AnalyticsTracker
|
||||
{
|
||||
public function track(Request $request, array $payload): ?AnalyticsEvent
|
||||
{
|
||||
if (!config('analytics.enabled')) return null;
|
||||
if (config('analytics.respect_dnt') && $request->header('DNT') === '1') return null;
|
||||
$path=ltrim((string)($payload['path'] ?? ''), '/');
|
||||
foreach (config('analytics.exclude_paths',[]) as $excluded) if ($excluded !== '' && str_starts_with($path, trim($excluded,'/'))) return null;
|
||||
$ip=(string)$request->ip();
|
||||
return AnalyticsEvent::create([
|
||||
'event_id'=>(string)Str::uuid(), 'site_id'=>app()->bound('currentSite') ? app('currentSite')?->id : null,
|
||||
'event_type'=>$payload['event_type'] ?? 'page_view', 'path'=>'/'.$path, 'title'=>$payload['title'] ?? null,
|
||||
'referrer'=>$payload['referrer'] ?? $request->headers->get('referer'),
|
||||
'visitor_hash'=>hash('sha256', (string)($payload['visitor_id'] ?? $request->cookie('analytics_visitor','guest'))),
|
||||
'session_hash'=>hash('sha256', (string)($payload['session_id'] ?? $request->session()->getId())),
|
||||
'ip_hash'=>config('analytics.anonymize_ip') ? hash('sha256',$ip.config('app.key')) : $ip,
|
||||
'device_type'=>$payload['device_type'] ?? null, 'browser'=>$payload['browser'] ?? null,
|
||||
'operating_system'=>$payload['operating_system'] ?? null, 'subject_type'=>$payload['subject_type'] ?? null,
|
||||
'subject_id'=>$payload['subject_id'] ?? null, 'properties'=>$payload['properties'] ?? [], 'occurred_at'=>now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user