Antworten auf 0100/0102/0104/0108-FE: Canonical paginierter Listen, JSON-LD-Breadcrumb auf den Datensatz, Story-Liste ohne crops, Startseiten-Daten
VitecMetaHandler: /insights/news?page=2 (und ?category=) bekommt einen selbstreferenzierenden Canonical statt Seite 1 (0100-FE 5.1). PageJsonLdRenderer: auf Produkt-, News- und Story-Detailseiten ersetzt der Datensatz (Titel + URL) die Shell-Seite als letztes Breadcrumb- Element (0108-FE F11). UsecaseListJsonRenderer: cardImage.crops aus den Listen-Karten entfernt, ~20 kB pro Seite mit Testimonial-Band (0102-FE 5). Migration fe_answers_fixes_20261111 (angewendet): Platzhalter 'H1 Header' (/solutions) und 'Featured Product' (Startseite, Lorem ipsum, CTA auf /product) versteckt; Karte 'Government' auf /markets/government; Button in #699 'Explore our solutions'; Story CDC h4 'Product Highlight' -> h3 (0104-FE 4.1). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
5824981e2b
commit
07f74e372b
4 files changed
+189
-3
No files matched your search
@@ -78,8 +78,17 @@ final class PageJsonLdRenderer
|
||||
$nodes[] = $service->buildWebSite($base, $siteName, $hasOrganization);
|
||||
}
|
||||
|
||||
// BreadcrumbList from the rootline.
|
||||
$breadcrumb = $service->buildBreadcrumbList($this->breadcrumbItems($rootLine), $base);
|
||||
// BreadcrumbList from the rootline. On record detail pages the last
|
||||
// crumb is the generic shell page ("Story", "Product", "Article")
|
||||
// and is swapped for the record itself (0108-FE, F11).
|
||||
$args = $this->routeArguments($request);
|
||||
$crumbs = $this->breadcrumbItems($rootLine);
|
||||
$recordCrumb = $this->recordCrumb($args);
|
||||
if ($recordCrumb !== null && $crumbs !== []) {
|
||||
array_pop($crumbs);
|
||||
$crumbs[] = $recordCrumb;
|
||||
}
|
||||
$breadcrumb = $service->buildBreadcrumbList($crumbs, $base);
|
||||
if ($breadcrumb !== null) {
|
||||
$nodes[] = $breadcrumb;
|
||||
}
|
||||
@@ -113,7 +122,6 @@ final class PageJsonLdRenderer
|
||||
|
||||
|
||||
// Product on product detail pages (routed record, SEO audit 2026-11-09).
|
||||
$args = $this->routeArguments($request);
|
||||
$productArg = (string)($args['tx_vitec_productshow']['product'] ?? '');
|
||||
if ($productArg !== '') {
|
||||
$productRow = $this->fetchDetailRecord(
|
||||
@@ -220,6 +228,40 @@ final class PageJsonLdRenderer
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Breadcrumb item for the routed detail record (product, news, story), or
|
||||
* null on plain pages.
|
||||
*
|
||||
* @param array<string,mixed> $args
|
||||
* @return array{name:string, url:string}|null
|
||||
*/
|
||||
private function recordCrumb(array $args): ?array
|
||||
{
|
||||
$productArg = (string)($args['tx_vitec_productshow']['product'] ?? '');
|
||||
if ($productArg !== '') {
|
||||
$row = $this->fetchDetailRecord('tx_vitec_domain_model_product', is_numeric($productArg) ? 'uid' : 'slug', $productArg);
|
||||
if ($row !== null && (string)($row['slug'] ?? '') !== '') {
|
||||
return ['name' => (string)($row['title'] ?? ''), 'url' => '/product/' . $row['slug']];
|
||||
}
|
||||
}
|
||||
$newsUid = (int)($args['tx_news_pi1']['news'] ?? 0);
|
||||
if ($newsUid > 0) {
|
||||
$row = $this->fetchDetailRecord('tx_news_domain_model_news', 'uid', (string)$newsUid);
|
||||
if ($row !== null && (string)($row['path_segment'] ?? '') !== '') {
|
||||
$name = trim((string)($row['alternative_title'] ?? '')) ?: (string)($row['title'] ?? '');
|
||||
return ['name' => $name, 'url' => '/news/article/' . $row['path_segment']];
|
||||
}
|
||||
}
|
||||
$usecaseUid = (int)($args['tx_vitec_usecaseshow']['usecase'] ?? 0);
|
||||
if ($usecaseUid > 0) {
|
||||
$row = $this->fetchDetailRecord('tx_vitec_domain_model_usecase', 'uid', (string)$usecaseUid);
|
||||
if ($row !== null && (string)($row['slug'] ?? '') !== '') {
|
||||
return ['name' => (string)($row['title'] ?? ''), 'url' => '/success-stories/' . $row['slug']];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build ordered breadcrumb items (root → current) from the rootline.
|
||||
* Skips spacers, folders and recyclers; uses nav_title with title fallback.
|
||||
|
||||
Reference in new issue
Block a user