From 9a48acc5eeab8f79062dc34a02b5ec292ebdf555 Mon Sep 17 00:00:00 2001 From: Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> Date: Sun, 1 Nov 2026 21:53:47 +0900 Subject: hp-archive: 行事予定ページのSEOを改善 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - タイトルと説明文に「行事予定」「傍聴」を追加 - CollectionPage とイベントの ItemList の構造化データを出力 - 最終更新日をページ冒頭に表示 - 案内ページのリンクカードの文言を具体化 --- src/components/ScheduleInteractive.astro | 54 ++++++++++++++++++++++ src/components/ScheduleSeo.astro | 32 +++++++++++++ src/content/docs/kodaira-data/hp-archive.mdx | 4 +- .../docs/kodaira-data/hp-archive/schedule.mdx | 9 ++-- src/data/updates.json | 4 +- src/styles/custom.css | 5 ++ 6 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 src/components/ScheduleSeo.astro 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); diff --git a/src/components/ScheduleSeo.astro b/src/components/ScheduleSeo.astro new file mode 100644 index 0000000..0eadb46 --- /dev/null +++ b/src/components/ScheduleSeo.astro @@ -0,0 +1,32 @@ +--- +// このページの構造化データ(JSON-LD)。ビルド日を更新日として出力する。 +const url = 'https://yasutakeyohei.com/kodaira-data/hp-archive/schedule/'; +const updated = new Date(); +const iso = updated.toISOString().slice(0, 10); +const label = `${updated.getFullYear()}年${updated.getMonth() + 1}月${updated.getDate()}日`; + +const data = { + '@context': 'https://schema.org', + '@type': 'CollectionPage', + name: '小平市のイベント・行事予定と審議会の傍聴(2026年10月〜)', + description: + '小平市のイベント・行事予定と、審議会・市議会の傍聴予定を、日程・会場・申込期限つきでまとめた一覧です。カテゴリ別の絞り込みと地図で確認できます。', + url, + inLanguage: 'ja', + dateModified: iso, + about: [ + { '@type': 'Thing', name: '小平市のイベント' }, + { '@type': 'Thing', name: '小平市議会の傍聴' }, + { '@type': 'Thing', name: '小平市の審議会' }, + ], + isPartOf: { + '@type': 'WebSite', + name: '小平市議 安竹洋平 公式サイト', + url: 'https://yasutakeyohei.com/', + }, +}; +--- + +