Forest Book
Shopifyの顧客データには4通りの「消し方」がある ― APIから見た挙動の違いと連携アプリの設計

Shopifyの顧客データには4通りの「消し方」がある ― APIから見た挙動の違いと連携アプリの設計

2026年7月20日

Shopifyの管理画面には、顧客に対して「アカウントを無効にする」「お客様情報を統合」「個人データを消去」「お客様情報を削除」という4つの操作があります。日本語のラベルだけを見ると似たような操作に見えますが、APIから顧客情報を取得したときの挙動はこの4つでまったく異なります。この違いを知らないまま外部システムと顧客IDで連携すると、ある日突然、連携先で顧客が見つからなくなったり、氏名が空になったりします。本記事では、4つの操作がAPIにどう影響するかと、連携アプリ側で持つべきハンドリングを整理します。Shopifyでカスタムアプリや外部連携を設計する技術者、そして顧客情報の取り扱いを検討しているEC事業者に向けた内容です。

4つの操作は「レコードが残るか」「PIIが残るか」で分かれる

先に結論を表にすると、APIから見た結果は次の4パターンです。

管理画面の操作

顧客IDでのクエリ結果

個人情報(PII)

アカウントを無効にする

これまでどおり取得できる

すべて残る

お客様情報を統合

消えた側のIDは null

残った側に集約される

個人データを消去

オブジェクトは返る

氏名・住所などがマスクされる

お客様情報を削除

null

消える

つまり、「レコードごと消えるケース(統合・削除)」と「レコードは残るが中身が抜けるケース(消去)」の2系統があるというのが要点です。連携アプリはこの両方を想定しておく必要があります。

アカウントの無効化は、データには何も起きない

「アカウントを無効にする」は、名前から受ける印象に反して、顧客レコードには一切影響しません。APIでは従来どおり全フィールドが取得でき、変わるのは stateDISABLED になることだけです。メールアドレスも住所も注文履歴もそのまま返ります。

ここで注意したいのが、state の意味です。これはクラシック顧客アカウント(パスワードでログインする旧方式)のログイン可否を表すフィールドであり、新しい顧客アカウント(メールのワンタイムコードでログインする方式)のログイン可否とは連動しません。管理画面の警告文にも「無効にしても新しいバージョンのお客様アカウントでは引き続きログインできます」と書かれているとおりです。

したがって、state を見てログイン可能な顧客かどうかを判定する実装は、新顧客アカウント環境では誤判定になりますstate: DISABLED の顧客が普通にログインしてくる状況が起こり得るためです。ログイン状態の判定は state ではなく、実際のセッション情報(App Proxy経由の顧客ID、あるいはCustomer Account APIのトークン)で行うのが正解です。当社では、既存の連携アプリを引き継ぐ際にこの実装が残っていないかを確認するようにしています。

統合は「旧IDが消える」のが最大の落とし穴

「お客様情報を統合」は、2つの顧客レコードを1つに集約する操作です。統合されると、消えた側の顧客IDでクエリしても null が返ります。レコードが存在しなくなるためです。残った側のIDでは、注文・住所・タグなどが集約された統合後のデータが返ります。

外部システムとShopifyの顧客IDで紐付けをしている場合、これは深刻な事故につながります。連携先のDBが持っている顧客IDが、店舗側のちょっとした整理作業で無効になるからです。しかも統合は非同期のジョブとして実行されるため、処理中に問い合わせると中途半端な状態が見えることもあります。

対策は明確で、顧客IDで外部連携をしているアプリは、統合を通知するWebhookの購読が実質的に必須です。このWebhookは新旧IDのマッピングを届けてくれるので、受け取ったタイミングで連携先の顧客IDを付け替えられます。逆にこれを購読していないと、旧IDのまま孤立したレコードが連携先に残り続けます。

「消去」と「削除」は似て非なるもの

もっとも混同されやすいのがこの2つです。

