「1 ページ = 1 案件」ではなかった:1 つのフォームで 6 商品を受け付ける店の記事が、リンクが同じというだけで消されていた

English version

トレカダッシュ 開発の記録 / 2026年8月

iOS アプリ「トレカダッシュ」で、「複数の商品を受け付けている抽選なのに、1 件しか記事が無い」という報告が、2 回、来ました。1 回目に直したつもりでしたが、2 回目が来ました。

この記事は、その真因と、同じ時期に見つけた、「作った項目を、アプリが一度も読んでいなかった」話の記録です。

この記事は、2026 年 8 月 25 日の作業の記録から書いています。

真因:リンクだけで、重複と決めていた

1 回目の報告で、「リンクが同じだから、重複扱いされている」ところまでは、直しました。しかし、すでにある記事が、隠れたままだったので、同じ指摘を、また受けました。

犯人は、runHideDuplicateLinkArticles、つまり、リンクだけで、重複と判断するジョブでした。

実データは、こうでした。ある通販店は、1 つの Google フォームで、6 つの商品の抽選を受け付けています。6 件の記事は、全部、同じ URL です。このジョブが、そのうち 5 件を「重複」として、消していました。利用者からは、1 商品ぶんしか、見えません。

直し方は、まとめる単位を、リンクから、リンク + 商品に変えることでした。同じリンクでも、商品が違えば、別の案件です。商品が分かっていない記事どうしは、区別する手がかりが無いので、これまでどおり、リンクだけで、重複とみなします。

「1 ページ = 1 案件」という前提は、トレカの抽選では成り立ちません。1 つの申込みフォーム、1 つの告知のページで、複数の商品を受け付ける店は、普通にあります。

すでに隠されていた記事は、同じリンクの表示中の記事と、商品または題名が違うものに限って、表示に戻しました(7 件)。ある通販店の 5 件(6 商品すべてが表示される)、大手のゲーム店 1 件、別のチェーン 1 件です。

サーバが作った「応募枠」を、アプリが一度も読んでいなかった

8 月 23 日から、サーバーは、応募の条件を AI で読んで、「応募枠」(entryTiers)を取り出していました。「プレイヤーズクラブ:本人認証済みの枠と、未認証の枠」「A グループと B グループ」「ビックカメラの Suica カード会員限定」といったものです。実データにも、ちゃんと入っていました。

ところが、iOS のアプリが、この項目を、一度も読んでいませんでした。AI の費用だけを払って、利用者には、見えない状態です。アプリに、項目を足し、詳細の画面に、「応募枠」として表示するようにしました。

サーバーとアプリの項目の突き合わせは、コマンドで見つかります。アプリが読む項目を、ソースから機械的に抜き出し(grep)、Firestore の実データと比べます。

商品の一覧に、告知文が混ざっていた

「ONE PIECE カードゲームコーナー【事前入店申込・抽選】8 月 31 日(月)JUMP SHOP 東京駅店」のような、イベントの告知が、商品として登録されていました。

言い回しを並べる方式は、追いつきません。そこで、具体的な日付という、一般的な規則で弾きました。トレカの商品名に、「8 月 31 日」のような暦の日付は入りません。「Vol.3」「第 2 弾」「2025 年 19 号」は日付ではないので、影響しません。10 個のパターンで試して、食い違いは 0 件でした。すでにある 6 件を削除しました。

分かったこと

前提を疑う。作ったものが、使われているかを確かめる。

この話に出てくるもの

ほかの記録

コメント

感想や、記事の間違いの指摘は、ここへ。書くには、GitHub のアカウントが要ります。

押すと、giscus(giscus.app)と GitHub に接続します。押さなければ、接続しません。詳しくはあつかいに書いています。