Angular: metaタグの埋め込み方法(ルーターを使う場合)


Angular: metaタグの埋め込み方法(ルーターを使う場合)

Angular: SEO対策基本でSEO対策に最低限するべきことをまとめておいた。今回はどーやってmetaタグを埋め込むか。普通に検索するとAngularでコンポーネントからページの「メタ情報」を操作するには?のようにコンポーネントから直接meta.addTagなりmeta.updateTagで操作するみたいだが、ムムム…。思った通りにクローラーが拾ってくれない。

bootstrap componentからルーターのイベント経由でメタタグ操作をする方が良いみたい。

環境

Angular CLI: 7.1.4
Node: 10.15.3
OS: win32 x64
Angular: 7.1.4

"@angular/material": "^7.3.4"

やり方

まずapp.route.tsファイルにメタ情報を追記していく。

//app.route.ts

export const AppRoutes: Routes = [
    {path: "", component: HomeComponent,
    data: {
        title: 'hogehoge ー ホーム',
        description: 'hogeとはなんたらかんたら…',
        keywords: 'hoge,boyoyon,ororon',
        twittercard: 'summary',
        twittersite: '@hogehoge',
        twitterimage: 'https://hoge.io/hoge.img',
        url: 'https://hoge.io',
    }},
    {path: "introduction", component: IntroductionComponent,
    data: {
        title: 'hogehoge 紹介',
        description: 'hogeについてご紹介し…',
        keywords: 'hoge,boyoyon,ororon',
        twittercard: 'summary',
        twittersite: '@hogehoge',
        twitterimage: 'https://hoge.io/hoge_introduction.img',
        url: 'https://hoge.io/introduction',
    }},

次に、app.component.ts (もしくは独自のブートストラップコンポーネントにて)にて以下の通りに。

import { Component, OnInit} from '@angular/core';
import {Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import {Title, Meta} from "@angular/platform-browser";
import { filter, map, mergeMap } from 'rxjs/operators';

constructor(public router: Router, private route: ActivatedRoute, private titleService: Title, private meta: Meta) {}

そして同じくapp.component.ts (もしくは独自のブートストラップコンポーネントにて)にてngOnInit(){}に以下のメソッドを追記して、

ngOnInit() {
      //app.route.tsからmeta tagデータを引っ張り出してくるメソッド
      this.router.events.pipe(
        filter((event) => event instanceof NavigationEnd),
        map(() => this.route),
        map((route) => {
          while (route.firstChild) route = route.firstChild;
          return route;
        }),
        filter((route) => route.outlet === 'primary'),
        mergeMap((route) => route.data)).subscribe((event) => {
          this.updateDescription(event['description'], event['keywords'], event['title'], event['twittercard'], event['twittersite'], event['twitterimage'], event['url']);
        });
}

最後におなじくapp.component.ts (もしくは独自のブートストラップコンポーネントにて)にて適当な場所にupdateDescription()メソッドを追記。

   // metaタグをアップデートするメソッド
   updateDescription(desc: string, keywords: string, title: string, twittercard: string, twittersite: string, twitterimage: string, url: string) {
    this.titleService.setTitle(title);
    this.meta.updateTag({ name: 'description', content: desc })
    this.meta.updateTag({ name: 'keywords', content: keywords })
    this.meta.updateTag({ name: 'twitter:card', content: twittercard })
    this.meta.updateTag({ name: 'twitter:site', content: twittersite })
    this.meta.updateTag({ property: 'og:url', content: url })
    this.meta.updateTag({ property: 'og:title', content: title })
    this.meta.updateTag({ property: 'og:description', content: desc })
    this.meta.updateTag({ property: 'og:image', content: twitterimage })
   }

これでGoogleのクローラーは拾ってくれるようになった。
TwitterカードなどSNS系のボットはまだSPAのJS動的画面描画に対応してないようだがまあ時間の問題だろうと用意しておいた。


参考:Dynamically add meta description based on route in Angular