「個人データを消去」は、氏名・住所・メール・電話といった個人情報をマスクする操作です。顧客プロファイルと注文履歴自体は残るため、APIではクエリが成功してオブジェクトが返ってきます。ただし個人情報にあたるフィールドは null またはマスク済みの値になり、レコードは編集不可になります。アプリ側には個人データの消去を求めるWebhookが送られ、アプリが保持しているデータの削除義務が発生します。このWebhookはリクエスト直後に届くわけではなく、直近に注文がある顧客は一定期間の経過後に送信される点にも注意が必要です。

一方の「お客様情報を削除」は、レコードごと完全に消える操作です。IDでクエリすると null が返り、一覧・検索からも消えます。ただし注文がある顧客は削除できません。削除できるのは注文がゼロの顧客だけで、これが「消去」と「削除」の使い分けの根拠になっています。注文履歴を会計上の理由で保持しなければならない以上、注文のある顧客はマスクするしかない、というわけです。

「削除したのにAPIが返ってくる」ときに疑うこと

現場でよく遭遇するのが、管理画面で削除したはずなのにAPIからレスポンスが返ってくる、という状況です。原因は可能性の高い順に次のとおりです。

もっとも多いのが、即時削除ではなく「削除リクエスト」として受理されているケースです。注文履歴のある顧客はその場では削除できず、管理画面には削除ボタンの代わりに削除要請のリンクが出ます。リクエスト方式で処理される場合、送信後しばらくはキャンセル可能な猶予期間があり、さらにチャージバックへの備えとして注文発生から一定期間(半年程度)は削除が保留されます。つまり直近に注文がある顧客なら、実際にデータが消えるのは数か月後で、それまでAPIは普通に応答します。管理画面の顧客ページに消去リクエスト送信済みのセクションが出ていれば、このパターンで確定です。

判定を確実にするには、対象の顧客に対して削除可能かどうかを示すフィールドと注文件数を取得してみるのが早道です。削除不可かつ注文が1件以上あれば、保留パターンです。

そのほか、一覧・検索クエリは検索インデックスの反映ラグで古い結果を返すことがあるため、IDを直接指定したクエリの結果が正であること、注文経由で顧客情報を参照している場合は注文側に残る参照から情報が見えること、そしてアプリやCDNのキャッシュが古いレスポンスを返しているだけ、といった落とし穴もあります。

連携アプリが持つべきハンドリング

以上を踏まえると、外部システムと顧客情報を連携するアプリが備えるべき挙動は3つに整理できます。

第一に、顧客IDが null になるケース(統合・削除)への耐性です。連携先のレコードを孤児にしないよう、統合Webhookで付け替え、削除は連携先の論理削除に落とす、といった設計が必要です。

第二に、PIIが欠落するケース(消去)への耐性です。氏名や住所が null で返ってきたときにエラーで落ちるのではなく、マスク済みとして扱えること。消去済みレコードは更新もできないため、書き戻し処理も例外にする必要があります。

第三に、個人データの消去・削除を求めるWebhookの実装です。これは連携の都合ではなく、アプリ提供者としての義務にあたる部分です。当社では、この種の共通ハンドラはアプリごとに書くのではなくテンプレートに標準搭載し、個別実装の裁量から外す方針を取っています。コンプライアンス処理は「毎回正しく書く」よりも「書かなくても正しく動く」構造にしたほうが確実だからです。

まとめ

Shopifyの「消す」操作は4種類あり、APIから見た結果は「無効化=変化なし(state のみ)」「統合=旧IDは null」「消去=オブジェクトは返るがPIIが空」「削除=null」と、それぞれ異なります。管理画面のラベルの印象と実際の挙動がずれているものが多く、特に無効化がデータに影響しないこと、統合が旧IDを消すこと、削除が注文のある顧客には効かないことの3点は、連携設計の前提として押さえておく価値があります。顧客IDを外部システムのキーにするなら、そのIDはいつか消えるかもしれないという前提で設計しておくのが安全です。