web: Doppelveröffentlichung — Prüfsumme, kanonische Zuordnung (aus bis E9), Quellenauskunft, noindex im Portal (Anhang 2)
Über die API kommt praktisch jede Meldung zweimal, je Portal eine Zeile mit gleichem Text: 9.092 Paare, 53 % des Archivs, bisher jede Fassung self-canonical und in beiden Sitemaps — Google wählte. 1c.7: press_releases.content_hash (SHA-256 über Titel + Text ohne Markup), gesetzt beim Speichern, Bestand per press-releases:hash-content (Query-Builder, Blöcke). Migration in zwei Statements — ADD COLUMN INSTANT, ADD INDEX INPLACE, kein Rebuild. press-releases:duplicates-report zählt Paare je Hauptkategorie. 1c.8: canonical_press_release_id + CanonicalAssigner. Erstquelle folgt der Kategorie (config/canonical.php, Vorschlag zu E9), sonst die zuerst veröffentlichte Fassung. Zuordnung bei jeder Veröffentlichung und über den Bestand (press-releases:assign-canonicals). Die Kopie trägt rel=canonical und mainEntityOfPage auf die Erstquelle; Sitemap und News-Sitemap nennen nur sie; Leser sehen weiterhin beide. Alles hinter CANONICAL_ASSIGNMENT_ENABLED (false), bis E9 entschieden ist. 1c.9: user_canonical in den Index-Prüfungen, sourceVerdict() unterscheidet eigene Adresse / andere eigene Fassung / fremdes Portal; Anzeige im Block „Google-Index" hinter GSC_CUSTOMER_VISIBLE, ohne Aussage über das Warum. Dazu: Abschnitt zur einen Quelle auf /gute-pressemitteilung (Verteiler → viele Kopien, eigene Website zuerst, keine Garantie), noindex in Admin-, Kunden- und Auth-Layouts, UmamiSnippetTest von der lokalen .env gelöst. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
447dc4c61e
commit
ee267c622e
28 changed files with 1231 additions and 11 deletions
|
|
@ -1,6 +1,8 @@
|
|||
@extends('web.layouts.web-master')
|
||||
|
||||
@php
|
||||
use App\Enums\Portal;
|
||||
use App\Services\PressRelease\CanonicalAssigner;
|
||||
use App\Support\StructuredData;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
|
|
@ -89,6 +91,14 @@
|
|||
$shareUrl = $isPreview ? request()->fullUrl() : route('release.detail', ['slug' => $release->slug]);
|
||||
$brandLabel = config('app.theme') === 'presseecho' ? 'presseecho' : 'businessportal24';
|
||||
|
||||
// Doppelveröffentlichung (Anhang 2, 1c.8): rel=canonical zeigt auf die
|
||||
// Erstquelle — die eigene Adresse, oder bei zweiter Fassung/portal=both
|
||||
// das Portal, das laut Kategorie-Zuordnung führt. Geteilt wird weiterhin
|
||||
// die Adresse, auf der der Leser gerade ist.
|
||||
$canonicalUrl = $isPreview
|
||||
? $shareUrl
|
||||
: app(CanonicalAssigner::class)->canonicalUrlFor($release, $brandLabel === 'presseecho' ? Portal::Presseecho : Portal::Businessportal24);
|
||||
|
||||
// SEO: NewsArticle + BreadcrumbList als JSON-LD — nur für die öffentliche
|
||||
// Seite (die Vorschau ist noindex und hat keine stabile URL).
|
||||
$jsonLd = null;
|
||||
|
|
@ -116,7 +126,7 @@
|
|||
'@graph' => [
|
||||
array_filter([
|
||||
'@type' => 'NewsArticle',
|
||||
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $shareUrl],
|
||||
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => $canonicalUrl],
|
||||
'headline' => Str::limit($release->title, 110),
|
||||
'description' => filled($lead) ? $lead : $teaser,
|
||||
'image' => $imageUrl ? [$imageUrl] : null,
|
||||
|
|
@ -160,7 +170,7 @@
|
|||
@if ($isPreview)
|
||||
@section('robots', 'noindex,nofollow')
|
||||
@else
|
||||
@section('canonical', $shareUrl)
|
||||
@section('canonical', $canonicalUrl)
|
||||
|
||||
@section('meta_extra')
|
||||
@if ($publishedAt)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue