【Laravel】artesaos/seotoolsを利用してSEOに必要なmetaタグを生成する

# はじめに
こんにちは、オールアバウトナビエンジニアの@HaruKado777です。
本記事は[All About Group（株式会社オールアバウト） Advent Calendar 2022 22日目](https://qiita.com/advent-calendar/2022/allabout)の記事です。

今回はSEO対策に必要なメタタグを自動生成するLaravelのHelper関数を提供してくれるライブラリを紹介します。

# artesaos/seotoolsとは
[artesaos/seotools](https://github.com/artesaos/seotools)とは下記を自動生成してくれるLumenとLaravelに対応したSEO対策用ライブラリです
- SEO対策に必要なタイトルとメタタグの設定
- [Twitter Cards](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards)と[Open Graph](https://ogp.me/)のメタデータ
- [JSON Linked Data](https://json-ld.org/)

# インストール方法
下記コマンドを実行し`composer.json`ファイルを更新します

```
composer require artesaos/seotools
```

config/app.phpにSEOToolsの`providers`と`aliases`を追加します。
`aliases`は、各種それぞれを追加するか、それらをひとまとめにしたSEOを追加します。

```
return [
    // ...
    'providers' => [
        Artesaos\SEOTools\Providers\SEOToolsServiceProvider::class,
        // ...
    ],
    // ...
    'aliases' => [
        'SEOMeta'       => Artesaos\SEOTools\Facades\SEOMeta::class,
        'OpenGraph'     => Artesaos\SEOTools\Facades\OpenGraph::class,
        'Twitter'       => Artesaos\SEOTools\Facades\TwitterCard::class,
        'JsonLd'        => Artesaos\SEOTools\Facades\JsonLd::class,
        'JsonLdMulti'   => Artesaos\SEOTools\Facades\JsonLdMulti::class,
        // or
        'SEO' => Artesaos\SEOTools\Facades\SEOTools::class,
        // ...
    ],
    // ...
];

```

# デフォルト設定

下記のコマンドから```config/seotools.php```を生成します。
``` 
php artisan vendor:publish --provider="Artesaos\SEOTools\Providers\SEOToolsServiceProvider"
```

必要に応じて```config/seotools.php```の設定を変更します。

```
<?php
/**
 * @see https://github.com/artesaos/seotools
 */

return [
    'meta' => [
        /*
         * The default configurations to be used by the meta generator.
         */
        'defaults'       => [
            'title'        => "It's Over 9000!", // set false to total remove
            'titleBefore'  => false, // Put defaults.title before page title, like 'It's Over 9000! - Dashboard'
            'description'  => 'For those who helped create the Genki Dama', // set false to total remove
            'separator'    => ' - ',
            'keywords'     => [],
            'canonical'    => false, // Set to null or 'full' to use Url::full(), set to 'current' to use Url::current(), set false to total remove
            'robots'       => false, // Set to 'all', 'none' or any combination of index/noindex and follow/nofollow
        ],
        /*
         * Webmaster tags are always added.
         */
        'webmaster_tags' => [
            'google'    => null,
            'bing'      => null,
            'alexa'     => null,
            'pinterest' => null,
            'yandex'    => null,
            'norton'    => null,
        ],

        'add_notranslate_class' => false,
    ],
    'opengraph' => [
        /*
         * The default configurations to be used by the opengraph generator.
         */
        'defaults' => [
            'title'       => 'Over 9000 Thousand!', // set false to total remove
            'description' => 'For those who helped create the Genki Dama', // set false to total remove
            'url'         => false, // Set null for using Url::current(), set false to total remove
            'type'        => false,
            'site_name'   => false,
            'images'      => [],
        ],
    ],
    'twitter' => [
        /*
         * The default values to be used by the twitter cards generator.
         */
        'defaults' => [
            //'card'        => 'summary',
            //'site'        => '@LuizVinicius73',
        ],
    ],
    'json-ld' => [
        /*
         * The default configurations to be used by the json-ld generator.
         */
        'defaults' => [
            'title'       => 'Over 9000 Thousand!', // set false to total remove
            'description' => 'For those who helped create the Genki Dama', // set false to total remove
            'url'         => false, // Set to null or 'full' to use Url::full(), set to 'current' to use Url::current(), set false to total remove
            'type'        => 'WebPage',
            'images'      => [],
        ],
    ],
];
```

# 使い方
## コントローラー

```config/seotools.php```で定義したデフォルトから変更したい場合、コントローラーでページごとの設定を行います。 

```
<?php

namespace App\Http\Controllers;

use Artesaos\SEOTools\Facades\SEOMeta;
use Artesaos\SEOTools\Facades\OpenGraph;
use Artesaos\SEOTools\Facades\TwitterCard;
use Artesaos\SEOTools\Facades\JsonLd;
// OR with multi
use Artesaos\SEOTools\Facades\JsonLdMulti;

// OR
use Artesaos\SEOTools\Facades\SEOTools;

class CommomController extends Controller
{
    public function index()
    {
        SEOMeta::setTitle('Home');
        SEOMeta::setDescription('This is my page description');
        SEOMeta::setCanonical('https://codecasts.com.br/lesson');

        OpenGraph::setDescription('This is my page description');
        OpenGraph::setTitle('Home');
        OpenGraph::setUrl('http://current.url.com');
        OpenGraph::addProperty('type', 'articles');

        TwitterCard::setTitle('Homepage');
        TwitterCard::setSite('@LuizVinicius73');

        JsonLd::setTitle('Homepage');
        JsonLd::setDescription('This is my page description');
        JsonLd::addImage('https://codecasts.com.br/img/logo.jpg');

        // OR

        SEOTools::setTitle('Home');
        SEOTools::setDescription('This is my page description');
        SEOTools::opengraph()->setUrl('http://current.url.com');
        SEOTools::setCanonical('https://codecasts.com.br/lesson');
        SEOTools::opengraph()->addProperty('type', 'articles');
        SEOTools::twitter()->setSite('@LuizVinicius73');
        SEOTools::jsonLd()->addImage('https://codecasts.com.br/img/logo.jpg');

        $posts = Post::all();

        return view('myindex', compact('posts'));
    }
    // ...
}
```

※SEOToolsTraitを利用する方法もありますが、ここでは割愛します。

## View

Bladeにメタタグを出力するための設定をします。

```
<html>
<head>
    {!! SEOMeta::generate() !!}
    {!! OpenGraph::generate() !!}
    {!! Twitter::generate() !!}
    {!! JsonLd::generate() !!}
    // OR with multi
    {!! JsonLdMulti::generate() !!}

    <!-- OR -->
    {!! SEO::generate() !!}

    <!-- MINIFIED -->
    {!! SEO::generate(true) !!}

    <!-- LUMEN -->
    {!! app('seotools')->generate() !!}
</head>
<body>

</body>
</html>
```

## 出力結果

下記のような出力結果になります。
```
<html>
<head>
    <title>Title - Over 9000 Thousand!</title>
    <meta name='description' itemprop='description' content='description...'>
    <meta name='keywords' content='key1, key2, key3'>
    <meta property='article:published_time' content='2015-01-31T20:30:11-02:00'>
    <meta property='article:section' content='news'>

    <meta property="og:description" content="description...">
    <meta property="og:title" content="Title">
    <meta property="og:url" content="http://current.url.com">
    <meta property="og:type" content="article">
    <meta property="og:locale" content="pt-br">
    <meta property="og:locale:alternate" content="pt-pt">
    <meta property="og:locale:alternate" content="en-us">
    <meta property="og:site_name" content="name">
    <meta property="og:image" content="http://image.url.com/cover.jpg">
    <meta property="og:image" content="http://image.url.com/img1.jpg">
    <meta property="og:image" content="http://image.url.com/img2.jpg">
    <meta property="og:image" content="http://image.url.com/img3.jpg">
    <meta property="og:image:url" content="http://image.url.com/cover.jpg">
    <meta property="og:image:size" content="300">

    <meta name="twitter:card"content="summary">
    <meta name="twitter:title"content="Title">
    <meta name="twitter:site"content="@LuizVinicius73">

    <script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","name":"Title - Over 9000 Thousand!"}</script>
    <!-- OR with multi -->
    <script type="application/ld+json">{"@context":"https://schema.org","@type":"Article","name":"Title - Over 9000 Thousand!"}</script>
    <script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","name":"Title - Over 9000 Thousand!"}</script>
</head>
<body>

</body>
</html>
```

# まとめ（使ってみた感想）

下記使ってみた感想です。
- デフォルトの設定をすることができ、使いまわしやすい
- インターフェースの呼び出しが簡単で、デフォルトの設定変更がしやすい

webサイトのSEO対策に必要な設定を簡単にできる、非常に便利なライブラリだと感じました！
ぜひこの記事を読んでくださった方も使ってみてください。