1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

メルカリの検索結果からSOLDを削除するUser Script

Last updated at Posted at 2021-04-02

どんな講釈をヌかそうと、要らないものは要らない。

・メルカリが検索結果に「売れた商品」も表示するのはなぜ? 商品検索におけるUI/UXの考え方 - ログミーTech
https://logmi.jp/tech/articles/321231

邪魔だから消してみると何が起きるかと言うと、全KPIがすべて下がります。並みの勢いじゃないですよ。出品転換率、つまり1人のお客様が出品行動を取ったという行動も減るし、買ったという行動も減ります。

その結果、結局取引総数も取引総額もすべて下がって、負のスパイラルに入る。それで慌てて元に戻すというのを、実はUSとJPを合わせて、4~5回は繰り返しているんじゃないかと思います(笑)。

いったい、なぜなのか? 長らく謎でした。ちなみに創業者の山田進太郎は「ユーザーインタビューとかで、邪魔だからと言われているので消してもいいですよね?」と言われたとき、「いや、俺はあったほうがいいと思うけどね」と言ったそうです。

「なんか知らないけど、あったほうがいいと思う」と言ったと。3年前くらいですね。直感的にわかっている感じでした、あの人は(笑)。予言していたんです。

僕は「こういうことなんだろうな」という仮説があるんです。検索改善をしていて、僕がうまくいったときというのは、必ずさっきの購買転換率が上がるんです。

「やった! 検索結果がよくなって統計上有意に買う人が増えた! 買う数が増えた!」と思うと同時に、出品する人も増えるんですね。「なんで検索改善しているのに出品する人が増えるんだ? 俺は出品を増やそうとはしていないんだけど」と思っていました。

:thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking::thinking:

結局、行き着いた答えが「出品しようとしたときに検索してるんだ」ということです。つまり、買おうとする人もいるし、売ろうとする人もいる。Nintendo Switchを持っている人が売ろうとしたときに、「Nintendo Switch」と検索して何を見ているかという話ですね。

転売ヤーの気持ちなんか知るかヴォケ。
真っ当な購買には最低のUXですね。

環境

  • Tampermonkey
  • メルカリの検索結果

User Script

案① 検索結果から売り切れを削除する.

User Script
// ==UserScript==
// @name         案① 検索結果から売り切れを削除する.
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.mercari.com/jp/search/?*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // Your code here...
    document.querySelectorAll('div.items-box-content section').forEach(function(section) {
        if(section.querySelectorAll('div.item-sold-out-badge').length > 0) {
            section.parentNode.removeChild(section);
        }
    });
})();

安心感が強い半面、詳細検索と共存出来ない残念さがある。

image.png
div.item-sold-out-badgeのある section を削除する。

案② 画面移動

パラメータが keyword のみの場合、画面上部からの検索だと判定し、その場合には 販売中 の検索条件を追加した場合のURLに移動する。

User Script
// ==UserScript==
// @name         案② 画面移動.
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.mercari.com/jp/search/?*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Your code here...
    let querys = [...new URLSearchParams(window.location.search).entries()].reduce(function(obj, e) {return {...obj, [e[0]]: e[1]}}, {});
    console.info(Object.keys(querys).length);
    if(Object.keys(querys).length == 1) {
        if(querys.keyword) {
            location.replace(location.href + '&status_on_sale=1');
        }
    }
})();

JavaScriptでQuery Stringを解釈する楽しさはあるが、全体的にはナンセンス。

案③ デフォルトの検索条件に付与 (1shot)

inputtypesearch のものを画面上部の検索ボックスとして扱い、同 form 中に 販売中 の検索条件のための hidden を追加する。

User Script
// ==UserScript==
// @name         案③ デフォルトの検索条件に付与 (1shot)
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.mercari.com/*
// ==/UserScript==

(function() {
    'use strict';

    // Your code here...
    setTimeout(function() {
        document.querySelectorAll('input[type="search"]').forEach(function(e) {
            let p = e.parentNode;
            let div = document.createElement('div');
            let f = function (key, val) {
                let input = document.createElement('input');
                input.type = 'hidden';
                input.name = key;
                input.value = val;
                return input;
            };
            div.appendChild(f('status_on_sale', '1'));
            p.removeChild(e);
            div.appendChild(e);
            p.prepend(div);
        });
    }, 1);
})();
  • before
    image.png
  • after
    image.png

読み込み後の謎な処理で、form内のエレメントが2つに戻されるクソみたいな挙動があるので。独自タグでwarpして退避している。たまにうまく反応してくれないときもあるので要調整。

案④ デフォルトの検索条件に付与 (observer)

inputtypesearch のものを画面上部の検索ボックスとして扱い、同 form 中に 販売中 の検索条件のための hidden を追加する。
案③だと、たまに戻されてしまうので、親ノードを監視して再設定させる。 (多重で付かない様に、無かったら追加する。)

User Script
// ==UserScript==
// @name         案④ デフォルトの検索条件に付与 (observer)
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.mercari.com/*
// ==/UserScript==
(function() {
    'use strict';

    // Your code here...
    let f = function(p) {
        let div = document.createElement('div');
        let a = function(name, val) {
            if(p.querySelectorAll('input[name="' + name + '"]').length == 0) {
                let input = document.createElement('input');
                input.type = 'hidden';
                input.name = name;
                input.value = val;
                p.appendChild(input);
            }
        }
        a('status_on_sale', '1');
    }


    document.querySelectorAll('input[type="search').forEach(function(e) {
        let p = e.parentNode;
        // first
        (function() {
            f(p);
        })();
        // observer
        (function() {
            let observe;
            let observer = new MutationObserver(function() {
                observer.disconnect();
                f(p);
                observe();
            });
            observe = function() {
                observer.observe(p, {
                    childList:true,
                });
            }
            observe();
        })();
    });
})();
  • before
    image.png
  • after
    image.png

案③のformエレメントに追加しても削除されてしまう問題について、observerで潰した版。
詳細検索と衝突せず、TOP並びに検索画面に埋め込めた。一番美しい気がする。

以上。

参考 (謝辞)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?