STB Tracker の情報源

このページは、STB Tracker がどの情報源をもとに店舗情報や訪問情報を扱っているかをまとめるものです。

まず全体像だけをつかみたい場合は、次の図から見てください。STB Tracker が扱う情報は、公式サイトで公開されている店舗情報と、利用者本人がログイン済みの画面で確認できる訪問情報に分かれます。

STB Tracker の情報源の全体像。公式サイトの公開店舗情報と、利用者本人のマイストアパスポート画面から得られる訪問情報を、STB Tracker が整理して stores シート、通知、マイマップ用ファイルへつなげる流れ。
STB Tracker の情報源の全体像。公式サイトの公開店舗情報と、利用者本人のマイストアパスポート画面から得られる訪問情報を、STB Tracker が整理して stores シート、通知、マイマップ用ファイルへつなげる流れ。

☕️ はじめに

STB Tracker は、スターバックス コーヒー ジャパンが公開している店舗情報と、利用者本人がログイン済みのマイストアパスポート画面で確認できる訪問情報をもとに動作します。

このアプリは、非公開の管理画面、不正に取得したデータベース、第三者から購入した名簿、利用者の認証情報を預かる仕組みなどには依存していません。店舗情報については、通常のブラウザーから確認できる公式サイト上の情報を読み取り、訪問情報については、利用者本人が自分のブラウザーで閲覧できるマイストアパスポート上の情報だけを取り込みます。

つまり STB Tracker の情報源は、大きく分けると次の 2 系統です。

この区別は大切です。店舗情報は公式サイトが一般に公開している情報を整理し直すものですが、マイストアパスポート情報は利用者本人の会員アカウントに紐づく情報です。そのため STB Tracker では、マイストアパスポート情報を本サービス提供者のサーバーへ集めたり、他の利用者と共有したりする設計にはしていません。

また、STB Tracker が出力する情報は、スターバックス コーヒー ジャパン公式サイトを見やすく整理するための補助情報です。営業時間、休業、閉店、価格区分、提供サービスなど、実際の来店前に重要な情報は、必ず公式サイトや店舗側の案内を確認してください。

このページに載せている XML、JSON、HTML などのコードブロックは、構造を説明するための例です。読み取る場所が分かるように、必要な部分だけを抜き出しています。基本的には架空の値に置き換えていますが、公式ページに実際に出る短い文言を、構造説明のために最小限だけ使うことがあります。

☕️ 店舗情報の取得

店舗情報は、公式サイトの中でも役割の異なる複数の情報源を組み合わせています。

まず「どの店舗を見に行くべきか」を サイトマップ から取得し、各店舗の基本情報を 店舗詳細ページ から読み取ります。オープン予定店舗かどうかは 新店舗情報 JSON で補い、店舗の形態やサービスの有無は 店舗検索 API から取得します。

この章で使う用語は、以後の説明でも同じ意味で使います。

🦶 サイトマップ

サイトマップ は、公式店舗サイト全体に含まれる店舗詳細ページを探すための入口です。

サイトマップで分かるのは、「公式店舗サイト上に、どの店舗詳細ページが存在するか」です。STB Tracker は、その中から https://store.starbucks.co.jp/detail-{数字}/ 形式の URL を拾い、detail- の後ろの数字を store_id として扱います。

構造を最小限にすると、次の形です。

<urlset>
          <url>
            <loc>https://store.starbucks.co.jp/detail-1234/</loc>
          </url>
          <url>
            <loc>https://store.starbucks.co.jp/detail-5678/</loc>
          </url>
        </urlset>

一方で、サイトマップだけでは、店舗名、住所、営業時間、営業状態、店舗属性などは分かりません。サイトマップはあくまで入口であり、詳細な店舗情報は次の 店舗詳細ページ から読み取ります。

サイトマップは、閉店検出の入口にもなります。通常の店舗情報取得で一度観測済みの store_id が、今回のサイトマップから消えている場合、STB Tracker はその店舗を閉店扱いにします。

注意点として、サイトマップに載っている店舗がすべて営業中とは限りません。オープン前の店舗が含まれることがあるため、サイトマップだけで active と決めず、後述の 新店舗情報 JSON と照合して preopen を判定します。

🦶 店舗詳細ページ

店舗詳細ページ は、各店舗の基本情報の中心になる情報源です。

店舗詳細ページには、画面上に表示される本文のほかに、構造化データとして JSON-LD が埋め込まれています。STB Tracker では、この JSON-LD のうち @typeRestaurant のブロックを、店舗基本情報の主な情報源として扱います。

