feat: implement structured data support for blog and page components, enhancing SEO and user experience through JSON-LD integration
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
abstract class StructuredData
|
||||
{
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $graph
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function wrap(array $graph): array
|
||||
{
|
||||
return [
|
||||
'@context' => 'https://schema.org',
|
||||
'@graph' => array_values($graph),
|
||||
];
|
||||
}
|
||||
|
||||
protected static function siteUrl(): string
|
||||
{
|
||||
return url('/');
|
||||
}
|
||||
|
||||
protected static function siteName(): string
|
||||
{
|
||||
return (string) setting('site_name', config('app.name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function websiteNode(?string $searchUrlTemplate = null): array
|
||||
{
|
||||
$siteUrl = static::siteUrl();
|
||||
$siteName = static::siteName();
|
||||
|
||||
$node = [
|
||||
'@type' => 'WebSite',
|
||||
'@id' => $siteUrl . '#website',
|
||||
'url' => $siteUrl,
|
||||
'name' => $siteName,
|
||||
'inLanguage' => app()->getLocale(),
|
||||
'publisher' => ['@id' => $siteUrl . '#organization'],
|
||||
];
|
||||
|
||||
if ($searchUrlTemplate) {
|
||||
$node['potentialAction'] = [
|
||||
'@type' => 'SearchAction',
|
||||
'target' => [
|
||||
'@type' => 'EntryPoint',
|
||||
'urlTemplate' => $searchUrlTemplate,
|
||||
],
|
||||
'query-input' => 'required name=search_term_string',
|
||||
];
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function organizationNode(): array
|
||||
{
|
||||
$siteUrl = static::siteUrl();
|
||||
$siteName = static::siteName();
|
||||
|
||||
$node = [
|
||||
'@type' => 'Organization',
|
||||
'@id' => $siteUrl . '#organization',
|
||||
'name' => $siteName,
|
||||
'url' => $siteUrl,
|
||||
];
|
||||
|
||||
$logo = setting('site_logo');
|
||||
if ($logo) {
|
||||
$logoUrl = str_starts_with($logo, 'http') ? $logo : asset('storage/' . ltrim($logo, '/'));
|
||||
$node['logo'] = [
|
||||
'@type' => 'ImageObject',
|
||||
'url' => $logoUrl,
|
||||
];
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array{name: string, item: string}> $items
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function breadcrumbNode(string $pageUrl, array $items): array
|
||||
{
|
||||
$elements = [];
|
||||
|
||||
foreach ($items as $index => $item) {
|
||||
$elements[] = [
|
||||
'@type' => 'ListItem',
|
||||
'position' => $index + 1,
|
||||
'name' => $item['name'],
|
||||
'item' => $item['item'],
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'@type' => 'BreadcrumbList',
|
||||
'@id' => $pageUrl . '#breadcrumb',
|
||||
'itemListElement' => $elements,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $extra
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function webPageNode(
|
||||
string $pageUrl,
|
||||
string $name,
|
||||
?string $description = null,
|
||||
array $extra = [],
|
||||
): array {
|
||||
$node = array_merge([
|
||||
'@type' => 'WebPage',
|
||||
'@id' => $pageUrl . '#webpage',
|
||||
'url' => $pageUrl,
|
||||
'name' => $name,
|
||||
'inLanguage' => app()->getLocale(),
|
||||
'isPartOf' => ['@id' => static::siteUrl() . '#website'],
|
||||
'breadcrumb' => ['@id' => $pageUrl . '#breadcrumb'],
|
||||
], $extra);
|
||||
|
||||
if ($description) {
|
||||
$node['description'] = $description;
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function listItem(int $position, array $item): array
|
||||
{
|
||||
return [
|
||||
'@type' => 'ListItem',
|
||||
'position' => $position,
|
||||
'item' => $item,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user