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
87558aba4f
commit
4edb915a9a
28 changed files with 1231 additions and 11 deletions
|
|
@ -111,6 +111,7 @@ class IndexStatusChecker
|
|||
'page_fetch_state' => Str::limit((string) ($indexStatus['pageFetchState'] ?? ''), 60, '') ?: null,
|
||||
'last_crawl_time' => ! empty($indexStatus['lastCrawlTime']) ? Carbon::parse((string) $indexStatus['lastCrawlTime']) : null,
|
||||
'google_canonical' => Str::limit((string) ($indexStatus['googleCanonical'] ?? ''), 500, '') ?: null,
|
||||
'user_canonical' => Str::limit((string) ($indexStatus['userCanonical'] ?? ''), 500, '') ?: null,
|
||||
'raw' => $indexStatus,
|
||||
'checked_at' => now(),
|
||||
]);
|
||||
|
|
@ -133,6 +134,37 @@ class IndexStatusChecker
|
|||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Quellenauskunft (Anhang 2, 1c.9): welche Adresse Google als maßgeblich
|
||||
* führt, verglichen mit der eigenen Fassung. Sagt nichts darüber, warum.
|
||||
*
|
||||
* @return array{kind: 'self'|'own_other'|'foreign'|'unknown', url: ?string, host: ?string}
|
||||
*/
|
||||
public function sourceVerdict(PressReleaseIndexCheck $check): array
|
||||
{
|
||||
$google = $check->google_canonical;
|
||||
|
||||
if ($google === null || $google === '') {
|
||||
return ['kind' => 'unknown', 'url' => null, 'host' => null];
|
||||
}
|
||||
|
||||
$normalize = fn (string $url): string => rtrim(strtolower((string) preg_replace('#^https?://(www\.)?#i', '', $url)), '/');
|
||||
$host = strtolower((string) parse_url($google, PHP_URL_HOST));
|
||||
|
||||
if ($normalize($google) === $normalize($check->url)) {
|
||||
return ['kind' => 'self', 'url' => $google, 'host' => $host];
|
||||
}
|
||||
|
||||
$ownHosts = array_filter(array_map(
|
||||
fn (?string $url): string => strtolower((string) parse_url((string) $url, PHP_URL_HOST)),
|
||||
[config('domains.domain_presseecho_url'), config('domains.domain_businessportal_url')],
|
||||
), fn (string $own): bool => $own !== '');
|
||||
|
||||
$isOwn = collect($ownHosts)->contains(fn (string $own): bool => str_ends_with($host, $own) || str_ends_with($own, $host));
|
||||
|
||||
return ['kind' => $isOwn ? 'own_other' : 'foreign', 'url' => $google, 'host' => $host];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Builder<PressRelease>
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue