ブログサービス等に <link rel="canonical" ...> タグを付与する

追記 (2019/01/05)

本稿の本文及びタグ <link rel="canonical" ...> を付与するための javascript コードを修正しました。どうか御了承下さい。

追記 (2019/01/06)

本稿において、拙稿 “Rootless Containers 版 proot のソースコードの修正点について“ の投稿のリンクに誤りがありました。ここに、本稿を訂正すると共に、心より御詫び申し上げます。

追記 (2019/01/11)

タグ <link rel="canonical" ...> を付与するための javascript コードについて、動作の不具合を修正しました。どうか御了承下さい。

追記 (2019/01/12)

タグ <link rel="canonical" ...> の付与確認について追記しました。

追記 (2019/01/17)

タグ <link rel="canonical" ...> を付与するための javascript コードの外部ファイル化について追記しました。

追記 (2019/02/14)

javascript コードのバグフィックス及び機能追加に伴い、本稿の改稿を行いました。どうか御了承下さい。

はじめに

Qrunch は、技術的な内容に特化したブログサービスです。 Qrunch では、クロス投稿元 URL の設定を行う事によって、他のサイト及びブログサービスにおける投稿からのクロス投稿を行う事が出来ます。

ここで、 Qrunch においてクロス投稿元 URL を設定すると、 Qrunch の投稿のページに <link rel="canonical" ...> のタグが付与されます。

この為、Qrunch の投稿は検索エンジンによって無視され、クロス投稿元 URL の投稿がインデックスに残る為に、クロス投稿元 URL の投稿が “主” として、 Qrunch の投稿が “従” として扱われる事になります。

ここで、技術的なブログサービスとして主に Qrunch を使用したい時に、 Qrunch の投稿から他のサイト及びブログサービスへクロス投稿を行い、これらのサービスのページに <link rel="canonical" ...> のタグを付与し、Qrunch の投稿を “主” として、他のサイト等の投稿を “従” として扱いたい場合が考えられます。

本稿では、他のサイト及びブログサービスに javascript のコードの小片を投稿の本文に貼る事によって、これらのサービスのページに <link rel="canonical" ...> のタグを付与する手法について述べます。

なお本稿では、クロス投稿の一例として、拙稿 “Rootless Containers 版 proot のソースコードの修正点について“ をはてなブログにクロス投稿し、はてなブログ側に <link rel="canonical" ...> タグを付与する場合について示すものとします。

タグ <link rel="canonical" ...> の付与手法

ここで、はてなブログにおいて <link rel="canonical" ...> タグを付与する場合は、以下の javascript のコードの小片を <script> タグを用いて投稿の本文に埋め込みます。

なおここで、はてなブログの記法は markdown 記法を使用しているものとします。

また、

# 本稿について  

本稿は、<a href="https://z80oolong.qrunch.io/entries/gBKScNZEf8kRcOMb" id="canonical_url">以下の Qrunch 諸島の投稿</a>のクロス投稿です。どうか御了承下さい。  

