Files
ntspi-app/app/Containers/Analytics/Jobs/RecordVisitJob.php
T
F4ilji d6c0f48d48 feat(analytics): add site analytics with grouped navigation sections
- 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
2026-09-18 22:18:04 +05:00

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(),
]);
}
}