JSON-LD は、HTML の中に次のような形で埋め込まれている構造化データです。

<script type="application/ld+json">
        {
          "@context": "https://schema.org",
          "@type": "Restaurant",
          "@id": "https://store.starbucks.co.jp/detail-1234/",
          "name": "サンプルシティ中央通り店",
          "address": {
            "addressRegion": "東京都",
            "addressLocality": "サンプル市",
            "streetAddress": "中央1-2-3",
            "postalCode": "100-0000"
          },
          "geo": {
            "latitude": 35.000000,
            "longitude": 139.000000
          },
          "url": "https://store.starbucks.co.jp/detail-1234/",
          "openingHoursSpecification": [
            {
              "dayOfWeek": ["Monday", "Tuesday"],
              "opens": "07:00",
              "closes": "22:00"
            }
          ]
        }
        </script>

JSON-LD から取得する情報は次のとおりです。

STB Tracker の列 店舗詳細ページ上の主な情報源
name JSON-LD の name
address JSON-LD の addressRegionaddressLocalitystreetAddress
prefecture address の先頭から抽出した都道府県
postal_code JSON-LD の postalCode
latitude / longitude JSON-LD の geo.latitude / geo.longitude
store_url JSON-LD の url
hours_raw JSON-LD の openingHoursSpecification

一方で、JSON-LD だけでは取れない情報もあります。特定立地価格ドリンクサイズ制約休業状態 は、店舗詳細ページの HTML 文字列から判定します。

ここは DOM として解析しているのではなく、取得した HTML に対する文字列検索・正規表現検索です。具体的な判定条件は次のとおりです。

STB Tracker の列 読み取る内容
pricing_tier 本文中の 特定立地価格\s*([AB])適用店舗 に一致した A / B
drink_size 本文中に トールサイズのみの提供となります があれば tall_onlyショートサイズの販売を実施しておりません があれば no_short
status store-detail__text-detail クラスの <div>...</div> 範囲内に 休業中 があれば suspended、それ以外は active

該当する文字列は、現在の HTML では備考欄や注意書きの近くに現れます。

<div class="store-detail__text-title">備考</div>
        <div class="store-detail__text-detail number-text">
          ...<br />当店舗はすべてのドリンクについて、トールサイズのみの提供となります。
        </div>

        <div class="store-detail__text-notice">
          <div class="notice-icon">※</div>
          <div class="notice-text">
            特定立地価格 A適用店舗です。
          </div>
        </div>

        <div class="store-detail__text-title">営業時間</div>
        <div class="store-detail__text-detail number-text">
          休業中
        </div>

このように、本文側の情報は同じページの中でも置き場所が分かれます。STB Tracker の判定自体は文字列検索ですが、不具合調査では「HTML 上のどの欄の文言が変わったか」を見ると原因を追いやすくなります。

なお、status だけは store-detail__text-detail というクラス名にも依存します。このクラス名が変わった場合、HTML 上に 休業中 と表示されていても suspended として検出できません。

ここでの注意点は、表示上の見た目だけに頼りすぎないことです。店舗詳細ページには、画面表示用の HTML、構造化データ、スクリプト内の文言など、似た文字列が複数の場所に現れることがあります。たとえば「休業中」という文字は画面表示以外のテンプレートにも含まれることがあるため、STB Tracker では営業時間欄の本文として現れる「休業中」を見ます。

また、営業時間は表示用の日本語テキストではなく、JSON-LD の openingHoursSpecification をもとに、曜日順を固定した 1 行の表現へ正規化しています。これは、差分検出のためです。見た目の改行や順序の揺れに影響されず、実質的な営業時間の変更だけを追いやすくするため、同じデータを毎回同じ形に整えています。

店舗詳細ページは、公式サイトの表示内容そのものに近い情報源です。そのため、取得できる情報は分かりやすい反面、サイトの HTML 構造変更の影響を受けます。もし公式サイト側の構造が変わり、JSON-LD の位置や本文の表現が変わった場合は、STB Tracker 側の読み取りロジックも見直す必要があります。

コラム: 変わっていないページは取りに行かない

店舗詳細ページは店舗数の分だけ URL があるため、毎回すべてのページ本文を取り直すと公式サイトへの不要な負荷につながります。STB Tracker では、HTTP の ETagLast-Modified を保存し、次回取得時に If-None-Match / If-Modified-Since を付けた条件付き GET を行います。公式サイト側から 304 Not Modified が返った場合は、ページ内容に変化がないものとして前回保存した情報を再利用し、HTML 本文は受け取りません。

