サブスクリプションアプリを公開して最初の壁にぶつかるのが、ペイウォール画面の課金転換率です。価格設定は正しいはずなのに、ユーザーが「購入」ボタンを押してくれありません。その原因がデザインなのか、文章なのか、価格の見せ方なのかが分からないまま感覚で改修を重ねている方は少なくないはずです。
Superwall は、ペイウォール画面のA/Bテストに特化したSDKです。コードを再デプロイすることなくダッシュボード上でペイウォールのデザインや訴求文を切り替えられ、どのバリエーションが最も購入につながるかをデータで判断できます。ここではRorkで開発したReact Nativeアプリへの導入方法と、実際にA/Bテストを走らせるまでの流れをコード付きで解説します。
Superwallとは(なぜReact Nativeアプリに有効なのか
Superwallは「ペイウォールとして表示する画面」と「その表示ロジック」を、アプリのコードから切り離して管理できるサービスです。
通常のペイウォール実装では、こんな悩みがあります。
- 「月額580円」を先に見せるか、「年額4,800円」を先に見せるかで課金率が変わる気がするが、確かめる手段がない
- 訴求文を変えるたびにアプリを再ビルドしてApp Storeに提出しなければならない
- どのユーザーがどのペイウォールを見て離脱したか追えない
Superwallはこれらをすべて解決します。ペイウォールのHTML/CSSをダッシュボード上で編集でき、A/Bテストの設定も数クリックで完了します。React Nativeとの相性も良く、Expo Managed Workflowでも動作します。
事前準備:Superwallアカウントとアプリ設定
Superwallアカウントの作成
superwall.com からアカウントを作成し、新しいアプリを登録します。iOS用とAndroid用でそれぞれAPIキー(Superwall API Key)が発行されます。このキーは後ほど使用します。
RevenueCatとの連携(推奨)
SuperwallはRevenueCatと連携することで、購入処理をRevenueCatに委ねつつ、ペイウォールの表示ロジックだけをSuperwallで管理できます。すでにRevenueCatを導入済みであれば、Superwallダッシュボードの「Integrations」からRevenueCatのAPIキーを設定するだけで連携が完了します。
RevenueCatを使っていない場合は、Superwallが内部でStoreKitを直接操作することも可能です。ただし購入履歴の管理や複数プラットフォームの統合を考えると、RevenueCatとの組み合わせが現実的です。
SDK導入:Expo プロジェクトへのインストール
RorkはExpoベースのReact Nativeプロジェクトを生成するため、@superwall/superwall-reactnative パッケージを使います。
パッケージのインストール
# npm の場合
npm install @superwall/superwall-reactnative
# yarn の場合
yarn add @superwall/superwall-reactnativeSuperwallはネイティブモジュールを使用するため、Expo Managed WorkflowではExpo Development Buildが必要です。純粋なExpo Goでは動作しません。
# EAS Build でdevelopment buildを作成
eas build --profile development --platform ios初期化コード
アプリのエントリーポイント(通常は App.tsx または _layout.tsx)でSuperwallを初期化します。
import Superwall from '@superwall/superwall-reactnative';
import { Platform } from 'react-native';
// App.tsx または app/_layout.tsx
const SUPERWALL_API_KEY = Platform.OS === 'ios'
? 'pk_ios_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' // SuperwallダッシュボードのiOS APIキー
: 'pk_android_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // Android APIキー
// 環境変数で管理することを推奨
// const SUPERWALL_API_KEY = process.env.EXPO_PUBLIC_SUPERWALL_API_KEY;
Superwall.configure(SUPERWALL_API_KEY);configure は非同期処理ですが、await せずとも内部でキューイングされます。ただしRevenueCatとの連携時はPurchaseControllerを実装する必要があります(後述)。
ペイウォールの表示:placement(旧trigger)の使い方
Superwallでペイウォールを表示するには、ダッシュボードで設定した「placement」(配置ポイント)を呼び出します。これがSuperwallの核心です。
import Superwall from '@superwall/superwall-reactnative';
// プレミアム機能ボタンを押した時にペイウォールを表示
const handlePremiumFeature = async () => {
await Superwall.shared.register('premium_feature_tapped');
// register() の後に続くコードは、ユーザーがサブスクライブした場合のみ実行される
// (Superwallがサブスクリプション状態を自動的に確認する)
navigateToPremiumFeature();
};register に渡す文字列('premium_feature_tapped')がplacementです。ダッシュボード上でこのplacementに対してどのペイウォールを表示するかを設定します。
placementを複数定義して使い分ける
機能によってペイウォールの訴求を変えるのが重要です。
// 機能ごとに異なるplacementを使用
const placements = {
// AIチャット機能を使おうとした時
aiChat: 'ai_chat_gate',
// エクスポート機能を使おうとした時
exportData: 'export_feature_gate',
// 設定画面のUpgradeボタン
settingsUpgrade: 'settings_upgrade_tapped',
};
// 使用例
await Superwall.shared.register(placements.aiChat);なぜ使い分けるのか。ユーザーが「何をしようとしてペイウォールを見たか」によって、最も効果的な訴求が変わります。AIチャット機能への入口では「AIで〇〇ができます」という機能訴求が刺さり、設定画面からのUpgradeでは「全機能が使い放題」という包括的なメリット訴求が有効になる傾向があります。
RevenueCatとの連携:PurchaseControllerの実装
RevenueCatを購入処理に使う場合は、SuperwallにPurchaseControllerを渡します。これにより「購入処理はRevenueCat」「ペイウォール表示と分析はSuperwall」という役割分担が明確になります。
import Superwall, {
PurchaseController,
PurchaseResult,
RestorationResult,
} from '@superwall/superwall-reactnative';
import Purchases from 'react-native-purchases'; // RevenueCat
class RCPurchaseController extends PurchaseController {
// サブスクリプションの購入
async purchaseFromAppStore(productId: string): Promise<PurchaseResult> {
try {
const { customerInfo } = await Purchases.purchaseStoreProduct(
// productIdからStoreProductを取得する必要がある
// 実際の実装ではSuperwallから渡されるproductを使う
{ productIdentifier: productId } as any
);
// 購入後のサブスクリプション状態をチェック
if (
customerInfo.entitlements.active['pro'] \!== undefined
) {
return PurchaseResult.Purchased;
}
return PurchaseResult.Cancelled;
} catch (error: any) {
if (error.userCancelled) {
return PurchaseResult.Cancelled;
}
return PurchaseResult.Failed;
}
}
// 購入履歴の復元
async restorePurchases(): Promise<RestorationResult> {
try {
const customerInfo = await Purchases.restorePurchases();
if (Object.keys(customerInfo.entitlements.active).length > 0) {
return RestorationResult.Restored;
}
return RestorationResult.NothingToRestore;
} catch {
return RestorationResult.Failed;
}
}
}
// App初期化時にPurchaseControllerを渡す
const controller = new RCPurchaseController();
Superwall.configure(SUPERWALL_API_KEY, { purchaseController: controller });エンタイトルメント名('pro')は自分のRevenueCatプロジェクトに合わせて変更してください。
ダッシュボードでA/Bテストを設定する
コードの準備ができたら、Superwallダッシュボードに戻ってA/Bテストを設定します。
ペイウォールの作成
ダッシュボードの「Paywalls」から新規ペイウォールを作成します。HTMLテンプレートをベースに、CSSとJavaScriptで見た目と動作を定義できます。Superwallが提供するテンプレートを流用するのが最速です。
テスト対象の差分はシンプルに絞る点が肝心です。一度に複数の要素を変えると、どの変更が効いたか判断できなくなります。最初のテストでは「ヘッドラインのコピー」だけを変えることをおすすめします。
バリアントA(コントロール):「プレミアムにアップグレード」
バリアントB(テスト):「AIの制限を外す、今すぐ」
Campaignの設定
「Campaigns」でキャンペーンを作成し、先ほど定義したplacementにバリアントA/Bを割り当てます。分割比率は50/50から始めると統計的に比較しやすくなります。
Audienceの設定で「初回セッションのユーザーのみ」「3日以上経過したユーザーのみ」などのセグメントを指定することもできます。新規ユーザーとリピーターでは効果的なコピーが異なることが多いため、セグメント別のテストも検討する価値があります。
統計的有意性の確認
テスト結果を早まって判断しない点が肝心です。Superwallダッシュボードは信頼区間と統計的有意性を表示しますが、サンプルサイズが小さいうちは誤った結論を引き起こしやすいです。
一般的なガイドライン:
- 最低でも各バリアント100〜200のペイウォール表示を確保してから判断する
- p値が0.05未満になるまでテストを続ける
- テスト期間は最低1週間(週の曜日でユーザー行動が変わるため)
SuperwallのイベントをAnalyticsに連携する
Superwallが発火するイベントをMixpanelやAmplitudeに送信することで、ペイウォール以外のユーザー行動との相関を分析できます。
import Superwall, {
SuperwallEventInfo,
SuperwallDelegate,
} from '@superwall/superwall-reactnative';
import { Mixpanel } from 'mixpanel-react-native'; // Mixpanelの例
class AnalyticsDelegate extends SuperwallDelegate {
async handleSuperwallEvent(eventInfo: SuperwallEventInfo): Promise<void> {
// Superwallが発火するイベントをMixpanelに転送
const { event } = eventInfo;
switch (event.type) {
case 'paywallOpen':
Mixpanel.track('Paywall Viewed', {
placement: event.paywallInfo.identifier,
experiment: event.paywallInfo.experiment?.id,
variant: event.paywallInfo.experiment?.variant.id,
});
break;
case 'transactionComplete':
Mixpanel.track('Purchase Completed', {
placement: event.paywallInfo.identifier,
productId: event.transaction?.productIdentifier,
amount: event.transaction?.price,
});
break;
case 'paywallClose':
Mixpanel.track('Paywall Dismissed', {
placement: event.paywallInfo.identifier,
closedByUser: true,
});
break;
}
}
}
// delegateを設定
Superwall.shared.delegate = new AnalyticsDelegate();よくある実装のつまずきポイント
実際にSuperwallを導入した開発者がぶつかりやすい問題を3つ取り上げます。
1. Development Buildなのに広告が表示されない
SuperwallはAPIキーに対応した「Paywalls」が存在しないと何も表示しません。ダッシュボードで作成したペイウォールが Active 状態になっているか、また該当のplacementにキャンペーンが紐付いているかを確認してください。
2. テスト環境で毎回同じバリアントが出る
Superwallはユーザー識別子でバリアントを固定します。シミュレーターやテスト端末で別のバリアントを確認したい場合は、Superwall.shared.reset() を呼ぶかダッシュボードのPreviewモードを使います。
3. RevenueCat連携後に二重課金リスクが心配
PurchaseControllerを適切に実装していれば、購入処理はRevenueCatが1回だけ行います。Superwallは「どのペイウォールで購入されたか」を追跡するだけで、課金処理自体には関与しません。ただしPurchaseResultの返し方を誤ると、Superwallが購入完了と判断できず次のステップに進まないため、エラーハンドリングは丁寧に実装してください。
全体を振り返って:データ駆動でペイウォールを改善する
Superwallを使うことで、ペイウォールの改善が「感覚」から「データ」に変わります。小さなコピーの変更が課金率を20〜30%改善することは珍しくありません。まずシンプルなA/Bテスト(ヘッドライン1行の差)から始めて、統計的有意差が出た段階で次のテストに進む。この繰り返しが、Rorkで作ったアプリの収益を着実に伸ばす最短経路です。
まず手を動かしてみるなら、SDKを導入してplacementを1箇所設定し、ダッシュボードのPreviewモードでペイウォールが表示されることを確認するところから始めてみてください。