Add backlinks section to the site detail page
Shows inbound links (who links to this site, via Site::inboundLinks()) with the referring site, source page, and anchor text — paginated separately from the Pages table via a distinct page-name query param so both can paginate independently. Also surfaces a simple outbound link count and a "N backlinks from M referring domains" summary. Verified against real data: crawled podcastyradio.es (previously only known as a backlink target from 00podcast.es) and confirmed its detail page correctly shows that inbound link with the right anchor text.
This commit is contained in:
@@ -9,8 +9,22 @@ class SiteController extends Controller
|
||||
{
|
||||
public function show(Site $site): View
|
||||
{
|
||||
$pages = $site->pages()->orderBy('url')->paginate(50);
|
||||
$pages = $site->pages()->orderBy('url')->paginate(50, ['*'], 'pages_page');
|
||||
|
||||
return view('sites.show', ['site' => $site, 'pages' => $pages]);
|
||||
$backlinks = $site->inboundLinks()
|
||||
->with(['site', 'sitePage'])
|
||||
->latest()
|
||||
->paginate(50, ['*'], 'backlinks_page');
|
||||
|
||||
$referringDomainsCount = $site->inboundLinks()->distinct()->count('site_id');
|
||||
$outboundLinksCount = $site->outboundLinks()->count();
|
||||
|
||||
return view('sites.show', [
|
||||
'site' => $site,
|
||||
'pages' => $pages,
|
||||
'backlinks' => $backlinks,
|
||||
'referringDomainsCount' => $referringDomainsCount,
|
||||
'outboundLinksCount' => $outboundLinksCount,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,5 +50,57 @@
|
||||
<div class="mt-4">
|
||||
{{ $pages->links() }}
|
||||
</div>
|
||||
|
||||
<h2 class="mt-10 text-lg font-medium">
|
||||
Backlinks ({{ $backlinks->total() }} from {{ number_format($referringDomainsCount) }} referring {{ \Illuminate\Support\Str::plural('domain', $referringDomainsCount) }})
|
||||
</h2>
|
||||
<p class="mt-1 text-sm text-neutral-500">
|
||||
Also links out to {{ number_format($outboundLinksCount) }} {{ \Illuminate\Support\Str::plural('page', $outboundLinksCount) }} on other domains.
|
||||
</p>
|
||||
|
||||
<div class="mt-4 overflow-hidden rounded-lg border border-neutral-200 dark:border-neutral-800">
|
||||
<table class="min-w-full divide-y divide-neutral-200 dark:divide-neutral-800">
|
||||
<thead class="bg-neutral-50 dark:bg-neutral-900">
|
||||
<tr>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium uppercase tracking-wide text-neutral-500">Referring site</th>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium uppercase tracking-wide text-neutral-500">Source page</th>
|
||||
<th class="px-4 py-2 text-left text-xs font-medium uppercase tracking-wide text-neutral-500">Anchor text</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-neutral-200 dark:divide-neutral-800">
|
||||
@forelse ($backlinks as $backlink)
|
||||
<tr>
|
||||
<td class="px-4 py-2 text-sm">
|
||||
@if ($backlink->site)
|
||||
<a href="{{ route('sites.show', $backlink->site) }}" class="font-medium text-blue-600 hover:underline dark:text-blue-400">
|
||||
{{ $backlink->site->domain }}
|
||||
</a>
|
||||
@else
|
||||
<span class="text-neutral-500">—</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="max-w-md truncate px-4 py-2 text-sm">
|
||||
@if ($backlink->sitePage)
|
||||
<a href="{{ $backlink->sitePage->url }}" target="_blank" rel="noopener" class="text-blue-600 hover:underline dark:text-blue-400">
|
||||
{{ $backlink->sitePage->url }}
|
||||
</a>
|
||||
@else
|
||||
<span class="text-neutral-500">—</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="max-w-xs truncate px-4 py-2 text-sm text-neutral-600 dark:text-neutral-400">{{ $backlink->anchor_text ?? '—' }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="3" class="px-4 py-6 text-center text-sm text-neutral-500">No backlinks found yet.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
{{ $backlinks->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</x-layouts.app>
|
||||
|
||||
Reference in New Issue
Block a user