同じように公開サイトの情報を継続的に確認する仕組みを作る場合も、「全ページを毎回取得する」前提にせず、ETag や Last-Modified、取得頻度の制限、差分検出の分離などを組み合わせて、公式サイトに余計な負荷をかけない設計にすることをおすすめします。

🦶 新店舗情報 JSON

新店舗情報 JSON は、オープン予定店舗を判定するための補助的な情報源です。

公式サイトでは、まだ営業開始前の店舗が店舗詳細ページやサイトマップに現れることがあります。これは利用者にとって便利な情報ですが、単純にサイトマップへ載っていることだけを見てしまうと、オープン予定店舗まで営業中として扱ってしまいます。

そこで STB Tracker では、新店舗情報 JSON に載っている idopen_date を参照します。判定条件は、サイトマップに含まれる store_id と新店舗情報 JSON の id が一致し、かつ open_date が実行日より未来であることです。この条件を満たす店舗を preopen として扱います。

新店舗情報 JSON は、構造としては次のような配列です。

[
          {
            "id": "1234",
            "name": "サンプルシティ中央通り店",
            "en_name": "Sample City Chuo-dori",
            "open_date": "2026-06-01"
          },
          {
            "id": "5678",
            "name": "サンプル駅前店",
            "en_name": "Sample Station",
            "open_date": "2026-06-15"
          }
        ]

この情報源の役割は、店舗詳細ページの情報を置き換えることではありません。あくまで「サイトマップにある店舗を、営業中として扱うべきか、オープン予定として扱うべきか」を判定するための補助です。店舗名、住所、位置情報などの基本情報は、引き続き 店舗詳細ページ を主な情報源にします。

注意点として、新店舗情報 JSON が一時的に取得できない場合でも、店舗情報全体の取得を止めるほどの致命的な問題ではありません。その場合、STB Tracker はオープン予定判定だけを諦め、サイトマップと店舗詳細ページをもとに処理を続けます。オープン予定判定は便利な上乗せ情報ですが、店舗一覧の基本取得とは分けて考えています。

🦶 店舗検索 API

店舗検索 API は、公式店舗検索ページが内部で利用している検索用の情報源です。

店舗詳細ページだけでは、店舗属性を安定して取得できません。STB Tracker が扱う店舗属性は、ドライブスルー、サービス エリア、駅構内、空港、リージョナル ランドマーク ストア、リザーブ販売店舗、ティー & カフェ、ブック カフェ、My フルーツ³ フラペチーノ、Family Friendly、アルコール提供、Clover Vertica です。これらは店舗検索ページの絞り込み条件やキーワード検索としては扱われていますが、店舗詳細ページ上では一貫した形で取得できるとは限りません。

そこで STB Tracker では、店舗検索 API に条件を指定し、「その属性に該当する店舗 ID の集合」を取得します。たとえば、ドライブスルーに該当する店舗、リージョナル ランドマーク ストアに該当する店舗、ティー & カフェに該当する店舗、といった単位で検索し、返ってきた store_id に対応する行へ 1 を入れます。

リクエストは、属性ごとに条件を変えて投げます。ドライブスルー店舗を探す場合は、fqstore_type:3 を指定します。

GET https://hn8madehag.execute-api.ap-northeast-1.amazonaws.com/prd-2019-08-21/storesearch
          ?size=100
          &start=0
          &q.parser=structured
          &q=matchall
          &fq=%28and%20store_type%3A3%29

レスポンスは CloudSearch 風の JSON で、STB Tracker が主に見るのは fields.store_id です。

{
          "hits": {
            "found": 2,
            "hit": [
              {
                "fields": {
                  "store_id": "1234"
                }
              },
              {
                "fields": {
                  "store_id": "5678"
                }
              }
            ]
          }
        }

この API から STB Tracker が列へ反映するのは「該当する店舗 ID」です。店舗名や住所などの基本情報は 店舗詳細ページ を正とし、店舗検索 API は属性フラグを補うために使います。情報源ごとの役割を分けることで、同じ項目を複数の場所から拾って矛盾させないようにしています。

STB Tracker で扱う店舗属性と、店舗検索 API に渡す条件は次のとおりです。

