buildPayload( $joinToken, $eventType, $request, $context, $providedToken, $httpStatus )); } catch (\Throwable $exception) { // Never block the main request if analytics fails report($exception); } } private function buildPayload( ?EventJoinToken $joinToken, string $eventType, Request $request, array $context, ?string $providedToken, ?int $httpStatus ): array { $route = $request->route(); $routeName = $route ? $route->getName() : null; $deviceId = (string) $request->header('X-Device-Id', $request->input('device_id', '')); $deviceId = $deviceId !== '' ? substr(preg_replace('/[^a-zA-Z0-9_-]/', '', $deviceId), 0, 64) : null; $tokenHash = null; $tokenPreview = null; if ($joinToken) { $tokenHash = $joinToken->token_hash ?? null; $tokenPreview = $joinToken->token_preview ?? null; } elseif ($providedToken) { $tokenHash = hash('sha256', $providedToken); $tokenPreview = $this->buildPreview($providedToken); } $eventId = $joinToken?->event_id; $tenantId = null; if ($joinToken && $joinToken->relationLoaded('event')) { $tenantId = $joinToken->event?->tenant_id; } elseif ($joinToken) { $tenantId = $joinToken->event()->value('tenant_id'); } return [ 'event_join_token_id' => $joinToken?->getKey(), 'event_id' => $eventId, 'tenant_id' => $tenantId, 'token_hash' => $tokenHash, 'token_preview' => $tokenPreview, 'event_type' => $eventType, 'route' => $routeName, 'http_method' => $request->getMethod(), 'http_status' => $httpStatus, 'device_id' => $deviceId, 'ip_address' => $request->ip(), 'user_agent' => $this->shortenUserAgent($request->userAgent()), 'context' => $context ?: null, 'occurred_at' => now(), ]; } private function shortenUserAgent(?string $userAgent): ?string { if ($userAgent === null) { return null; } if (Str::length($userAgent) > 1024) { return Str::substr($userAgent, 0, 1024); } return $userAgent; } private function buildPreview(string $token): string { $token = trim($token); $length = Str::length($token); if ($length <= 10) { return $token; } return Str::substr($token, 0, 6).'…'.Str::substr($token, -4); } }