- Add Analytics container: models, tasks, jobs, controllers, routes, services - Add analytics config with section groups (structure, institute, content, services) - Add database tables: analytics_sessions, analytics_hits, analytics_daily_stats - Add frontend: Analytics page, section detail, chart, overview, navigation components - Add consent banner and JS tracking service (sendBeacon + Inertia listener) - Add permission sync for view_analytics, view_any_analytic - Fix trailing slash URL matching in GetNavigationSectionsTask - Fix event propagation on expand arrows in navigation sections - Fix RecordVisitJob to not depend on dropped analytics_geo_cache table - Replace plain text views/visitors with badge-style icons - Group navigation sections by category with separate blocks - Add config-driven non-CMS sections (faculties, divisions, DPO, journals) - Remove Events, TV, Sveden from analytics sections
69 lines
2.0 KiB
PHP
69 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace App\Containers\Analytics\Jobs;
|
|
|
|
use App\Containers\Analytics\Models\AnalyticsHit;
|
|
use App\Containers\Analytics\Models\AnalyticsSession;
|
|
use App\Containers\Analytics\Services\DeviceDetectorService;
|
|
use Illuminate\Bus\Queueable;
|
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
use Illuminate\Foundation\Bus\Dispatchable;
|
|
use Illuminate\Queue\InteractsWithQueue;
|
|
use Illuminate\Queue\SerializesModels;
|
|
|
|
class RecordVisitJob implements ShouldQueue
|
|
{
|
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
|
|
public int $tries = 3;
|
|
|
|
public int $timeout = 15;
|
|
|
|
public function __construct(
|
|
public array $data,
|
|
) {}
|
|
|
|
public function handle(
|
|
DeviceDetectorService $detector,
|
|
): void {
|
|
$userAgent = $this->data['user_agent'] ?? '';
|
|
|
|
if ($detector->isBot($userAgent)) {
|
|
return;
|
|
}
|
|
|
|
$device = $detector->parse($userAgent);
|
|
|
|
$utmParams = array_filter([
|
|
'utm_source' => $this->data['utm_source'] ?? null,
|
|
'utm_medium' => $this->data['utm_medium'] ?? null,
|
|
'utm_campaign' => $this->data['utm_campaign'] ?? null,
|
|
], fn($v) => $v !== null);
|
|
|
|
$session = (new AnalyticsSession())->firstOrCreateSession(
|
|
visitorId: $this->data['visitor_id'],
|
|
ip: $this->data['ip'] ?? '0.0.0.0',
|
|
userId: $this->data['user_id'] ?? null,
|
|
entryPage: $this->data['url'],
|
|
utmParams: $utmParams,
|
|
);
|
|
|
|
if (empty($session->browser)) {
|
|
$session->update([
|
|
'browser' => $device['browser'],
|
|
'os' => $device['os'],
|
|
'device_type' => $device['type'],
|
|
]);
|
|
}
|
|
|
|
AnalyticsHit::create([
|
|
'session_id' => $session->id,
|
|
'user_id' => $this->data['user_id'] ?? null,
|
|
'url' => $this->data['url'],
|
|
'referrer' => $this->data['referrer'] ?? null,
|
|
'title' => $this->data['title'] ?? null,
|
|
'created_at' => now(),
|
|
]);
|
|
}
|
|
}
|