パラメーターやリファラ情報を引き継ぎながらリダイレクトを行うJavaScriptコード

#情報を引き継ぎながらリダイレクトを行うJavaScriptコード
.htaccessが使えない等の理由でやむなくJavaScriptでリダイレクトするときのためのコード。

単純に

```js:
location.href = 'http://example.co.jp/sp/index.html';
```

のようにやってしまうと、リダイレクト元ページURLのクエリパラメータ(URLの「`?`」の後に続く文字列)とリファラ情報(`document.referrer`)が拾えなくなってしまうので、
リダイレクト元ページのクエリパラメータをそのままリダイレクト先URLにくっつけ、更にリファラ情報もクエリパラメータ`referrer`の名前でくっつけてリダイレクトを行うようにした。
リダイレクト先URLに`#key`のようにフラグメント部が含まれていることも考慮している。

##動作例
たとえば、以下のような状況でリダイレクトコードが動作したとき、


**コードを埋め込むページURL**   `http://example.co.jp/product/2359/index.html?quux=corge&grault=garply`

**コードが動作したときのリファラ** `http://example.co.jp/search?q=book&camp=springSale2018`

**コード内で指定したリダイレクト先URL**
`http://example.co.jp/sp/product/2359/index.html?foo=bar&baz=qux#key`

このコードは、
`http://example.co.jp/sp/product/2359/index.html?foo=bar&baz=qux&quux=corge&grault=garply&referrer=http%3A%2F%2Fexample.co.jp%2Fsearch%3Fq%3Dbook%26camp%3DspringSale2018#key`にリダイレクトする。

このURLをパーツごとに分解すると以下のようになる。

###生成されるリダイレクト先URLの分解

**コード内で指定していたリダイレクト先URLのindex.htmlの部分まで**
`http://example.co.jp/sp/product/2359/index.html?foo=bar&baz=qux`

**クエリ部のはじまりを示す半角疑問符?**
`?`

**コード内で指定していたリダイレクト先URLのクエリパラメータ部分**
`foo=bar&baz=qux`

**パラメタ同士を繋ぐアンパサンド&**
`&`

**リダイレクト元ページに付いていたクエリパラメータ**
`quux=corge&grault=garply`

**パラメタ同士を繋ぐアンパサンド&**
`&`

**リダイレクト元ページのリファラ情報**
`referrer=http%3A%2F%2Fexample.co.jp%2Fsearch%3Fq%3Dbook%26camp%3DspringSale2018`

**コード内で指定していたリダイレクト先URLのフラグメント部**
`#key`