STB Tracker の列 意味 店舗検索 API の条件
drive_through ドライブスルー store_type:3
service_area サービス エリア service_area:1
station 駅構内・駅関連店舗 station:1
airport 空港店舗 airport:1
regional_landmark リージョナル ランドマーク ストア regional_landmark_flg:1
reserve スターバックス リザーブ取扱店舗 reserve_flg:1
tea_cafe スターバックス ティー & カフェ tea_cafe:1
book_cafe ブック カフェ book_cafe:1
my_fruit My フルーツ³ フラペチーノ取扱店舗 my_fruit_flg:1
family_friendly Family Friendly 店舗 family_friendly_flg:1
alcohol アルコール提供店舗 seasonal3:1
clover_vertica Clover Vertica 対応店舗 キーワード検索: q=(and record_type:1 'cloververtica')fq=(and data_type:'prd')

店舗検索 API には、この表に載せていない条件もあります。Mobile Order & Pay無線LANサービススターバックス カード は、公式サイト側では絞り込み・表示に使われている情報ですが、STB Tracker では取得対象にしていません。

理由は、これらに該当する店舗が非常に多く、店舗巡りの管理上の絞り込み情報としては相対的に重要度が低いためです。大量の該当店舗を取得するには、そのぶんページングのリクエストも増えます。公式サイト側への負荷を増やさず、STB Tracker 側の処理時間も短く保つため、利用価値が高い属性に絞って取得しています。

店舗検索 API には、1 回のリクエストで返る件数に上限があります。そのため、該当店舗が多い属性では、ページングしながら全件を集める必要があります。一方で、むやみに並列化したり、短時間に大量のリクエストを投げたりするべきではありません。STB Tracker では、属性ごとに順番に取得し、必要なページだけをたどる方針にしています。

もうひとつの注意点は、API 側が公式サイトの店舗検索画面からの利用を前提としていることです。ブラウザー上の店舗検索ページと同じ文脈で呼び出されることを期待しているため、通常の機械的な HTTP クライアントからの呼び出しでは拒否されることがあります。これは「秘密の API に認証情報が必要」という意味ではなく、公式サイトのフロントエンドが使っている公開画面向けの API であっても、リクエストの前提条件がある、ということです。

🦶 店舗情報を組み合わせる考え方

STB Tracker では、ひとつの URL からすべてを取ろうとはしていません。情報源ごとに得意な役割が違うためです。

役割 主な情報源
現在追跡する店舗 ID の一覧 サイトマップ
店舗名、住所、位置、営業時間などの基本情報 店舗詳細ページ
オープン予定かどうか 新店舗情報 JSON
店舗形態やサービスの属性 店舗検索 API
閉店したかどうか 通常の店舗情報取得で一度観測済みの店舗がサイトマップから消えたこと

この分担を守ると、データの矛盾を減らせます。たとえば、店舗検索 API の検索結果にも店舗名らしき情報が含まれる場合がありますが、基本情報の正本は 店舗詳細ページ に寄せます。逆に、店舗詳細ページから安定して取れない属性は、無理に HTML から拾わず 店舗検索 API に寄せます。

また、閉店は「閉店と書かれたページを探す」のではなく、「以前はサイトマップに存在した店舗詳細ページが、今回のサイトマップから消えた」と見ます。公式サイト上で到達できなくなった店舗を追跡するには、この考え方の方が自然です。

取得の頻度や範囲についても、公式サイトへの負荷を避けることを前提にしています。全店舗を頻繁に取り直すのではなく、日次程度の確認にとどめ、同じ情報源へ不必要なアクセスを繰り返さない設計にすることが大切です。

☕️ マイストアパスポート情報の取得

マイストアパスポート情報は、店舗情報とは性質が違います。

店舗情報は公式サイトで一般公開されている情報ですが、マイストアパスポート情報は、利用者本人のスターバックス会員アカウントでログインしたときに見える訪問情報です。そのため STB Tracker では、利用者本人が自分のブラウザーでマイストアパスポート画面を開き、その画面上に存在する情報だけを取り込み対象にします。

STB Tracker がやらないと決めていることのひとつに、利用者の代わりにスターバックス公式サイトへログインすることがあります。会員 ID やパスワードなどの大切な情報を預かりたくありませんし、今後 ログイン2段階認証 が本格化していく中で、それをかいくぐるような実装をするべきではないからです。

そのため、マイストアパスポート情報は店舗情報のように自動取得できません。少し手間はかかりますが、利用者本人がログイン済みの画面を開き、その場で自分の情報を取り込む形にしています。

マイストアパスポート連携の使い方や、取り込んだ訪問情報の扱いについては、マイストアパスポート連携ガイドプライバシー ポリシー利用規約 も確認してください。

