Deploy Ladill Link / deploy (push) Successful in 32s
Record parsed user-agent and geo data on clicks, then surface breakdowns and richer recent-click context on per-link and account analytics views. Co-authored-by: Cursor <cursoragent@cursor.com>
49 lines
1.2 KiB
PHP
49 lines
1.2 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Support\Link\LinkGeoResolver;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
class LinkClick extends Model
|
|
{
|
|
protected $fillable = [
|
|
'short_link_id',
|
|
'ip_hash',
|
|
'user_agent',
|
|
'referer',
|
|
'device_type',
|
|
'browser',
|
|
'os',
|
|
'country',
|
|
'is_unique',
|
|
'clicked_at',
|
|
];
|
|
|
|
protected $casts = [
|
|
'is_unique' => 'boolean',
|
|
'clicked_at' => 'datetime',
|
|
];
|
|
|
|
public function shortLink(): BelongsTo
|
|
{
|
|
return $this->belongsTo(ShortLink::class);
|
|
}
|
|
|
|
public function contextLabel(): string
|
|
{
|
|
$parts = array_filter([
|
|
$this->device_type ? ucfirst($this->device_type) : null,
|
|
$this->browser,
|
|
$this->os,
|
|
$this->country ? LinkGeoResolver::countryLabel($this->country) : null,
|
|
]);
|
|
|
|
$context = $parts !== [] ? implode(' · ', $parts) : null;
|
|
$referer = $this->referer ? parse_url($this->referer, PHP_URL_HOST) ?: $this->referer : 'Direct';
|
|
|
|
return $context ? "{$context} · via {$referer}" : "via {$referer}";
|
|
}
|
|
}
|