Livewire
@seoなどのBladeディレクティブは、特定のフロントエンドフレームワークに依存しません。<head>内に通常のHTMLを出力するため、どのLivewireアプリでもBladeと同じように動作します。
初回のフルページ描画
Livewireのフルページコンポーネント(ルートがコンポーネントを返す形式)や、Livewireコンポーネントを囲むBladeレイアウトでは、@seoはBladeのガイドとまったく同じように動作します。
{{-- layouts/app.blade.php --}}
<head>
@seo($post ?? null)
</head>最初のHTTPレスポンスには、クローラーが読み取れる完全なheadが含まれます。title、description、canonical、Open Graph、Twitter、JSON-LDがすべて出力されます。クローラーやSNSのスクレイパーが取得するこのレスポンスでは、必要な内容が正しく揃います。
wire:navigateの注意点
Livewireのwire:navigateは、リンクのクリックをSPA形式のページ遷移に変えます。この遷移では、Livewireが<body>を置き換え、<head>をマージします。ただし、SEOパッケージにとって重要な扱いの違いがあります。
- **
<title>と<meta>、<link>**は新しいページのheadからマージされるため、解決済みのtitleやmetaは通常どおり更新されます。 <script>は削除できないアセットとして扱われます。 Livewireは、一度読み込んだ<script>をすべて保持し、再実行によってJavaScriptが壊れることを防ぎます。そのため、JSON-LDの<script>ブロックが蓄積します。3つの記事を閲覧すると、3記事分のスキーマが同時にhead内へ残り、構造化データを読み取るツールには、誤ったエンティティや複数のエンティティが見えてしまいます。
不要なものを削除できるように、レンダラーは出力するすべてのJSON-LDスクリプトにマーカーを付けます。
<script type="application/ld+json" data-seo-schema
data-seo-url="https://example.com/blog/the-post"> … </script>JSON-LDの削除処理を追加する
次のコードを1回だけ追加してください。例えば、ルートレイアウトの@livewireScriptsの後に置きます。wire:navigateによる遷移のたびに、現在のページのスキーマだけを残し、古いスキーマを削除します。
<script>
document.addEventListener('livewire:navigated', () => {
// The page we are now on. data-seo-url is the canonical (query-stripped),
// so compare on the query-stripped location.
const here = window.location.href.split('#')[0].split('?')[0]
// Keep only the LAST schema for this page; remove every other-URL
// (stale) script AND same-URL duplicates Livewire re-adds when a page is
// revisited — including clearing a lone stale script when this page has
// none. Iterate from the end so the freshest copy is the one kept.
const scripts = [...document.querySelectorAll('script[data-seo-schema]')]
let kept = false
for (let i = scripts.length - 1; i >= 0; i--) {
const url = (scripts[i].getAttribute('data-seo-url') || '').split('?')[0]
if (url === here && !kept) { kept = true; continue }
scripts[i].remove()
}
})
</script>レンダラーがすでに出力するdata-seo-schemaマーカーとURLごとの識別子だけを利用するため、ページごとの設定は不要です。
最後に追加されたスクリプトではなく、現在のURLと比較する
以前のサンプルは、スキーマのscriptが2つ未満の場合に処理を終了し、最後に追加されたscriptを現在のページのものと見なしていました。この方法では、JSON-LDがあるページからないページへ移動したときに、古いスキーマがheadに残ります。古いscriptが1つだけ残った状態で処理を終了してしまうためです。また、再訪問時にLivewireが追加する同じURLの重複も削除できません。それぞれのdata-seo-urlをwindow.locationと比較し、一致するもののうち最後の1つだけを保持すれば、いずれの場合も古いスキーマと重複を取り除けます。rankbeam-examplesのLivewireアプリとブラウザーテストでは、この動作を検証しています。
SPA形式の遷移と単一のmetaタグ
Livewireのheadマージにより、単一の<meta>や<link>タグが古いまま残ることは、多くの場合避けられます。ただし、正確な動作はLivewireのバージョンとレイアウトの構造に依存します。クローラー向けの正しいmetaが特に重要なページでは、ページ全体の再読み込み(wire:navigateのない通常のリンク)を優先するか、サーバー側で描画し、最初のHTTPレスポンスに正しい内容を含めてください。rankbeam-examplesのLivewireアプリでは、ブラウザー上で実際にwire:navigateによる遷移を行い、この動作を確認しています。
Filament
Filamentは内部でLivewireを使っていますが、管理画面でコンテンツを編集するためのものです。seo_metaを編集するだけで、公開フロントエンドのheadを出力することはありません。Filamentのガイドを参照してください。このページで説明した処理は、管理パネルには適用されません。