Seat-based billing は、アカウント上のユーザー数に基づいて顧客に料金を請求します。Dodo Payments では、add-on システムを使用して実装します。基本のサブスクリプション商品に、数量がシート数を表すシート単位の add-on を組み合わせます。
Implementation Tutorial
コード例付きのステップバイステップガイド。
Add-ons Documentation
席数ベースの課金を支えるアドオンシステムについて学ぶ。
Subscription Management
席数ベースのサブスクリプションとプラン変更を管理する。
Webhooks
サブスクリプションのWebhooksで席数の変更を追跡する。
シートベースの請求とは?
Seat-based billing は、製品にアクセスするユーザー数に基づいて顧客に料金を請求します。固定料金ではなく、チームの規模に応じて価格が変動します。一般的な使用例
シートベースの価格設定の利点
ビジネスにとって:- 顧客の成長に応じて収益が拡大する
- 顧客が予算を予測しやすい
- 個人向けからチーム向け、エンタープライズ向けへ明確にアップグレードできる
- チームの拡大に伴い顧客生涯価値が高まる
- 利用しているユーザー分だけ支払える
- コストを簡単に理解し、予測できる
- 必要に応じてユーザーを追加・削除できる
- チームの規模に見合った公平な料金設定
仕組み
Dodo Payments は、Add-ons システムを使用して Seat-based billing を実装します。Seat-based subscription は次の2つの部分で構成されます。
顧客の月額合計は次のとおりです。
価格設定戦略
ビジネスに合ったシートベースの価格設定戦略を選択してください:戦略1: 基本 + シートごとのアドオン
基本プランに設定された数のシートを含め、追加シートに対して料金を請求します。Strategy 2: 純粋なシート単位の料金
基本料金なしで、シートごとに定額料金を請求します。Strategy 3: 段階制のシート料金
基本プランごとに、異なるシート単価を設定します。Strategy 4: シートバンドル
シートを1つずつではなく、パック単位で販売します。Seat-based billing の設定
Step 1: 料金を計画する
実装前に、料金体系を定義します。1
Define Base Plan
ベースサブスクリプションに含める内容を決定します:
- ベース価格(純粋なシート単位の課金では$0に設定可能)
- 含まれるシート数
- このティアで利用できる機能
2
Set Seat Pricing
シート単位の add-on 料金を決定します。
- 追加シート1つあたりの料金
- ボリュームディスカウント(複数の add-on による設定)
- 許可する最大シート数(該当する場合)
3
Consider Billing Frequency
シート料金を請求サイクルに合わせます。
- 月額サブスクリプション → 月額のシート料金
- 年額サブスクリプション → 年額のシート料金(通常は割引あり)
Step 2: Seat add-on を作成する
Dodo Payments ダッシュボードで次の操作を行います。- Products → Add-Ons に移動します
- Create Add-On をクリックします
- add-on を設定します。
Step 3: 基本サブスクリプションを作成する
サブスクリプション商品を作成します。- Products → Create Product に移動します
- Subscription を選択します
- 料金と詳細を設定します
- Add-Ons セクションでシート add-on を追加します
Step 4: 商品に add-on を追加する
シート add-on をサブスクリプションにリンクします。- サブスクリプション商品を編集します
- Add-Ons セクションまでスクロールします
- Add Add-Ons をクリックします
- シート add-on を選択します
- 変更を保存します
これでサブスクリプション商品がシート単位の料金に対応します。顧客は checkout 中に追加シートを任意の数量で購入できます。
シートの管理
新しいサブスクリプションへのシート追加
checkout session の作成時に、シート数量を指定します。既存のサブスクリプションのシート数変更
Change Plan API を使用してシート数を調整します。addons 配列には、差分ではなく新しい合計シート数を設定します。
シートの削除
シート数を減らすには、少ない数量を指定します。追加シートをすべて削除する
空のaddons 配列を渡すと、すべての add-on が削除されます。
シート変更時の Proration
サイクル途中でシート変更を適用すると、Dodo Payments は即時請求額を次の3段階で計算します。各モードのクレジット処理
difference_immediately では、顧客は旧プラン価格と新プラン価格の差額のみを支払います。これがこの名前の由来であり、サイクル中のいつ変更しても金額が同じになる理由です。
クレジットが新しいサイクルの請求額を上回る場合、差額はサブスクリプション単位のクレジットとして保持され、今後の更新に自動的に適用されます。
具体例: シートを5つ追加する
4つすべてのモードで1つのシナリオを実行し、数値を直接比較します。
3つの即時適用モードではすべて、顧客は本日支払う金額と引き換えに、$130で新しい1か月分を全額受け取ります。
prorated_immediately でタイミングが重要な理由
現在のサイクルに残っていてクレジットできる期間が少なくなるため、サイクルの後半に変更するほど同じ変更の費用が高くなります。
どの行でも顧客は新しい1か月分を受け取ります。「すでに支払い済みの分」と「今回支払う分」の内訳だけが変わります。
変更のタイミングにかかわらずシート変更の費用を同じにするには、
difference_immediately を使用します。
具体例: 「予想外の請求」
これは、merchant が最も驚くことの多いケースです。サイクル終盤に少額のシート add-on を追加すると、add-on の価格を大きく上回る請求が発生する場合があります。
$10/月のシートを追加すると、
prorated_immediately では**$55.00**かかります。顧客には$60の新しい1か月分が全額請求され、旧月に残っていた$5がクレジットされ、更新日がリセットされます。
サイクル途中の少数のシート追加を、シート価格のみで、それ以上の費用をかけずに行うには、difference_immediately を使用します。
具体例: シートの削除(ダウングレード)
新しいプランの料金がクレジットを下回る場合、超過分はsubscription credit として保持され、このサブスクリプションの今後の更新に自動的に適用されます。Customer Wallet に追加されることも、credit entitlement になることもありません。クレジットの対象は、削除するシートだけでなく、ベースプランとすべてのアドオンを含むサブスクリプション全体です。
Preview response の読み方
previewChangePlan は、請求される正確な明細項目を返します。各明細項目には proration_factor があります。
Proration は変更時刻の正確な時点を基準に秒単位で計算され、最も近い日単位には丸められません。上記の具体例では、わかりやすさのため日単位の丸めた数値を使用しています。
変更前の Preview
変更を行う前に、必ず proration を preview します。Webhook によるシートの追跡
subscription webhook をリッスンしてシート変更を監視します。関連イベント
Webhook handler の例
シート上限の適用
シート上限はアプリケーション側で適用する必要があります。Dodo Payments が管理するのは billing であり、アクセスを管理するのはあなたのアプリケーションです。- Hard Limit
- Soft Limit with Warning
- Auto-Upgrade
シート数を超えてユーザーを追加できないよう厳密に制限します。
高度なパターン
異なるシートタイプ
異なる料金で複数のシートタイプを提供します。年額シート割引
年額のシート料金を割引価格で提供します。最低シート数要件
特定のプランで最低シート数を必須にします。ベストプラクティス
料金に関するベストプラクティス
- 明確なコミュニケーション: 料金ページでシート単価を目立つように表示する
- 含まれるシート: 導入の障壁を下げるため、基本料金に数シートを含めることを検討する
- ボリュームディスカウント: エンタープライズ契約を獲得するため、大規模チームには低いシート単価を提供する
- 年額プランのインセンティブ: キャッシュフローと retention を改善するため、年額プランを割引する
Technical Best Practices
- シート数をキャッシュする: リクエストごとの API 呼び出しを避けるため、サブスクリプションのシート数をローカルにキャッシュする
- 定期的に同期する: API 経由で Dodo Payments とローカルのシート数を定期的に同期する
- 失敗に対処する: シート変更に失敗した場合は、わかりやすいエラーメッセージと再試行オプションを表示する
- 監査証跡: billing の異議申し立てとコンプライアンスのため、すべてのシート変更を記録する
User Experience Best Practices
- リアルタイムのフィードバック: シートを調整した際の費用への影響をすぐに表示する
- 確認ステップ: 請求変更の前に確認を必須にする
- 日割り計算の透明性: 適用前に日割り料金を明確に説明する
- 簡単なダウングレード: シートを減らしにくくしない(信頼の構築につながります)
トラブルシューティング
Seat count mismatch between app and billing
Seat count mismatch between app and billing
症状: アプリに表示されるシート数がサブスクリプションと異なる。原因:
- Webhook を受信または処理できていない
- シート変更中の race condition
- キャッシュデータが更新されていない
subscription.plan_changed用の webhook handler を実装する- 現在のサブスクリプションを取得する「billing と同期」ボタンを追加する
- 定期的に更新されるよう cache TTL を設定する
Unexpected mid-cycle charge amount
Unexpected mid-cycle charge amount
症状: 顧客がサイクル途中の請求額に困惑している。原因: billing サイクルの後半で
prorated_immediately を使用している(上記の予想外の請求の例を参照)。解決策:- 変更前に必ず
previewChangePlanを使用する - 明確な内訳を表示する: “Xシートを追加すると、本日$Yかかります”
- 請求額を常に価格差額と一致させたい場合は、
difference_immediatelyに切り替える
Add-on not appearing in checkout
Add-on not appearing in checkout
症状: checkout 中にシート add-on を利用できない。原因:
- add-on が商品に追加されていない
- add-on がアーカイブまたは削除されている
- 商品と add-on の通貨が一致していない
- 商品設定で add-on が追加されていることを確認する
- Add-Ons ダッシュボードで add-on の状態を確認する
- 通貨が完全に一致していることを確認する
Cannot reduce seats below current usage
Cannot reduce seats below current usage
症状: 顧客がユーザーを割り当てたままシートを減らしたい。解決策:
- シートを減らす前に削除が必要なユーザーを表示する
- 「ユーザーを削除 → シートを減らす」というワークフローを実装する
- シート削減を適用する前に猶予期間を設けることを検討する
関連ドキュメント
Seat-Based Pricing Tutorial
コードを含む完全な実装ガイド。
Add-ons
add-on システムを詳しく理解します。
Plan Changes & Proration
サブスクリプションの変更を処理します。
Subscription Webhooks
サブスクリプションイベントを追跡します。