aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/components/ScheduleInteractive.astro
diff options
context:
space:
mode:
authorYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-11-01 21:53:47 +0900
committerYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-11-01 21:53:47 +0900
commit9a48acc5eeab8f79062dc34a02b5ec292ebdf555 (patch)
tree03a8b28c75e335f5bde7aa0ef62ce4e829e96306 /src/components/ScheduleInteractive.astro
parent6de625ae9fdc1d19d9aa3908fd5ebdcc4a2aa359 (diff)
hp-archive: 行事予定ページのSEOを改善
- タイトルと説明文に「行事予定」「傍聴」を追加 - CollectionPage とイベントの ItemList の構造化データを出力 - 最終更新日をページ冒頭に表示 - 案内ページのリンクカードの文言を具体化
Diffstat (limited to 'src/components/ScheduleInteractive.astro')
-rw-r--r--src/components/ScheduleInteractive.astro54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/components/ScheduleInteractive.astro b/src/components/ScheduleInteractive.astro
index cb33ce9..129b38a 100644
--- a/src/components/ScheduleInteractive.astro
+++ b/src/components/ScheduleInteractive.astro
@@ -529,6 +529,59 @@
});
}
+ // 検索エンジン向けに、これからのイベントを構造化データ(JSON-LD)で出力する。
+ function emitEventStructuredData() {
+ const upcoming = entries
+ .filter((e) => e.type === 'event' && e.dates.some((d) => d >= todayKey))
+ .map((e) => {
+ const future = e.dates.filter((d) => d >= todayKey).sort();
+ const name = e.name.startsWith(e.category)
+ ? e.name.slice(e.category.length).trim()
+ : e.name;
+ const parts = e.time.split('/');
+ const venue = (parts[1] ?? '').trim();
+ return {
+ '@type': 'Event',
+ name,
+ startDate: future[0],
+ eventStatus: 'https://schema.org/EventScheduled',
+ eventAttendanceMode: 'https://schema.org/OfflineEventAttendanceMode',
+ location: {
+ '@type': 'Place',
+ name: venue || '小平市',
+ address: {
+ '@type': 'PostalAddress',
+ addressLocality: '東京都小平市',
+ addressCountry: 'JP',
+ },
+ },
+ description: e.time,
+ url: `https://yasutakeyohei.com/kodaira-data/hp-archive/schedule/#${e.rowId}`,
+ };
+ })
+ .sort((a, b) => a.startDate.localeCompare(b.startDate))
+ .slice(0, 40);
+
+ const existing = document.getElementById('schedule-event-ldjson');
+ if (existing) existing.remove();
+ if (upcoming.length === 0) return;
+
+ const script = document.createElement('script');
+ script.type = 'application/ld+json';
+ script.id = 'schedule-event-ldjson';
+ script.textContent = JSON.stringify({
+ '@context': 'https://schema.org',
+ '@type': 'ItemList',
+ name: '小平市のこれからのイベント',
+ itemListElement: upcoming.map((item, index) => ({
+ '@type': 'ListItem',
+ position: index + 1,
+ item,
+ })),
+ });
+ document.head.appendChild(script);
+ }
+
// 件数はフィルターのボタンには出さず、ページ下部にまとめて表示する。
function renderCategorySummary() {
const summaryEl = document.getElementById('schedule-category-summary');
@@ -543,6 +596,7 @@
buildFilters();
renderCategorySummary();
+ emitEventStructuredData();
applyFilter();
renderCalendar();
if (selectedDate) showDayDetails(selectedDate);