JavaScript
redirect
リダイレクト

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

情報を引き継ぎながらリダイレクトを行うJavaScriptコード

.htaccessが使えない等の理由でやむなくJavaScriptでリダイレクトするときのためのコード。

単純に

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によりスマートフォン向けページにリダイレクトが必要な状況を想定している。スマートフォンであるかどうかの判定にはこちらのコードを使用している。
別の条件が必要であればisMobile部分を書き換えるなりすればOK。

スマホからのアクセス時に別ページに移動させるためのコード(コメントなし)

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;
    }
}();

デバイスに関係なくリダイレクトさせるコード

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;
}();

スマホからのアクセス時に別ページに移動させるためのコード(コメントつき)

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;
    }
}();

参考になるリンク