Laravel + Inertia.js(Vue)でMetaタグを設定する

LaravelのJetstreamを使用する時に使うフレームワークはInertia.jsを使っているのですが、Metaタグの設定にてこづったのでメモがわりに残しておきます。

Jetstreamは会員登録機能を作る時にはほぼ必須で使用しています。

https://laravel.com/docs/9.x/starter-kits#laravel-jetstream

テンプレートフレームワークを Livewire か Inertia を選択する必要があるのですが、Vue.jsの知識をそのまま使用できる Inertia.js を毎回使っています。

https://inertiajs.com

Inertia.jsはLaravel上で使用できるSPAフレームワークという認識です。Vue.js、React.js、Svelte.jsと選べます。

Metaタグの設定方法が公式で記載されていますが、jsで展開されるMetaタグなのでTwitterやFacebook、Slackでの展開に対応していません。

Google botはjsを展開して検索結果に反映してくれるのですが、SNSにURL投稿したときにタイトルや画像を展開したかったので対応した方法を記載します。

公式で記載されていたMetaタグの設定は無意味かというとそうではなく、ページ遷移した時にブラウザのタブの表示名がtitle名になる、というメリットがあります。この表示がされる方が自然なため、タブ名を変える事は諦めたくはありません。

達成したい仕様

jsでの設定では展開されないサイトが多いので、サーバーサイドのLaravelでMetaタグが出力されるようにします。

なおかつ、ページ遷移の際にブラウザのタブにtitle要素の文字列が表示されるので、同じ内容がjs側でも読み取れるようにします。

設定方法

SEOタグの出力は以下のライブラリを使用

https://github.com/artesaos/seotools

上記のドキュメント通りに設定が終わった事を前提にしています。

その後、app.blade.php に以下のように設定するのが今回のポイントです。

        <title inertia>{{ SEO::getTitle() }}</title>
        {!! SEO::generate() !!}

上記の設定を行うとtitleタグが2つ表示されます。

Inertia.js はページ遷移した際に <title inertia> のタグ内容を変更するのですが、titleタグは先に読まれた内容をブラウザタブの名前に適応されるため、このように2つ設定しています。

こうすればページ遷移した時にブラウザタブの名前も変更されて遷移した事がわかり、サーバーサイドで出力したMetaタグも共存できます。

あとはjs側にタイトル要素が渡るように

use Artesaos\SEOTools\Facades\SEOTools;

    public function share(Request $request): array
    {
        $data = parent::share($request);

        $data = array_merge($data, $this->seoData($request));

        return $data;
    }

    private function seoData(Request $request)
    {
        return [
            'metaTitle' => function () use ($request) {
                // コントローラーで直編集しづらいページのタイトルを指定
                $routes = [
                    'terms-of-service' => '利用規約',
                    'privacy-policy' => 'プライバシーポリシー',
                    'user/profile' => 'プロフィール編集',
                ];
                foreach ($routes as $path => $title) {
                    if ($request->is($path)) {
                        SEOTools::setTitle($title);
                    }
                }
                if ($request->is(['terms-of-service', 'privacy-policy'])) {
                    SEOTools::metatags()->addMeta('robots', 'noindex,nofollow');
                }

                return SEOTools::getTitle();
            },
        ];
    }
<script setup>
import { Head } from '@inertiajs/inertia-vue3';
</script>

<template>
    <Head :title="$page.props.metaTitle" />
~~~~
</template>
use Artesaos\SEOTools\Traits\SEOTools as SEOToolsTrait;

class Controller extends BaseController
{
    use SEOToolsTrait;
}

と設定すれば共通処理は完了です。常にAppLayout.vueを使用するようにしましょう。

各種コントローラーでタイトル要素や画像などなど、必要に応じて変更しましょう

<?php

namespace App\Http\Controllers;

use App\Models\Office;
use Illuminate\Http\Request;
use Inertia\Inertia;

class TopController extends Controller
{
    public function index()
    {
        $this->seo()->setTitle('Top');

        return Inertia::render('Top/Index');
    }
}

こうする事でこちらの画像のように

タグが出力されるようになるので、SNSなどjsのみで設定したMetaタグを展開しないサイトでも適切に展開されるようになりました。

投稿者


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA