Stripe Customer Portalを利用して、「サブスクリプションを解約する理由」を集める方法

サブスクリプションビジネスを成長させるために、「解約すると決めた理由」を知ることはとても重要です。

顧客が目的を達成したことによる円満解約なのか、サービスやサポートに対する不満が原因なのか。

原因を分析することで、サービスの解約率を低く抑え、収益率を高めることが可能です。

## Customer Portalを利用して、追加の開発無しで解約理由のアンケートを追加する

Stripeでサブスクリプションを提供している場合、Customer Portalを利用して簡単に解約者へのアンケートを行えます。

![スクリーンショット 2023-04-17 14.02.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/d53b9039-5ccb-721b-0512-896f8ffbb72e.png)

## Stripe ダッシュボードから解約者アンケートを有効化する

解約時のアンケート機能は、ダッシュボードから設定できます。

まずは[製品の設定 > カスタマーポータル]にアクセスしましょう。

![スクリーンショット 2023-04-17 14.37.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/d0e84215-8ef9-1497-b624-3fdb9f6549d7.png)

カスタマーポータルの設定画面が表示されます。

![スクリーンショット 2023-04-17 14.37.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/05466208-cf46-ac6d-9d91-0f2fc308c12d.png)

[キャンセル]をクリックすると、[カスタマーポータルでサブスクリプションをキャンセルできるようにするか]の設定項目が開きます。

ここで[サブスクリプションをキャンセル]を有効化しましょう。

![スクリーンショット 2023-04-17 14.39.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/ec2f1fc9-6789-902a-5f43-39278fc48f17.png)

[サブスクリプションをキャンセル]を有効化すると、[キャンセル理由を収集する]ボタンが表示されます。

[キャンセル理由を収集する]を有効化しましょう。

![スクリーンショット 2023-04-17 14.38.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/e44ffca0-46a5-d8ea-7fb7-929cd1d52146.png)

アンケートに表示する項目・表示しない項目を選ぶ画面が開きました。
アンケートの選択肢に表示したいものを選んで、[閉じる]をクリックしましょう。

![スクリーンショット 2023-04-17 14.38.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/c63ca199-5877-77a5-fcd8-332d1fe01b39.png)


最後に[変更を保存]をクリックして、確定します。

![スクリーンショット 2023-04-17 14.41.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/59f8aa7f-14f4-d228-37e0-ab4e5a7dc895.png)

### Stripe APIでCustomer Portalの解約者アンケートを有効化する方法

複数のCustomer Portal設定を組み合わせて利用している場合、APIから設定を変更する必要があります。

その場合、`billingPortal.configurations.update`APIを利用しましょう。

```js
	await stripe.billingPortal.configurations.update('bpc_xxx', {
		features: {
			subscription_cancel: {
				cancellation_reason: {
					enabled: true,
					options: [
						'customer_service',
						'unused'
					]
				}
			}
		}
	})
```

## 解約理由を確認する方法

ユーザーが解約時に入力したアンケート結果は、ダッシュボードまたはAPIから確認・収集できます。

### ダッシュボードでは、サブスクリプションの詳細から確認

サブスクリプションごとの解約理由は、ダッシュボードのサブスクリプション詳細ページで確認できます。

![スクリーンショット 2023-04-17 15.52.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/d9a38d6c-6187-560e-6a97-8e84ac46f88e.png)

解約理由とは別に、「ユーザーが平均何ヶ月契約を続けているか」のコホート図もダッシュボードから確認できます。

![スクリーンショット 2023-04-17 15.54.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/f3b05897-267c-3a23-e46e-d57af141c2ed.png)

### APIで解約理由を収集する

バッチ処理などで分析データを収集したい場合は、APIを利用します。

「キャンセル済みのサブスクリプション」を一覧取得し、必要に応じてレスポンスからアンケート結果の抽出や絞り込みなどを行いましょう。

```typescript
	const subscriptions: Stripe.Subscription[] = []

    // 全件取得する際は、for awaitを利用する
    // @see https://stripe.com/docs/api/pagination/auto
	for await (const subscription of stripe.subscriptions.list({
		status: 'canceled',
		limit: 100,
	})) {
		// 解約理由のデータがないサブスクリプションを除外する場合
		if (
			!subscription.cancellation_details ||
			!Object.values(subscription.cancellation_details).find(value => !!value)
		) {
			continue
		}
		subscriptions.push(subscription)
	}
```

### Webhookイベントから、解約理由を取得する

`customer.subscription.deleted`や`customer.subscription.updated`のWebhookイベントでも、解約理由を取得できます。

![スクリーンショット 2023-04-17 16.11.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/2cf48456-8417-7f4f-9a4e-2f92949bd574.png)

WebhookやIPaaSを利用することで、「Slackなどの社内ツールへの通知」や「外部の分析基盤やCRMへのデータ送信」なども自動化できます。

### [有料オプション] Stripe Sigmaで解約理由をSQLから取得する

Stripe Sigmaを利用すると、SQLを使って様々な条件・角度から解約理由を調査できます。

https://stripe.com/jp/sigma

例えば、次のSQLを利用して「どの理由で解約されることが多いのか」を調べることができます。

```sql
SELECT
  subscriptions.cancellation_reason,
  count(*) as reason_count
FROM  subscriptions 
WHERE subscriptions.cancellation_reason IS NOT NULL
GROUP by subscriptions.cancellation_reason
```

**実行結果**
![スクリーンショット 2023-04-20 14.45.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/6133590c-f4fc-a2f4-7e1f-f65f829d0829.png)

また、他にも次のSQLで、商品や料金ごとのキャンセル理由を集計できます。

```sql
SELECT
  products.name AS product_name,
  SUM(CASE WHEN subscriptions.cancellation_reason = 'other' THEN 1 ELSE 0 END) AS other_count, 
  SUM(CASE WHEN subscriptions.cancellation_reason = 'too_expensive' THEN 1 ELSE 0 END) AS too_expensive_count,
  SUM(CASE WHEN subscriptions.cancellation_reason = 'unused' THEN 1 ELSE 0 END) AS unused_count,
  SUM(CASE WHEN subscriptions.cancellation_reason = 'missing_features' THEN 1 ELSE 0 END) AS missing_features_count
FROM subscriptions
JOIN prices
	ON subscriptions.price_id = prices.id
LEFT JOIN products -- join plans on products to get product name
  ON prices.product_id = products.id
WHERE
 subscriptions.cancellation_reason IS NOT NULL
GROUP BY products.name
```

**実行結果**
![スクリーンショット 2023-04-20 15.03.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/03c41ae1-12f7-2a29-9bff-61b374a1b389.png)


::: note
「取引データは、**1日以内にクエリ可能**」のため、リアルタイムのデータを取得したい場合にはご注意ください。

https://stripe.com/docs/stripe-data/available-data?locale=ja-JP
:::

## [One more tips] AWSなどの外部サービスで分析する

Amazon S3とAmazon QuickSightなどを利用することで、「どの理由で解約されることが多いか」などをプランや製品ごとに分析することも可能です。

![スクリーンショット 2023-04-17 15.45.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/68dbc291-6de1-71f9-f573-c1110afe32d2.png)

## 関連ドキュメント

- 全件取得する際のAPI実装方法: https://stripe.com/docs/api/pagination/auto
- Subscriptionの`cancellation_details`オブジェクトの詳細: https://stripe.com/docs/api/subscriptions/object#subscription_object-cancellation_details
- Customer Portalの設定変更方法: https://stripe.com/docs/customer-management/configure-portal