[https://z80oolong.qrunch.io/entries/gBKScNZEf8kRcOMb:embed:cite]  <!-- はてなブログの埋め込みリンク -->  

<script type="text/javascript">  
<!--  
window.addEventListener("load", function () {  
    var doc    = document;  
    var head   = doc.getElementsByTagName("head")[0];  
    var links  = doc.getElementsByTagName("link");  
    var as     = doc.getElementsByTagName("a");  
    var a_curl = doc.getElementById("canonical_url");  
    var c_href = location.href;  
    var canon  = null;  

    for (var i = 0; i < links.length; i++) {  
        if (links[i].rel && (links[i].rel.toLowerCase() == "canonical")) {  
            if (canon == null) {  
                canon = links[i];  // <link rel="canonical" ...> タグを1個抽出。  
            } else {  
                links[i].parentNode.removeChild(links[i]);  // 残りの <link rel="canonical" ...> タグは除去。  
                i--; // 除去したタグ <link rel="canonical" ...> 1個分だけ links.length が 1 減少する。  
            }  
        }  
    }  

    if (canon == null) {  
        canon = doc.createElement("link");  // <link rel="canonical" ...> タグが存在しない場合はこれを生成。  
        canon.setAttribute("rel", "canonical");  
        head.appendChild(canon);  
    }  

    if (a_curl && (a_curl.href.toString() != "")) {  
        // <a href="..." id="canonical_url"> タグの href 属性が空文字列でない場合は、  
        // この href 属性を <link rel="canonical" ...> タグの href 属性とする。  
        c_href = a_curl.href.toString();  
    } else {  
        // <a href="..." id="canonical_url"> タグの href 属性が空文字列の場合は、  
        // <a> タグの中から title 属性が "canonical url" であるものを探す。  
        for (var i = 0; i < as.length; i++) {  
            if (as[i].title && (as[i].title.toLowerCase() == "canonical url")) {  
                if (as[i].href.toString() != "") {  
                    // <a href="..." title="canonical url"> タグの href 属性が空文字列でないもののうち、  
                    // 最初の href 属性を <link rel="canonical" ...> タグの href 属性とする。  
                    c_href = as[i].href.toString();  
                    break;  
                }  
            }  
        }  
    }  

    // <link rel="canonical" ...> タグに href 属性を付与する。  
    canon.setAttribute("href", c_href);  
});  
//->  
</script>

なお、以上の javascript のコードを記述するにあたっては、以下の投稿を参考にしました。投稿記事の著者各位に心より感謝致します。

即ち、投稿ページ内に <link rel="canonical" ...> タグが存在しない場合は、これを生成した上で、 <head> の子要素として付加し、<link rel="canonical" ...> タグが存在する場合は、既存の1個の <link rel="canonical" ...> タグの属性を修正した上で、それ以外の <link rel="canonical" ...> タグを削除します。

そして、 <link rel="canonical" ...> タグに付与するhref 属性の値は、以下の順序に従って決定されます。

  • ページ内に存在する全ての <a> タグのうち、 id 属性の値が "canonical_url" である <a> タグの href 属性の値。
  • 上記の値が存在しない場合は、ページ内に存在する全ての <a> タグのうち、 title 属性の値が "canonical url" (大文字・小文字の区別をしない) であるもののうち、最初に href 属性をもつ<a> タグの href 属性の値。
  • 上記の値が存在しない場合は、ページ本体の URL の値。

なお、ここで <link rel="canonical" ...> タグを1個のみとするのは、検索エンジンが、1ページ内に複数個の <link rel="canonical" ...> タグを見つけると、検索エンジンは <link rel="canonical" ...> タグを完全に無視する為です。

javascript コードの外部ファイル化

ここで、前述した javascript のコードの設置を容易にするために、前述の javascript コードを外部 javascript ファイル化した URL を以下に示します。

上記した外部 javascript ファイルを使用するには、例えば、はてなブログ等のクロス投稿先となるブログサービスにおいて、ページ内の任意の位置に以下の <script> タグを記述します。

<!-- ...(略)... -->  
<script text="text/javascript" src="https://github.com/z80oolong/canonical_url/releases/download/v0.0.2/canonical.js"></script>  
<!-- ...(略)... -->

なお、この <script> タグは、はてなブログにおいては、デザインの設定により、ヘッダ及びフッタに記述しても構いません。

そして前述と同じく、クロス投稿元となる Web ページ等の URL を以下のような形式で埋め込みます。

<!-- ...(略)... -->  
<a href="https://www.example.com/canonical.html" id="canonical_url">クロス投稿元のリンクです</a> <!-- ここに、 https://www.example.com/canonical.html は、クロス投稿元の URL -->  
<!-- ...(略)... -->

また、 <a> タグに title 属性を付与する場合は、クロス投稿元となる Web ページ等の URL を以下のような形式で埋め込みます。

<!-- ...(略)... -->  
<a href="https://www.example.com/canonical.html" title="Canonical URL">クロス投稿元のリンクです</a> <!-- ここに、 https://www.example.com/canonical.html は、クロス投稿元の URL -->  
<!-- ...(略)... -->

なお、上記の形式は、 Markdown 記法では、以下の形式で埋め込むことが出来ます。

<!-- ...(略)... -->  
[クロス投稿元のリンクです][CANON]  

[CANON]:https://www.exanple.com/canonical.html "Canonical URL"  

<!-- ここに、 https://www.example.com/canonical.html は、クロス投稿元の URL -->  
<!-- ...(略)... -->

なお、外部ファイルの詳細については以下のページを御覧下さい。

タグ <link rel="canonical" ...> の付与確認

ここで、はてなブログにおいて、前述した javascript のコードの小片を埋め込んで、実際にタグ <link rel="canonical" ...> が付与されたかどうか確認します。

なお、ここで確認に用いる Web ブラウザは Firefox 49.0 として確認を行います。

まず、 javascript のコードの小片を埋め込んだページを表示させた後に、以下の画像のようにブラウザのメニューで [”開発ツール”] を選択します。

次に、以下の画像のように [“開発ツール”] のメニューから [“インスペクタ”] を選択します。

そして、 [“インスペクタ”] のコンソール表示において、以下の画像のように <head> 要素の内容を確認すると、 Qrunch の投稿をクロス投稿元とした <link rel="canonical" ...> タグが付与されている事が判ります。