ハイライト
Apple は App Store Connect に Retention Messaging 機能を追加しました。ユーザーがサブスクリプションをキャンセルするときに、開発者は挽留メッセージや offer を表示できます。同時に Real-time Retention Messaging API も開放され、ユーザーがキャンセルを押したリアルタイム要求に対して、サーバーがパーソナライズされたメッセージ、ダウングレード案、promotional offer を返せます。この機能を採用した App では平均 save rate が 82% 向上し、promotional offer モードでは 223% 向上しました。
主要内容
サブスクリプション制 App を作る人には共通の痛みがあります。ユーザーが黙ってシステム設定を開き、サブスクリプションをキャンセルしてしまう。こちらには話しかける機会すらありません。以前は App 内に「サブスクリプションを管理」入口を置くことしかできませんでしたが、本気でキャンセルしようとしているユーザーは、そもそもその導線を通りません。
Apple は今回、サブスクリプション管理ページのキャンセル確認ステップを開放しました。(00:15)
App Store Connect の静的設定: バックエンドなしで始める
バックエンドチームがない開発者や、コードを書きたくない開発者は、App Store Connect で Retention Messaging を直接設定できます。サブスクリプション管理ページに入り、“Get Started” をクリックして挽留メッセージを作成し、タイトルと説明を入力し、Asset Library から画像を選び、具体的なサブスクリプション項目に紐づけます。1 つのメッセージを複数のサブスクリプションに関連付けることも、複数の Retention Offer を設定することもできます。App Store は条件を満たすユーザーに最適な offer を自動で選びます。(02:43)
設定後、ユーザーがサブスクリプションのキャンセルを押すと、システムはキャンセル確認ページに設定したメッセージを表示します。Apple のデータは明快です。Retention Messaging を使った App は、平均キャンセル挽留率、つまり Save rate が 1.4 パーセントポイント向上しました。これは相対的に 82% の伸びです。Promotional offer と組み合わせると、挽留率は 5.5 パーセントポイント上がり、相対的に 223% の伸びになります。(02:06)
Real-time Retention Messaging: 一人ひとりに合わせた精密な挽留
バックエンド能力があるチームにとっての本命は Real-time Retention Messaging です。ユーザーがキャンセルを押すと、App Store はあなたのサーバーへ HTTP request を送ります。サーバーはユーザーデータをもとに、何を表示するかをリアルタイムに決められます。(06:48)
リアルタイム応答は 3 種類の形式をサポートします。
- メッセージを返す。文字だけ、または画像付きの文字を表示できます。
- ダウングレード案 (
alternateProduct) を返し、同じ subscription group 内の別 product を推奨します。 - Promotional offer (
promotionalOffer) を返し、期間限定割引を提示します。
この方式なら、ユーザーのアクティブ度、利用期間、支払い履歴などのデータに応じて、割引で挽留するのか、低価格プランを勧めるのか、単にリマインドのメッセージだけを出すのかを決められます。全員に同じクーポンを配るより、ずっと賢い方法です。(08:57)
3 段階の fallback 仕組み
リアルタイム interface には応答速度の厳しい要件があります。サーバーが timeout したり error を返したりした場合、App Store は次の順序で fallback します。(10:10)
- まずリアルタイム応答を使う。
- App Store Connect に設定した静的 Retention Messaging に fallback する。
- 最後に Retention Messaging API で設定した default message に fallback する。
つまりリアルタイム interface に問題が起きても、ユーザーが空白ページを見ることはありません。
詳細
Retention Messaging API endpoint 概要
リアルタイム機能は https://api.storekit.apple.com/inApps/v1/messaging で提供され、主要 endpoint は次のとおりです。(07:50)
// URL 設定
PUT /realtime/url // リアルタイム callback URL を設定する
GET /realtime/url // 現在の URL を照会する
DELETE /realtime/url // URL を削除する
// メッセージ設定
PUT /message/{messageIdentifier} // メッセージを作成または更新する
DELETE /message/{messageIdentifier} // メッセージを削除する
GET /message/list // すべてのメッセージを一覧表示する
PUT /default/{productId}/{locale} // default message を設定する
DELETE /default/{productId}/{locale} // default message を削除する
GET /default/{productId}/{locale} // default message を照会する
// 画像設定
PUT /image/{imageIdentifier} // 画像をアップロードする
DELETE /image/{imageIdentifier} // 画像を削除する
GET /image/list // すべての画像を一覧表示する
// 性能テスト (Sandbox のみ)
POST /performanceTest // 性能テストを開始する
GET /performanceTest/result/{requestId} // テスト結果を照会する
重要ポイント:
- すべての設定操作は server-to-server で、クライアントの参加は不要です。
- メッセージ、画像、default configuration は互いに独立しており、柔軟に組み合わせられます。
- Sandbox 環境では、Production を有効にする前に
/performanceTestを通過する必要があります。
App Store から届くリアルタイム request 形式
ユーザーがキャンセルを押すと、App Store は callback URL に次の JSON を送ります。(08:34)
{
"originalTransactionId": "123456789",
"appAppleId": 6745974591,
"productId": "Yoga_summer_2026",
"userLocale": "en-US",
"requestIdentifier": "c03248af-dd76-4e9b-9c1e-4489cd19a768",
"environment": "Production",
"signedDate": 1780920000000
}
重要ポイント:
originalTransactionIdはユーザーのサブスクリプション記録を特定するために使います。userLocaleはどの言語で返答すべきかを教えてくれます。requestIdentifierは追跡と debug に使います。environmentは Sandbox と Production を区別します。
応答形式 1: メッセージを返す
{
"message": {
"messageIdentifier": "551ee7c0-c097-418e-9dd5-2a98533a7390"
}
}
重要ポイント:
messageIdentifierは事前にPUT /message/{id}で設定しておく必要があります。- メッセージは文字だけでも、
PUT /image/{id}でアップロードした画像と組み合わせても表示できます。 - そのメッセージが App Store Connect にも設定されている場合、両者は一貫した状態に保たれます。
応答形式 2: ダウングレード product を返す
{
"alternateProduct": {
"messageIdentifier": "ed7f25fc-5741-46a3-8502-062e0fb8afd0",
"productId": "Yoga_summer_2026_annual"
}
}
重要ポイント:
productIdは、現在キャンセルされようとしているサブスクリプションと同じ Subscription Group 内にある必要があります。- ユーザーがタップすると、購入フローをやり直さず直接新しい product に切り替わります。
- 「高度な機能は使わない」ユーザーに向いています。低価格プランでユーザーの LTV を保てます。
- iOS 26.5 で追加された 12 か月コミットメントの月額支払いプランも、
billingPlanTypefield で指定できます。(11:11)
応答形式 3: promotional offer を返す
{
"promotionalOffer": {
"messageIdentifier": "80135e2b-ae15-4ec4-8c5c-9ecc8045c0dc",
"promotionalOfferSignatureV2": "eyJhbGciOiJFUzI..."
}
}
重要ポイント:
- V2 版の promotional offer signature を使う必要があります。V1 signature は有効になりません。
- signature 生成ロジックは StoreKit 2 仕様に従います。
- 離脱直前の高価値ユーザーに対して、期間限定割引で精密に挽留する場面に向いています。
Retention Offer transaction を識別する
ユーザーが挽留 offer を受け入れると、transaction 情報には新しい marker が入ります。(06:08)
{
"bundleId": "com.example.app",
"productId": "Yoga_summer_2026",
"type": "Auto-Renewable Subscription",
"transactionReason": "RENEWAL",
"offerType": 5,
"offerIdentifier": "Yoga_2026_cancel_free_3m",
"offerDiscountType": "FREE_TRIAL",
"offerPeriod": "P3M",
"originalTransactionId": "1000011859217"
}
重要ポイント:
offerType: 5は新しい Retention Offer type です。- 以前の
offerTypeは 1-4 だけだったため、backend の parse logic は enum を更新する必要があります。 offerIdentifier、offerDiscountType、offerPeriodなどの field は通常の offer と同じです。
2 つの方式の比較
| 観点 | App Store Connect の静的設定 | Real-time Retention Messaging |
|---|---|---|
| 判断方式 | App Store が自動選択 | 開発者がリアルタイム制御 |
| 設定入口 | App Store Connect または ASC API | Retention Messaging API |
| offer type | Retention Offer | Promotional Offer |
| view support | メッセージ / 画像 / offer | メッセージ / 画像 / offer / ダウングレード案 |
| サーバー要否 | 不要 | 必要 |
| 性能要件 | なし | Sandbox 性能テストに合格する必要がある |
(11:52)
重要な示唆
1. まず静的設定、その後リアルタイムへ
バックエンドがない、またはバックエンドリソースが限られるチームは、まず App Store Connect で静的 Retention Messaging を設定するべきです。Apple のデータは、文字メッセージだけでも平均 save rate を 82% 改善できることを示しています。これはコード不要、コスト不要なので、すぐにやるべきです。
- 何をするか: ASC で各 subscription product に 1 つの挽留メッセージと 1 枚の画像を設定する。
- なぜ価値があるか: 開発コストなしで、82% の save-rate lift を直接得られる。
- どう始めるか: App Store Connect > Subscriptions > Retention Messaging > Get Started を開く。
2. alternateProduct でスマートにダウングレードする
キャンセルされそうになるたびに割引する必要はありません。ユーザーがキャンセルする理由を分析します。理由が「高度な機能を使わない」なら、同じ group 内の低価格な basic subscription を返します。これによりユーザーの LTV を保ちつつ、「キャンセルすれば割引される」と学習させることも避けられます。
- 何をするか: ユーザー profile data に応じて、リアルタイム応答で
alternateProductを返す。 - なぜ価値があるか: 割引より上品で、利益率の損失も小さい。
- どう始めるか: subscription group 内に低価格 tier の product を作り、Retention Messaging API でダウングレードメッセージを設定する。
3. ユーザー profile を Redis に cache する
リアルタイム interface は遅延に非常に敏感です。request を受け取ってから database を引いたり、第三者 API を呼んだりしてはいけません。ユーザーのアクティブ度、支払い履歴、利用傾向などのデータを事前計算し、Redis に保存しておき、originalTransactionId で直接 cache を引いて返します。
- 何をするか: 低遅延の挽留意思決定 service を構築する。
- なぜ価値があるか: 性能テストはリリース条件であり、遅延はユーザー体験に直結する。
- どう始めるか:
originalTransactionIdを key にして、ユーザー profile data を cache に pre-warm する。
4. Win-back と組み合わせてライフサイクルの閉ループを作る
Retention Messaging が捉えるのは「今まさにキャンセルしようとしている」ユーザーです。Win-back が呼び戻すのは「すでにキャンセルした」ユーザーです。両者を組み合わせると、サブスクリプションのライフサイクルを完全に閉じられます。
- 何をするか: キャンセル時には Retention で止め、キャンセル後には Win-back で呼び戻す。
- なぜ価値があるか: サブスクリプション離脱の 2 つの重要地点を覆える。
- どう始めるか: まず Retention Messaging をリリースし、その後 Win-back Offer を統合する。
関連セッション
- Apple In-App Purchase の新機能 - iOS 26.5 で追加された 12 か月コミットメントの月額支払いプランと、Retention Offer が transaction 上でどう表れるかを学ぶ
- App Store での存在感を高める - Asset Library の使い方を学ぶ。Retention Messaging の画像は Asset Library から直接再利用される
- App Intents: 新機能 - App が Siri や Shortcuts をサポートしているなら、App Intents と組み合わせてユーザーが音声でサブスクリプションを管理できる
- StoreKit の新機能 - StoreKit 2 の transaction model と promotional offer signature の仕組みを深く理解する
コメント
GitHub Issues · utterances