##コード
スマートフォンからのアクセス時にJavaScriptによりスマートフォン向けページにリダイレクトが必要な状況を想定している。スマートフォンであるかどうかの判定には[こちらのコード](https://qiita.com/AQRiL_1132/items/f7c568d5048c4ba1074e)を使用している。
別の条件が必要であれば`isMobile`部分を書き換えるなりすればOK。

###スマホからのアクセス時に別ページに移動させるためのコード(コメントなし)
```js:mobileRedirect.js
!function() {
    var newPage = 'https://example.com/sp/index.html?hoge=hoga#id';
    var isMobile = (function() {
        var ua = navigator.userAgent.toLowerCase();
        var sdev = /iphone;|(android|nokia|blackberry|bb10;).+mobile|android.+fennec|opera.+mobi|windows phone|symbianos/;
        return sdev.test(ua);
    })();
    if (isMobile) {
        var separatednewPage = newPage.match(/(^https?:\/\/[^?#]+)(?:\?([^#]*))?(#.*)?$/);
        var newOriginPath = separatednewPage[1];
        var newFlagment = separatednewPage[3];
        var oldReferrer = document.referrer ? 'referrer=' + encodeURIComponent(document.referrer) : '';
        var oldQuery = location.search.slice(1);
        var newQuery = [separatednewPage[2], oldQuery, oldReferrer].filter(function(q) {
            return !!q
        }).join('&');
        var newLocation = newOriginPath;
        if (newQuery) {
            newLocation = newLocation + '?' + newQuery;
        }
        if (newFlagment) {
            newLocation = newLocation + newFlagment;
        }
        location.href = newLocation;
    }
}();
```

###デバイスに関係なくリダイレクトさせるコード
```js:mobileRedirect.js
!function() {
    var newPage = 'https://example.com/sp/index.html?hoge=hoga#id';
    var separatednewPage = newPage.match(/(^https?:\/\/[^?#]+)(?:\?([^#]*))?(#.*)?$/);
    var newOriginPath = separatednewPage[1];
    var newFlagment = separatednewPage[3];
    var oldReferrer = document.referrer ? 'referrer=' + encodeURIComponent(document.referrer) : '';
    var oldQuery = location.search.slice(1);
    var newQuery = [separatednewPage[2], oldQuery, oldReferrer].filter(function(q) {
        return !!q
    }).join('&');
    var newLocation = newOriginPath;
    if (newQuery) {
        newLocation = newLocation + '?' + newQuery;
    }
    if (newFlagment) {
        newLocation = newLocation + newFlagment;
    }
    location.href = newLocation;
}();
```

###スマホからのアクセス時に別ページに移動させるためのコード(コメントつき)
```js:mobileRedirect.js
/**
 * スマートフォンからのアクセス時に指定したURLにリダイレクトするコード
 * リダイレクト元ページのGETパラメタとリファラをリダイレクト先のGETパラメタに追加することで、
 * リダイレクト先でもこれらの情報を利用できるようにしている。
*/
!function() {

    /**
     * リダイレクト先のURLを指定します。
     * @type {string}
     */
    var newPage = 'https://example.com/sp/index.html?hoge=hoga#id';

    /**
     *  スマートフォンからのアクセスであるかを示す真偽値です。
     * @type {boolean}
     */
    var isMobile = (function() {
        var ua = navigator.userAgent.toLowerCase();
        var sdev = /iphone;|(android|nokia|blackberry|bb10;).+mobile|android.+fennec|opera.+mobi|windows phone|symbianos/;
        return sdev.test(ua);
    })();
    
    if (isMobile) {
        /**
         * 指定されたリダイレクト先URLを正規表現により、プロトコル+ドメイン+パス部、GETパラメタ部、フラグメント部に分けた文字列です。
         * @type {string}
         */
        var separatednewPage = newPage.match(/(^https?:\/\/[^?#]+)(?:\?([^#]*))?(#.*)?$/);

        /**
         * 指定された飛び先URLのプロトコルからパス部までを示す文字列です。 e.g.'http://hoge.com/sp/index.html'
         * @type {string}
         */
        var newOriginPath = separatednewPage[1];

        /**
         * 指定されたリダイレクト先URLのフラグメント部を示す文字列です。 e.g.'#fragment'
         * @type {string}
         */
        var newFlagment = separatednewPage[3];

        /**
         * 今のページのリファラ情報であるdocument.referrerの値を示す文字列です。 e.g.'referrer=http%3A%2F%2Fhoge.com%2FprevPage'
         * リダイレクト先のGETパラメタに付与してリダイレクト先のページでも利用できるようにします。
         * @type {string}
         */
        var oldReferrer = document.referrer ? 'referrer=' + encodeURIComponent(document.referrer) : '';

        /**
         * 今のページのGETパラメタであるlocation.searchから先頭の「?」を除いた結果を示す文字列です。 e.g.'foo=bar&baz=qux'
         * リダイレクト先のGETパラメタに付与してリダイレクト先のページでも利用できるようにします。
         * @type {string}
         */
        var oldQuery = location.search.slice(1);

        /**
         * 実際のリダイレクト先URLに設定するGETパラメタすべてを&で結合した結果を示す文字列です。 e.g.'foo=bar&baz=qux&oldq=oldk&referrer=http%3A%2F%2Fhoge.com%2FprevPage'
         * リダイレクト先のGETパラメタに付与してリダイレクト先のページでも利用できるようにします。
         * @type {string}
         */
        var newQuery = [separatednewPage[2], oldQuery, oldReferrer].filter(function(q) {
            return !!q
        }).join('&');

        /**
         * 実際の飛び先URLを示す文字列です。 e.g.'http://hoge.com/sp/index.htmlfoo=bar&baz=qux&oldq=oldk&referrer=http%3A%2F%2Fhoge.com%2FprevPage'
         * @type {string}
         */
        var newLocation = newOriginPath;
        if (newQuery) {
            newLocation = newLocation + '?' + newQuery;
        }
        if (newFlagment) {
            newLocation = newLocation + newFlagment;
        }
        location.href = newLocation;
    }
}();
```



##参考になるリンク

- [document.referrer - Web API インターフェイス | MDN](https://developer.mozilla.org/ja/docs/Web/API/Document/referrer)
- [リダイレクトの方法 - Qiita](https://qiita.com/mimoe/items/ec2f51b13410b9e1024a)
- [やはり、お前らのJavaScriptでのリダイレクト実装は間違っている - Qiita](https://qiita.com/1987yama3/items/5ff58b6195fe6c3f268b)
- [Referrer を制御する - Qiita](https://qiita.com/wakaba@github/items/707d72f97f2862cd8000)
- [ユーザーエージェントから電話デバイスかどうか簡易判定するコード - Qiita](https://qiita.com/AQRiL_1132/items/f7c568d5048c4ba1074e)
- [userAgentでブラウザ＆デバイス判別 2017年版 - Qiita](https://qiita.com/gurigurico/items/bd19ed121bfdf77fced6)
- [シャープ記号(#)付きのURLをGoogleアナリティクスで測定する - Qiita](https://qiita.com/AQRiL_1132/items/3e9061d349dc580e4ad7)