presseportale/app/Support/StructuredData.php
Kevin Adametz b74f881ac8 web: Entitaeten im JSON-LD verknuepft, News-Sitemap und llms.txt (Roadmap 2.1, 2.2, 2.7)
- App\Support\StructuredData: Portal-Organization als Publisher mit @id
  und Logo (ImageObject), Newsroom-@id; NewsArticle.author auf der
  Meldung und Organization auf der Newsroom-Seite beschreiben jetzt
  dieselbe Entitaet. Startseiten nutzen denselben Publisher.
- /sitemap-news.xml je Spoke (NewsSitemapController): im Archiv
  sichtbare Meldungen der letzten 48 h, max. 1.000, news:publication
  mit Portalname und Sprache; 15 min gecacht, mit den anderen Sitemaps
  geleert; in robots.txt der Spokes. Hub liefert leere Liste.
- /llms.txt je Host (LlmsTxtController): sachliche Beschreibung,
  URL-Aufbau, aktive Kategorien, Seiten fuer Unternehmen, Rechtliches;
  Hub verweist auf beide Portale. Keine Aussagen ueber KI-Nennungen.
- Protokoll Teil 5 (Block 2) inkl. Betreiber-Schritten fuer das
  Publisher Center und Befund zu 2.5/E5; Roadmap 2.1/2.7 abgehakt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 10:15:28 +00:00

53 lines
1.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Support;
/**
* Gemeinsame Entitäten für das JSON-LD der Web-Seiten (Roadmap 2.1):
* das Portal als Publisher mit stabiler `@id` und Logo, der Newsroom als
* Organization mit stabiler `@id`. NewsArticle.author auf der Meldung und
* die Organization auf der Newsroom-Seite zeigen damit auf dieselbe Entität,
* statt zwei namensgleiche Objekte zu sein.
*/
class StructuredData
{
public static function portalBase(?string $domainUrl): string
{
return rtrim($domainUrl ?? (string) config('app.url'), '/');
}
/**
* Portal-Organisation (Publisher der Meldungen) — Name aus der
* Domain-Konfiguration, Logo als ImageObject (600×200-SVG unter /images).
*
* @return array<string, mixed>
*/
public static function publisher(string $portalBase): array
{
$isPresseecho = config('app.theme') === 'presseecho';
$brand = (array) config('domains.domains.'.($isPresseecho ? 'presseecho' : 'businessportal24').'.brand', []);
return [
'@type' => 'Organization',
'@id' => $portalBase.'/#organization',
'name' => ($brand['name'] ?? ($isPresseecho ? 'presse' : 'businessportal')).($brand['accent'] ?? ($isPresseecho ? 'echo' : '24')),
'url' => $portalBase.'/',
'logo' => [
'@type' => 'ImageObject',
'url' => $portalBase.'/images/'.($isPresseecho ? 'presseecho-logo.svg' : 'businessportal-logo.svg'),
'width' => 600,
'height' => 200,
],
];
}
public static function newsroomUrl(string $portalBase, string $slug): string
{
return $portalBase.'/'.app()->getLocale().'/newsroom/'.$slug;
}
public static function newsroomId(string $newsroomUrl): string
{
return $newsroomUrl.'#organization';
}
}