1. レビュー・プロセスのハイレベルな俯瞰
Store への ChatGPT App の公開は「リンクを上げて終わり」ではなく、明確なライフサイクルです。ざっくり言うと、App を準備して審査に出し、レビュアーが自分たちのチェックリストで検証し、あなたは指摘を受けて直し、再提出する——これを全員が納得するまで何度か繰り返します。
これを小さなワークフローとして捉えるのが最も分かりやすいでしょう。
flowchart TD A[Dev Mode / Internal beta] --> B[Submit to Store] B --> C[Under review] C -->|Approved| D[Published] C -->|Changes requested| E[Fixes & Iteration] E --> B D --> F[Updates] F --> C D --> G[Paused / Unpublished]
初期段階(Dev Mode や社内ベータ)では技術的・UX の問題を洗い出します。「Submit to Store」を押した瞬間から、より形式的なレビューが始まります。コンテンツポリシーへの適合、権限設定、安定性、そしてリスティングや法的文書の内容がチェックされます。
ここでの基本姿勢は「一度受かれば二度と戻らない試験」でも「落ちたら終わり」でもないということです。これはあなたとプラットフォームの間の継続的なフィードバック・チャネルです。Store はあなたの App を安全で、分かりやすく、安定したものにしたい。そしてあなたはユーザーに届けて一週間で取り下げられたくない。実は利害は一致しているのです。
2. 審査に提出するもの
プラットフォーム側の誰かがあなたの App を開く前に、あなたはごく一般的な一式を埋めます。
- App のメタデータ: 名前、サブタイトル、カテゴリ、アイコン。
- リスティングの説明: 短文と詳細説明、シナリオ例。
- リンク: Privacy Policy、Terms、Support/Contact。
- 権限設定: App が要求するアクセス(例: OAuth、外部 API、決済モードなど)。
- 場合によっては、レビュアー向けのテストシナリオやアカウントの説明。
- App 本体: MCP サーバー、UI バンドル、system‑prompt、プラットフォームがすでに Dev Mode/production‑URL で把握している tools の説明。
技術的には、この時点であなたはすでにプロダクション版を(多くの場合 Vercel などに)デプロイしており、Store はそこにアクセスします。つまり「Submit」ボタンはコードのデプロイではなく、そのステータスの変更を意味します。「このコードはすでに本番で稼働しています。では審査してユーザーに公開してください」ということです。
全体を結び付けるため、リポジトリに小さな設定を置き、「レビュー候補版」に何が含まれているかを明示しておくと便利です。たとえば、次のような単純な TypeScript 構造です。
// config/release-candidate.ts
export const releaseCandidate = {
version: "1.0.0",
apiBaseUrl: process.env.API_BASE_URL,
enableCommerce: true,
privacyPolicyUrl: "https://example.com/legal/privacy",
termsUrl: "https://example.com/legal/terms",
supportUrl: "https://example.com/support",
};
このファイルは Store のフォームを置き換えるものではありませんが、レビュアーやユーザーに「いま何を売っているか」をチームが共有するうえで役に立ちます。
3. レビュアーはあなたの App をどう見るか
フォームを埋め、リンクを用意し、Submit を押しました。Store の向こう側では何が起きているでしょうか。あなた自身がレビュアーだと想像してください。コードも履歴も知らない一方で、チェックリストと限られた時間はあります。通常、App はいくつかの観点から見られます。
まず、コンテンツポリシーとブランド適合性を確認します。禁止カテゴリの提供、医療・法律・金融を必要なディスクレーマーや「human in the loop」なしで扱うことは禁止です。OpenAI を装ったり、あたかも公式製品のようにそのブランドを使うこともできません。
次に、権限を精査します。ユーザープロファイル、決済、外部アカウントへの OAuth など、機微なアクセスを要求するなら、本当に必要なのか、説明と App の挙動からユーザーに明確に伝わるのかを問われます。理想は、最小限の権限で、記載したシナリオと一致していることです。
さらに、UX と安定性を評価します。App が ChatGPT の画面全体を専有すべきではありません。理由もなく常にフルスクリーンを開くような挙動はマイナスです。バックエンドが頻繁にエラーを返し、ツールがときどき壊れるようでは信頼されません。
最後に、リスティングの誠実さを見ます。説明と、レビュアーが実際にチャットで見る動作が一致しているか。たとえば「稲妻のように最適なギフトを見つけ、即座に checkout」と約束しながら、実際は検索で何度も落ち、注文もできないなら、レビューは早くて悲しい結末になります。
レビュアーの作業を楽にするため、あらかじめ「ルート」を準備しておくと賢明です。試すべき手順と期待結果のリストです。これはあなたの回帰テストにも役立ちます。
コード内にテストシナリオの構造を用意し、社内ドキュメントから参照するのが最も簡単な例です。
// test/review-scenarios.ts
export const reviewScenarios = [
{
id: "gift-basic",
title: "購入なしのギフト選定",
steps: [
"依頼する: 友人向けのギフトを提案。ボードゲームが好きで、予算は50ドル",
"アプリが候補を提示し、ログインを要求しないことを確認する",
],
},
{
id: "gift-checkout",
title: "テスト用チェックアウト付きのギフト選定",
steps: [
"リストから任意のギフトを選ぶ",
"テストカードを使ってチェックアウトへ進む",
],
},
];
この構造自体が Store に送られるわけではありませんが、チームの規律を保ち、後でレビュアーやサポート向けの説明を更新するのに役立ちます。
4. テスト用アカウントとデータ:それがなければレビューは進まない
お金、個人データ、外部アカウントが関わる時点で、レビュアーは本物のカードや個人メール、実際の Slack/Google/何であれを使わずに、全シナリオを安全に通せる方法の提供を期待します。
大きく分けて、テスト用の対象は二種類あります。
第一は、あなたのシステム内のテストユーザー/テスト組織です。たとえば GiftGenius では、デモ用カタログと支払いプロバイダーの sandbox に紐づいたテスト決済手段を備えた「レビュー用組織」を用意できます。レビュアーに複雑なオンボーディングをさせないことが重要です。理想は、ログイン/パスワードやマジックリンクを渡せば、すぐに用意されたサンドボックスに入れること。
第二は、外部プロバイダーのテストデータです。決済にはたいてい sandbox モード(test cards、test accounts)があります。App が ACP/Instant Checkout で支払いを委譲している場合、審査ではテスト環境を使っており、誰も実際のお金を支払っていないことを確認すべきです。これはコマース部分のアーキテクチャにも関わりますが、考え方は単純で、バックエンドに「review/test mode」フラグを入れることです。
コードでは、環境変数と設定の単純なフラグにできます。
// config/env.ts
export const env = {
nodeEnv: process.env.NODE_ENV,
reviewMode: process.env.REVIEW_MODE === "true",
paymentProviderEnv: process.env.REVIEW_MODE === "true" ? "sandbox" : "production",
};
決済システムのクライアントを初期化する箇所では次のようになります。
// lib/payments/client.ts
import { env } from "@/config/env";
export const paymentClient = createPaymentClient({
environment: env.paymentProviderEnv, // "sandbox" または "production"
apiKey: process.env.PAYMENT_API_KEY!,
});
この小さな工夫で作業は大きく楽になります。実運用に近いモードで App を動かしつつ、レビュアーがお金を触らずに検証できます。
さらに、Gmail、Slack、Notion などの統合に対するテストシナリオをよく考えておくべきです。そこに OAuth を使うなら、共有のデモアカウント、もしくはテスト用ワークスペースを作るごく簡単な手順が期待されがちです。「サポートに連絡すれば手動で何かを有効化します」のような流れは避けましょう。レビューはしばしば自動化され、時間も限られているため、あなたからのメールを待ってはくれません。
5. よくある指摘と、その対応方法
残念なお知らせかもしれませんが、初回の審査が完璧に通る確率は、プログラマがバグゼロで一発でコードを書ける確率と同程度です。つまり限りなくゼロに近い。それで構いません。
指摘はたいてい、予測しやすいカテゴリーに分類されます。
第一のカテゴリーは、権限とプライバシーです。例えばメールアドレスへのアクセスを要求しているのに、リスティングで用途を説明していない。あるいは Privacy Policy で「チャットデータは保存しない」と書きながら、MCP サーバーのログが PII 付きでリクエスト全文を記録している。レビュアーは文書の修正、App の挙動の変更、またはその両方を求めることがあります。
第二のカテゴリーは、UX とチャット内での挙動です。App が会話を「乗っ取る」——つまり、インラインで済む場面でも強引にフルスクリーンを開いたり、操作後にテキストの要約を残さなかったり、チャットに戻る明確な方法を提供しない——場合、UX の単純化と ChatGPT の会話 UI を尊重するよう求められるでしょう。
第三のカテゴリーは、安定性とエラーです。典型的なシナリオで App が定期的に「Error talking to app」や内部 500 を返す場合、これが例外的な事象で常態ではないと示すまでレビューは中断されます。ここではバグ修正だけでなく、最低限の可観測性——ログ、ヘルスチェック、妥当なタイムアウト——も期待されます。
第四のカテゴリーは、リスティングの誠実さとマーケティングの約束です。実力以上の約束、とりわけセンシティブな領域で「保証された結果」をうたうと、レビュアーはすぐに見抜きます。対処は二択です。約束を小さくするか、実装を大きくするか。多くの場合は前者です。
指摘への正しい向き合い方は? 要は、レビューを「意地悪なモデレーター」ではなくパートナーシップとして扱うことです。返信では次の点が有効です。
- 問題を明確に認める:「はい、現行バージョンでは App は X をしていますが、説明には Y と書かれていました」。
- すでに行った変更を述べる:「リスティングを修正し、Privacy Policy を更新して……と明記しました」。
- 可能であれば、修正を確認できる短いテストシナリオを添える。
なぜ指摘されたのかがはっきり分からない場合は、当て推量よりも確認質問をする方が良いでしょう。例えば:「問題の本質は、ユーザー操作なしに App が自動でフルスクリーン展開する点で合っていますか?」。
6. 提出前の社内チェックリスト
反復回数を減らすため、モジュール 7、15–17 を踏まえた社内の pre‑flight チェックリストを用意するとよいでしょう。単なる「やったことにする」リストではなく、提出のたびに本当に実施する実践的なものです。
技術的には、このチェックリストを JSON/TS モジュールとしてリポジトリに埋め込み、README やパイプラインで走らせることもできます。
TypeScript の最小例は次のようになります。
// tools/review-checklist.ts
export interface ChecklistItem {
id: string;
description: string;
done: boolean;
}
export const reviewChecklist: ChecklistItem[] = [
{
id: "ux-inline-first",
description: "主要なシナリオはインラインで動作し、フルスクリーンは本当に正当な場所でのみ使う。",
done: false,
},
{
id: "privacy-links",
description: "Privacy Policy、Terms、Support へのリンクは有効で、認証なしで開ける。",
done: false,
},
{
id: "permissions-minimal",
description: "要求する権限は最小限であり、それぞれをリスティングに記載している。",
done: false,
},
];
社内ツールや単なるコンソールでも、このリストを出力して進捗をチェックできます。必須の自動化ではありませんが、エンジニアは Google Docs よりコードの方が得意なことが多いので、慣れた道具を使えばよいのです。
7. イテレーションとバージョニング:初回公開後の暮らし
二つ目のサプライズ:審査を通ってユーザーに公開された後も、プロセスは終わりません。権限の変更、センシティブなシナリオの追加、UX の大幅変更など、意味のあるアップデートは再審査のトリガーになり得ます。
ChatGPT App は「最後の一撃」ではなく、通常のリリースプロセスを持つ生きたプロダクトとして扱いましょう。
最低限として、コード上のバージョン(semver)、変更履歴(changelog)、どのリリースが再審査を必要とするかの把握があるべきです。たとえば UI の誤字修正のように App の挙動や権限に影響しないものは静かに進むこともありますが、「おすすめのみ」から「支払いを伴う本格的な checkout」への移行は確実に新たなレビューを要します。
コードでは、単純な定数と変更点のオブジェクトにできます。
// config/app-version.ts
export const appVersion = "1.1.0";
export const appChangelog = {
"1.1.0": [
"テストユーザー向けに sandbox チェックアウトを追加",
"リスティングの権限説明を明確化",
],
"1.0.0": ["GiftGenius の初の公開版(支払いなし)"],
};
そして、Store のリリースノートとこれらのメモを同期しておくと尚良いです。レビュアーにもユーザーにも、何が起きたのか分かりやすくなります。
8. プラットフォームとのやり取り:レビュアーと衝突しないために
過小評価されがちなのが、レビュアーと適切に会話するスキルです。多くの場合、フィードバックは「何が問題か」「どのポリシーに抵触したか」「どの UX が疑問か」といった箇条書きで届きます。良い返信とは「あなたは分かっていない」と言い返すことではなく、落ち着いて具体的に返すことです。
いくつかの簡単な原則を心に留めましょう。
第一に、明瞭さ。MCP サーバーの内部構造がどれほど美しいかを延々と書く必要はありません。レビュアーが知りたいのは、まずユーザー体験とポリシー適合です。何を変えたのか、どう検証できるのかを簡潔に述べれば十分です。
第二に、透明性。問題が「文言を直した」以上に複雑で大規模な手直しを要するなら、正直に書きましょう。「これはチェックアウトのコアに関わるため、適切な修正に 1–2 週間が必要です。準備でき次第、更新版をお送りします」。
第三に、記録。レビューフィードバックはメールや社内トラッカーだけでなく、「何がダメで、なぜか」を小さな「決定事項」として文書化しておくとよいです。新しい開発者やプロダクト担当が同じ落とし穴にはまりにくくなります。社内ドキュメントや README の「Store Review Decisions」のようなセクションが役立ちます。
9. アーキテクチャと過去モジュールとの関係
レビュー・プロセスを、これまでのモジュール全体に対する「統合的な検証」として眺めるのは有益です。
セキュリティと権限(7、15)のモジュールがなければ、アクセスや PII、OAuth、破壊的操作に関する質問が出るでしょう。
安定性と可観測性(16、17)のモジュールがなければ、なぜ App が時々落ち、時々落ちないのか、どう監視しているのかを明確に答えられません。メトリクスや SLO は理論から根拠に変わります。「主要ツールの p95 < 2 秒で、直近 N 日の error rate が < 1%」のように。
UX モジュール(8、11)がなければ、App はチャットを「壊し」かねません。不要なフルスクリーン、分かりにくいモード遷移、テキスト要約の欠如。レビュアーは多くの App をテストしているため、誰かがやり過ぎているとすぐに気づきます。
そして最後に、今日のレビュー・プロセスの理解がなければ、「出したのに戻されて、腹を立てたまま」という段階で足踏みしがちです。正しくは、これをもう一つのイテレーションのサイクルとして捉えることです。あなたの社内回帰にとてもよく似ていますが、もう一人の利害関係者——プラットフォーム——が加わるだけです。
結局のところ、しっかりしたチェックリスト、テストアカウントと sandbox モード、基本的な可観測性、そしてレビュアーとの健全なコミュニケーションがあれば、レビューは抽選ではなくなります。これはあなたの ChatGPT App を取り巻く、回帰やチーム内のコードレビューと同じような、自然な反復サイクルに過ぎません。
10. レビュー通過時の典型的な失敗
失敗その1:社内チェックリストなしに「動いたから」そのまま提出する。
多くのチームは、Dev Mode で「動いた」直後に「Submit」を押してしまいます。その結果、Privacy/Terms へのリンク切れ、動かないシナリオ、テストアカウントの欠如といった基本事項が審査で露見します。対策は単純で、本当に毎回実行する社内チェックリストを持つこと(有効なリンク、最小権限、主要シナリオの動作)——その例は本講義の「提出前の社内チェックリスト」で示しました。
失敗その2:テストアカウントや sandbox モードを無視する。
レビュアーに本物のクレジットカードを要求する App を審査に出すのは悪手です。チェックアウトが一応あるのに、レビュアーがまったく試せないのも同様に悪い。あなたのシステム内のテスト用 organization/user と、決済プロバイダーの sandbox モードを、REVIEW_MODE やそれに類するフラグに結びつけて事前に設計しておきましょう。
失敗その3:問題を直す代わりに「特例を交渉」しようとする。
開発者が「競合も同じだ」や「これはプラットフォームの制約で仕方がない」と議論を始めることがありますが、この手の姿勢はまず功を奏しません。シナリオの言い換え、UX の単純化、権限の削減、挙動に忠実なリスティングへの修正の方がはるかに効果的です。
失敗その4:指摘と対応を記録しない。
指摘を受けて「コードのバグを直した」だけで、何がダメだったのかを記録しないと、半年後にチームの誰かがまた同じことをします。小さくてもレビュー判断のレジストリを持ちましょう。「ユーザーの明示的操作なしに自動でフルスクリーンを開いてはいけない」「明記のない限り、チャット全文を N 日以上保持してはいけない」など。
失敗その5:段階戦略なしの「大型リリース」。
1 回のリリースで決済、権限追加、新 UX、バックエンド刷新をすべて入れようとするのは、長期化するレビューのレシピです。小さなステップで出す方がずっと平穏です。まずはおすすめのみ(支払いなし)、次に sandbox チェックアウト、そして本格的な決済フローへ。そうすればリスクも減り、レビューでの論点も少なくなります。
失敗その6:自前の QA と可観測性の代わりに Store の受け入れに頼る。
無意識のうちに、レビュアーが「代わりにテストしてくれる」と期待してしまうことがあります。その結果、レビューが無料 QA と化し、ローンチが何週間も遅れます。レビューは、テスト・ログ・メトリクス・明確なシナリオを備えた、かなり成熟したプロダクトに対する最終的な sanity チェックだと捉える方が健全です。
GO TO FULL VERSION