JavaScriptでGoToトラベルのクーポン種別を絞込む


はじめに

金持ちほど得をする素敵なキャンペーン、GoToトラベルですが、クーポン種別が紙と電子の二種類あることをご存知でしょうか?
紙クーポンは、その名の通り実体のある紙形のクーポン、電子クーポンはスマホから使用できるバーチャルなクーポンです。

普通に考えれば、同じキャンペーンで発行されたクーポンなので同じように使えるはずですが、そこは流石日本というべきか、
電子クーポンは紙クーポンと比較して約半数の店鋪でしか使用できません。

「まあ、最初に調べてから旅行すればいいじゃん」と思いますが、GoToトラベルのサイト上ではクーポン種別による絞り込みが出来ません。

これをUserScriptを使用して改善してみます。

UserScriptって?

UserScriptとは、Webサイト上でユーザー任意のJavascriptを割り込む仕組み、またはそのスクリプトのことです。
たいていのブラウザで拡張機能として動作します。Tampermonkeyあたりが有名でしょうか。
今回はこれを用いることによって、GoToトラベルの公式Webサイト上で絞り込み機能を有効化しています。

スクリプト

// ==UserScript==
// @name         GoToRefine
// @namespace    https://satoh.dev/
// @version      0.1
// @description  Refine your search results by coupon type for GoTo Travel. This is how it should be.
// @author       Soh Satoh
// @match        https://map.goto.jata-net.or.jp/?st=result&*
// @require      https://jpillora.com/xhook/dist/xhook.min.js
// @grant none
// ==/UserScript==

(function () {
    // Add a button to choose between electronic or paper coupons
    // ref: https://www.lisz-works.com/entry/tampermonkey-add-selector
    var selectable_elements = ['デフォルト', '電子クーポン', '紙クーポン'];
    var selectbox = $('<select>')
        .attr({
            name: 'sel',
            id: 'selector',
            style: 'color: white; font-size:' + $('.reset-btn').css('font-size'),
        })

        .on('change', async function () {
            localStorage.setItem('mode', this.selectedIndex);
            location.reload(true);
        })

        .appendTo($('.reset-btn'));

    $.each(selectable_elements, function (i, v) {
        selectbox.append($('<option>').val(v).text(v));
    });

    // Apply the saved setting
    var selector = $('#selector')[0];
    selector.selectedIndex = localStorage.getItem('mode');

    if(selector.selectedIndex == 0) return;

    // Hook XHR
    xhook.after(function (request, response) {
        if(request.url.indexOf('api/point') == -1) return;

        var modified = JSON.parse(response.data);

        var items = modified.items;
        var i = items.length;
        while (i--) {
            if (items[i][selector.value] != '1') {
                items.splice(i, 1);
            }
        }
        response.data = JSON.stringify(modified);
    });
})();

最初にJQueryでページにセレクトボックスを追加します。
デフォルト、電子クーポン、紙クーポンの間で選択可能にし、

localStorage.setItem('mode', this.selectedIndex);

でローカルストレージに設定を保存するようにしています。
本来はGM.setValueを使用するべきなのですが、これを使用するとなぜかXHRにHookできなくなるため断念しました。理由がわかる方はコメントをいただけると幸いです。

次にXHookを使用してresponseを書き換えています。
このスクリプトを使用することで、かんたんにXHR(Ajax)を傍受、改変することが可能です。
本来は外部スクリプトを利用する予定ではなかったのですが、responseの書き換えがどうやってもうまく行かず断念しました。(responseTextの改変は簡単なのですが)

最後に

最初は容易に検索できるよう、Webサイトを作成しようと思ったのですが怒られたくないのでやめました。
「初めから絞込めるようにしろよ」とは思うのですが、まあそれやられるとGoToキャンペーン本来の意味を失う部分もあるのかもしれません。
電子クーポンのほうが不便だなんて意味がわからないですけどね。それならどちらかに統一してくれたほうが便利なんですが。