WWDC Quick Look 💓 By SwiftGGTeam
App Store Connect の Retention Messaging を探る

App Store Connect の Retention Messaging を探る

元の動画を見る

ハイライト

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)

  1. まずリアルタイム応答を使う。
  2. App Store Connect に設定した静的 Retention Messaging に fallback する。
  3. 最後に 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 か月コミットメントの月額支払いプランも、billingPlanType field で指定できます。(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 を更新する必要があります。
  • offerIdentifierofferDiscountTypeofferPeriod などの field は通常の offer と同じです。

2 つの方式の比較

観点App Store Connect の静的設定Real-time Retention Messaging
判断方式App Store が自動選択開発者がリアルタイム制御
設定入口App Store Connect または ASC APIRetention Messaging API
offer typeRetention OfferPromotional 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