この章では、「マイストアパスポート画面上のどの情報を、何として扱っているか」に絞って説明します。

🦶 マイストアパスポート画面の訪問情報

マイストアパスポート画面の訪問情報 は、利用者本人の訪問記録を取り込むための情報源です。

この画面は、スターバックス会員としてログインしている利用者本人が、自分の訪問履歴を確認するためのページです。STB Tracker は、利用者本人がすでにログインして表示している画面上の情報を読み取ります。

マイストアパスポート画面には、スタンプ帳に表示される店舗情報が、画面表示用のデータとして保持されています。STB Tracker は、その中から店舗ごとの訪問情報を抜き出し、store_id をキーにして stores シートへ対応づけます。

画面上のデータは、構造としては次の形です。

window.Stamp = {
          store_all: [
            {
              store_id: 1234,
              name: "サンプルシティ中央通り店",
              first_visit_date: "2025-04-10 12:34:56",
              last_visit_date: "2026-05-01 09:00:00",
              frequency_of_visits: 3,
              limited_area: 0,
              is_exist: true
            }
          ]
        };

この方法では、利用者本人が見ている範囲の情報だけを扱います。一方で、画面上のデータ構造に依存するため、公式サイト側の画面構造が変わると、必要な情報が見つからなくなることがあります。

STB Tracker では、次の項目を扱います。

STB Tracker の列 マイストアパスポート画面で見る内容 反映条件
store_id 店舗 ID 1〜8 桁の数字だけを受け付ける
name 店舗名 シートで安全な文字列にして、最大 120 文字まで保持する
first_visit_date 初訪問日 値の先頭が YYYY-MM-DD 形式に一致したときだけその 10 文字を使い、既存値が空のときだけ埋める
last_visit_date 最終訪問日 値の先頭が YYYY-MM-DD 形式に一致したときだけその 10 文字を使い、現在値に合わせて更新する
frequency_of_visits 訪問回数 parseInt で 0 以上の整数になればその値を使い、不正な値は 0 にする
limited_area 限定エリア店舗かどうか true / 1 / '1' / 'true' なら 1、それ以外は 0 にする
status 現存店舗かどうか マイストアパスポートにだけ現れる店舗を扱うときの補助情報として参照する。is_existfalse / 0 / '0' / 'false' なら closed、それ以外は active として扱う

store_id は、店舗情報側とマイストアパスポート情報側を結びつけるキーです。マイストアパスポートに載っている訪問済み店舗と、公式店舗サイトから取得した店舗詳細ページの store_id が一致すれば、同じ店舗として扱えます。

limited_area は、stores シート読本 でも触れている「非公開店舗」を表すフラグです。限られた利用者だけが入れるエリアにあって、公開されている店舗一覧には出てこない店舗でも、Web 登録済みスターバックス カードで支払いをすると、マイストアパスポートに記録される場合があります。こうした店舗は、通常の店舗検索やサイトマップだけでは見つけにくく、マイストアパスポート情報を通じて STB Tracker に現れます。

注意点として、マイストアパスポートにだけ現れる店舗は、店舗詳細ページやサイトマップから十分な基本情報を取得できないことがあります。その場合、STB Tracker ではまず store_id と訪問情報を持つ「骨組み」の行として扱い、住所や緯度経度などの基本情報は空のままにします。後日、公式店舗サイト側で情報が取得できるようになれば、通常の店舗情報取得で補完されます。

🦶 画面上の補助属性

画面上の補助属性 は、マイストアパスポート画面に表示される要素や、その要素に付随する属性から読み取る情報です。

マイストアパスポート画面では、中心となる店舗データのほかに、店舗ごとのリンクや表示要素にも店舗 ID、店舗名、最終訪問日、訪問回数、限定エリア店舗かどうか、現存店舗かどうかといった情報が付いている場合があります。

補助属性は、画面上のリンク要素に次の形で付いていることがあります。

<a class="modal-trigger"
           data-store_id="1234"
           data-name="サンプルシティ中央通り店"
           data-last_visit="2026-05-01 09:00:00"
           data-frequency_of_visits="3"
           data-limited_area="0"
           data-is_exist="true">
          サンプルシティ中央通り店
        </a>

STB Tracker では、中心となる訪問情報に含まれていない店舗がある場合だけ、画面上の補助属性も確認します。同じ store_id が複数の場所で見つかった場合は、同じ店舗を重複して取り込まないようにします。